summaryrefslogtreecommitdiff
path: root/src/parserfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/parserfunc.c')
-rw-r--r--src/parserfunc.c967
1 files changed, 967 insertions, 0 deletions
diff --git a/src/parserfunc.c b/src/parserfunc.c
new file mode 100644
index 0000000..edd34f6
--- /dev/null
+++ b/src/parserfunc.c
@@ -0,0 +1,967 @@
+#include <glib.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "parser.h"
+#include "parserfunc.h"
+
+/* Register error variables in ParserState structure. */
+void
+set_error(ParserState* state, gint errorno, const gchar *token)
+{
+ state->error = errorno;
+ if(token)
+ state->error_token = strdup(token);
+}
+
+/* Unused function pointer. This won't be called anytime. */
+void*
+pf_none(ParseNode* self)
+{
+ return NULL;
+}
+
+/* Set variable. */
+void*
+pf_set_var(ParseNode* self)
+{
+ MPNumber* val;
+ val = (MPNumber *) (*(self->right->evaluate))(self->right);
+ if(!val || !(self->state->set_variable))
+ {
+ if(val)
+ free(val);
+ return NULL;
+ }
+ (*(self->state->set_variable))(self->state, self->left->token->string, val);
+ return val;
+}
+
+/* Converts Number from one unit to other. */
+void*
+pf_convert_number(ParseNode* self)
+{
+ gchar* from;
+ gchar* to;
+ gint free_from = 0;
+ gint free_to = 0;
+ MPNumber tmp;
+ MPNumber* ans;
+ ans = (MPNumber *) malloc(sizeof(MPNumber));
+ if(self->left->value)
+ {
+ from = (gchar*) self->left->value;
+ free_from = 1;
+ }
+ else
+ from = self->left->token->string;
+ if(self->right->value)
+ {
+ to = (gchar*) self->right->value;
+ free_to = 1;
+ }
+ else
+ to = self->right->token->string;
+
+ if(mp_set_from_string(self->left->left->token->string, self->state->options->base, &tmp) != 0)
+ {
+ free(ans);
+ ans = NULL;
+ goto END_PF_CONVERT_NUMBER;
+ }
+ if(!(self->state->convert))
+ {
+ free(ans);
+ ans = NULL;
+ goto END_PF_CONVERT_NUMBER;
+ }
+ if(!(*(self->state->convert))(self->state, &tmp, from, to, ans))
+ {
+ set_error(self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL);
+ free(ans);
+ ans = NULL;
+ }
+END_PF_CONVERT_NUMBER:
+ if(free_from)
+ {
+ g_free(self->left->value);
+ self->left->value = NULL;
+ }
+ if(free_to)
+ {
+ g_free(self->right->value);
+ self->right->value = NULL;
+ }
+ return ans;
+}
+
+/* Conversion rate. */
+void*
+pf_convert_1(ParseNode* self )
+{
+ gchar* from;
+ gchar* to;
+ gint free_from = 0;
+ gint free_to = 0;
+ MPNumber tmp;
+ MPNumber* ans;
+ ans = (MPNumber *) malloc(sizeof(MPNumber));
+ if(self->left->value)
+ {
+ from = (gchar*) self->left->value;
+ free_from = 1;
+ }
+ else
+ from = self->left->token->string;
+ if(self->right->value)
+ {
+ to = (gchar*) self->right->value;
+ free_to = 1;
+ }
+ else
+ to = self->right->token->string;
+ mp_set_from_integer(1, &tmp);
+ if(!(self->state->convert))
+ {
+ free(ans);
+ return NULL;
+ }
+ if(!(*(self->state->convert))(self->state, &tmp, from, to, ans))
+ {
+ set_error(self->state, PARSER_ERR_UNKNOWN_CONVERSION, NULL);
+ free(ans);
+ ans = NULL;
+ }
+ if(free_from)
+ {
+ g_free(self->left->value);
+ self->left->value = NULL;
+ }
+ if(free_to)
+ {
+ g_free(self->right->value);
+ self->right->value = NULL;
+ }
+ return ans;
+}
+
+/* Join source unit and power. */
+gchar*
+pf_make_unit(gchar* source, gchar* power)
+{
+ return g_strjoin(NULL, source, power, NULL);
+}
+
+static gchar *
+utf8_next_char(const gchar *c)
+{
+ c++;
+ while((*c & 0xC0) == 0x80)
+ c++;
+ return(gchar *) c;
+}
+
+/* Get value of variable. */
+void*
+pf_get_variable(ParseNode* self)
+{
+ gint result = 0;
+
+ const gchar *c, *next;
+ gchar *buffer;
+ MPNumber value;
+
+ MPNumber t;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+
+ if(!(self->state->get_variable))
+ {
+ free(ans);
+ return NULL;
+ }
+
+ /* If defined, then get the variable */
+ if((*(self->state->get_variable))(self->state, self->token->string, ans))
+ {
+ return ans;
+ }
+
+ /* If has more than one character then assume a multiplication of variables */
+ if(utf8_next_char(self->token->string)[0] != '\0')
+ {
+ result = 1;
+ buffer = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string));
+ mp_set_from_integer(1, &value);
+ for(c = self->token->string; *c != '\0'; c = next)
+ {
+ next = utf8_next_char(c);
+ snprintf(buffer, next - c + 1, "%s", c);
+ if(!(*(self->state->get_variable))(self->state, buffer, &t))
+ {
+ result = 0;
+ break;
+ }
+ mp_multiply(&value, &t, &value);
+ }
+ free(buffer);
+ if(result)
+ mp_set_from_mp(&value, ans);
+ }
+ if(!result)
+ {
+ free (ans);
+ ans = NULL;
+ set_error(self->state, PARSER_ERR_UNKNOWN_VARIABLE, self->token->string);
+ }
+ return ans;
+}
+
+/* Get value of variable with power. */
+void*
+pf_get_variable_with_power(ParseNode* self)
+{
+ gint result = 0;
+ gint pow;
+
+ const gchar *c, *next;
+ gchar *buffer;
+ MPNumber value;
+
+ MPNumber t;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ pow = super_atoi(((LexerToken*) self->value)->string);
+
+ /* No need to free the memory. It is allocated and freed somewhere else. */
+ self->value = NULL;
+
+ if(!(self->state->get_variable))
+ {
+ free(ans);
+ return NULL;
+ }
+
+ /* If defined, then get the variable */
+ if((*(self->state->get_variable))(self->state, self->token->string, ans))
+ {
+ mp_xpowy_integer(ans, pow, ans);
+ return ans;
+ }
+
+ /* If has more than one character then assume a multiplication of variables */
+ if(utf8_next_char(self->token->string)[0] != '\0')
+ {
+ result = 1;
+ buffer = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string));
+ mp_set_from_integer(1, &value);
+ for(c = self->token->string; *c != '\0'; c = next)
+ {
+ next = utf8_next_char(c);
+ snprintf(buffer, next - c + 1, "%s", c);
+ if(!(*(self->state->get_variable))(self->state, buffer, &t))
+ {
+ result = 0;
+ break;
+ }
+
+ /* If last term do power */
+ if(*next == '\0')
+ mp_xpowy_integer(&t, pow, &t);
+ mp_multiply(&value, &t, &value);
+ }
+ free(buffer);
+ if(result)
+ mp_set_from_mp(&value, ans);
+ }
+ if(!result)
+ {
+ free(ans);
+ ans = NULL;
+ set_error(self->state, PARSER_ERR_UNKNOWN_VARIABLE, self->token->string);
+ }
+ return ans;
+}
+
+/* Apply function on child. */
+void*
+pf_apply_func(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!(self->state->get_function))
+ {
+ free(val);
+ free(ans);
+ return NULL;
+ }
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ if(!(*(self->state->get_function))(self->state, self->token->string, val, ans))
+ {
+ free(val);
+ free(ans);
+ set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
+ return NULL;
+ }
+ free(val);
+ return ans;
+}
+
+/* Apply function with +ve power. */
+void*
+pf_apply_func_with_power(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* tmp;
+ MPNumber* ans;
+ gint pow;
+ tmp = (MPNumber*) malloc(sizeof(MPNumber));
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!(self->state->get_function))
+ {
+ free(tmp);
+ free(ans);
+ free(val);
+ self->value = NULL;
+ return NULL;
+ }
+ if(!val)
+ {
+ free(tmp);
+ free(ans);
+ self->value = NULL;
+ return NULL;
+ }
+ if(!(*(self->state->get_function))(self->state, self->token->string, val, tmp))
+ {
+ free(tmp);
+ free(ans);
+ free(val);
+ self->value = NULL;
+ set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
+ return NULL;
+ }
+ pow = super_atoi(((LexerToken*) self->value)->string);
+ mp_xpowy_integer(tmp, pow, ans);
+ free(val);
+ free(tmp);
+ self->value = NULL;
+ return ans;
+}
+
+/* Apply function with -ve power. */
+void*
+pf_apply_func_with_npower(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* tmp;
+ MPNumber* ans;
+ gint pow;
+ gchar* inv_name;
+ inv_name = (gchar*) malloc(sizeof(gchar) * strlen(self->token->string) + strlen("⁻¹") + 1);
+ strcpy(inv_name, self->token->string);
+ strcat(inv_name, "⁻¹");
+ tmp = (MPNumber*) malloc(sizeof(MPNumber));
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(tmp);
+ free(inv_name);
+ free(ans);
+ self->value = NULL;
+ return NULL;
+ }
+ if(!(self->state->get_function))
+ {
+ free(tmp);
+ free(ans);
+ free(inv_name);
+ self->value = NULL;
+ return NULL;
+ }
+ if(!(*(self->state->get_function))(self->state, inv_name, val, tmp))
+ {
+ free(tmp);
+ free(ans);
+ free(val);
+ free(inv_name);
+ self->value = NULL;
+ set_error(self->state, PARSER_ERR_UNKNOWN_FUNCTION, self->token->string);
+ return NULL;
+ }
+ pow = super_atoi(((LexerToken*) self->value)->string);
+ mp_xpowy_integer(tmp, -pow, ans);
+ free(val);
+ free(tmp);
+ free(inv_name);
+ self->value = NULL;
+ return ans;
+}
+
+/* Find nth root of child. */
+void*
+pf_do_nth_root(ParseNode* self)
+{
+ MPNumber* val;
+ gint pow;
+ MPNumber* ans;
+ pow = sub_atoi(((LexerToken*) self->value)->string);
+ self->value = NULL;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_root(val, pow, ans);
+ free(val);
+ return ans;
+}
+
+/* Find sqrt of child. */
+void*
+pf_do_sqrt(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_sqrt(val, ans);
+ free(val);
+ return ans;
+}
+
+/* Find 3rd root of child. */
+void*
+pf_do_root_3(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_root(val, 3, ans);
+ free(val);
+ return ans;
+}
+
+/* Find 4th root of child. */
+void*
+pf_do_root_4(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_root(val, 4, ans);
+ free(val);
+ return ans;
+}
+
+/* Apply floor function. */
+void*
+pf_do_floor(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_floor(val, ans);
+ free(val);
+ return ans;
+}
+
+/* Apply ceiling function. */
+void* pf_do_ceiling (ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_ceiling(val, ans);
+ free(val);
+ return ans;
+}
+
+/* Round off. */
+void*
+pf_do_round(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_round(val, ans);
+ free(val);
+ return ans;
+}
+
+/* Fraction. */
+void*
+pf_do_fraction(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_fractional_part(val, ans);
+ free(val);
+ return ans;
+}
+
+/* Absolute value. */
+void*
+pf_do_abs(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_abs(val, ans);
+ free(val);
+ return ans;
+}
+
+/* Find x^y for x and y being MPNumber. */
+void*
+pf_do_x_pow_y(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* pow;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->left->evaluate))(self->left);
+ pow = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val || !pow)
+ {
+ if(val)
+ free(val);
+ if(pow)
+ free(pow);
+ free(ans);
+ return NULL;
+ }
+ mp_xpowy(val, pow, ans);
+ free(val);
+ free(pow);
+ return ans;
+}
+
+/* Find x^y for MPNumber x and integer y. */
+void*
+pf_do_x_pow_y_int(ParseNode* self)
+{
+ MPNumber* val;
+ gint pow;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->left->evaluate))(self->left);
+ pow = super_atoi(self->right->token->string);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_xpowy_integer(val, pow, ans);
+ free(val);
+ return ans;
+}
+
+/* Find factorial. */
+void*
+pf_do_factorial(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_factorial(val, ans);
+ free(val);
+ return ans;
+}
+
+/* Apply unary minus. */
+void*
+pf_unary_minus(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_invert_sign(val, ans);
+ free(val);
+ return ans;
+}
+
+/* Divide. */
+void*
+pf_do_divide(ParseNode* self)
+{
+ MPNumber* left;
+ MPNumber* right;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ left = (MPNumber*) (*(self->left->evaluate))(self->left);
+ right = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!left || !right)
+ {
+ if(left)
+ free(left);
+ if(right)
+ free(right);
+ free(ans);
+ return NULL;
+ }
+ mp_divide(left, right, ans);
+ free(left);
+ free(right);
+ return ans;
+}
+
+/* Modulus. */
+void*
+pf_do_mod(ParseNode* self)
+{
+ MPNumber* left;
+ MPNumber* right;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ left = (MPNumber*) (*(self->left->evaluate))(self->left);
+ right = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!left || !right)
+ {
+ if(left)
+ free(left);
+ if(right)
+ free(right);
+ free(ans);
+ return NULL;
+ }
+ mp_modulus_divide(left, right, ans);
+ free(left);
+ free(right);
+ return ans;
+}
+
+/* Multiply two numbers. */
+void*
+pf_do_multiply(ParseNode* self)
+{
+ MPNumber* left;
+ MPNumber* right;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ left = (MPNumber*) (*(self->left->evaluate))(self->left);
+ right = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!left || !right)
+ {
+ if(left)
+ free(left);
+ if(right)
+ free(right);
+ free(ans);
+ return NULL;
+ }
+ mp_multiply(left, right, ans);
+ free(left);
+ free(right);
+ return ans;
+}
+
+/* Subtract two numbers. */
+void*
+pf_do_subtract(ParseNode* self)
+{
+ MPNumber* left;
+ MPNumber* right;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ left = (MPNumber*) (*(self->left->evaluate))(self->left);
+ right = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!left || !right)
+ {
+ if(left)
+ free(left);
+ if(right)
+ free (right);
+ free(ans);
+ return NULL;
+ }
+ mp_subtract(left, right, ans);
+ free(left);
+ free(right);
+ return ans;
+}
+
+/* Add two numbers. */
+void*
+pf_do_add(ParseNode* self)
+{
+ MPNumber* left;
+ MPNumber* right;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ left = (MPNumber*) (*(self->left->evaluate))(self->left);
+ right = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!left || !right)
+ {
+ if(left)
+ free(left);
+ if(right)
+ free(right);
+ free(ans);
+ return NULL;
+ }
+ mp_add(left, right, ans);
+ free(left);
+ free(right);
+ return ans;
+}
+
+/*Add (x) Percentage to value. */
+void*
+pf_do_add_percent(ParseNode* self)
+{
+ MPNumber* ans;
+ MPNumber* val;
+ MPNumber* per;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->left->evaluate))(self->left);
+ per = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val || !per)
+ {
+ if(val)
+ free(val);
+ if(per)
+ free(per);
+ free(ans);
+ return NULL;
+ }
+ mp_add_integer(per, 100, per);
+ mp_divide_integer(per, 100, per);
+ mp_multiply(val, per, ans);
+ free(val);
+ free(per);
+ return ans;
+}
+
+/* Subtract (x) Percentage to value. */
+void*
+pf_do_subtract_percent(ParseNode* self)
+{
+ MPNumber* ans;
+ MPNumber* val;
+ MPNumber* per;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->left->evaluate))(self->left);
+ per = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val || !per)
+ {
+ if(val)
+ free(val);
+ if(per)
+ free(per);
+ free(ans);
+ return NULL;
+ }
+ mp_add_integer(per, -100, per);
+ mp_divide_integer(per, -100, per);
+ mp_multiply(val, per, ans);
+ free(val);
+ free(per);
+ return ans;
+}
+
+/* Converts a constant into percentage. */
+void*
+pf_do_percent(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ mp_divide_integer(val, 100, ans);
+ free(val);
+ return ans;
+}
+
+/* NOT. */
+void*
+pf_do_not(ParseNode* self)
+{
+ MPNumber* val;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ val = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!val)
+ {
+ free(ans);
+ return NULL;
+ }
+ if(!mp_is_overflow(val, self->state->options->wordlen))
+ {
+ set_error(self->state, PARSER_ERR_OVERFLOW, NULL);
+ free(ans);
+ ans = NULL;
+ }
+ mp_not(val, self->state->options->wordlen, ans);
+ free(val);
+ return ans;
+}
+
+/* AND. */
+void*
+pf_do_and(ParseNode* self)
+{
+ MPNumber* left;
+ MPNumber* right;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ left = (MPNumber*) (*(self->left->evaluate))(self->left);
+ right = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!left || !right)
+ {
+ if(left)
+ free(left);
+ if(right)
+ free(right);
+ free(ans);
+ return NULL;
+ }
+ mp_and(left, right, ans);
+ free(left);
+ free(right);
+ return ans;
+}
+
+/* OR. */
+void*
+pf_do_or(ParseNode* self)
+{
+ MPNumber* left;
+ MPNumber* right;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ left = (MPNumber*) (*(self->left->evaluate))(self->left);
+ right = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!left || !right)
+ {
+ if(left)
+ free(left);
+ if(right)
+ free(right);
+ free(ans);
+ return NULL;
+ }
+ mp_or(left, right, ans);
+ free(left);
+ free(right);
+ return ans;
+}
+
+/* XOR. */
+void*
+pf_do_xor(ParseNode* self)
+{
+ MPNumber* left;
+ MPNumber* right;
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ left = (MPNumber*) (*(self->left->evaluate))(self->left);
+ right = (MPNumber*) (*(self->right->evaluate))(self->right);
+ if(!left || !right)
+ {
+ if(left)
+ free(left);
+ if(right)
+ free(right);
+ free(ans);
+ return NULL;
+ }
+ mp_xor(left, right, ans);
+ free(left);
+ free(right);
+ return ans;
+}
+
+/* Constant value. Convert into MPNumber and return. */
+void*
+pf_constant(ParseNode* self)
+{
+ MPNumber* ans;
+ ans = (MPNumber*) malloc(sizeof(MPNumber));
+ if(mp_set_from_string(self->token->string, self->state->options->base, ans) != 0)
+ {
+ /* This should never happen, as l_check_if_number() has already passed the string once. */
+ /* If the code reaches this point, something is really wrong. X( */
+ free(ans);
+ set_error(self->state, PARSER_ERR_INVALID, self->token->string);
+ return NULL;
+ }
+ return ans;
+}
+