/*
	Copyright 2010-2011 Leszek Dubiel <leszek@dubiel.pl>

	This file is part of Treep.

	Treep is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	Treep is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with Treep. If not, see <http://www.gnu.org/licenses/>.
*/

#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <ctype.h>
#include <math.h>
#include <float.h>
#include <string.h>
#include <limits.h>
#define __USE_XOPEN
#include <time.h>
#include <regex.h>
#include <gc/gc.h>
#include "tree.h"
#include "data.h"
#include "core.h"

/* global vairable to remember data put back from reading */
struct vlue *back = 0;

/* value of last parameter */
struct vlue *core_do(size_t vc, struct vlue **vv)
{
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc < 1) {
		fputs("Can not compute \"do\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return vv[vc - 1];
}

/* check if function is defined */
struct vlue *core_df(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"df\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NAME) {
		fputs("Can not compute \"df\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	/* search global "func" for function definition */
	v->data.bool = tree_search(func, vv[0]->data.name) != 0;
	return v;
}

/* check if value is of given type */
struct vlue *core_is(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"is\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NAME) {
		fputs("Can not compute \"is\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	if (strcmp(vv[0]->data.name, "void") == 0) {
		v->data.bool = vv[1]->type == VOID;
	} else if (strcmp(vv[0]->data.name, "spac") == 0) {
		v->data.bool = vv[1]->type == SPAC;
	} else if (strcmp(vv[0]->data.name, "tabu") == 0) {
		v->data.bool = vv[1]->type == TABU;
	} else if (strcmp(vv[0]->data.name, "line") == 0) {
		v->data.bool = vv[1]->type == LINE;
	} else if (strcmp(vv[0]->data.name, "lpar") == 0) {
		v->data.bool = vv[1]->type == LPAR;
	} else if (strcmp(vv[0]->data.name, "rpar") == 0) {
		v->data.bool = vv[1]->type == RPAR;
	} else if (strcmp(vv[0]->data.name, "numb") == 0) {
		v->data.bool = vv[1]->type == NUMB;
	} else if (strcmp(vv[0]->data.name, "name") == 0) {
		v->data.bool = vv[1]->type == NAME;
	} else if (strcmp(vv[0]->data.name, "text") == 0) {
		v->data.bool = vv[1]->type == TEXT;
	} else if (strcmp(vv[0]->data.name, "bool") == 0) {
		v->data.bool = vv[1]->type == BOOL;
	} else if (strcmp(vv[0]->data.name, "node") == 0) {
		v->data.bool = vv[1]->type == NODE;
	} else if (strcmp(vv[0]->data.name, "tree") == 0) {
		v->data.bool = vv[1]->type == TREE;
	} else {
		fprintf(stderr, "Can not compute \"is\" call. Wrong name of type \"%s\".\n", vv[0]->data.name);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* increment number by one */
struct vlue *core_inc(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"inc\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"inc\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(vv[0]->data.numb + 1.0L);
	return v;
}

/* decrement number by one */
struct vlue *core_dec(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"dec\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"dec\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(vv[0]->data.numb - 1.0L);
	return v;
}

/* add two or more numbers */
struct vlue *core_add(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"add\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB || vv[1]->type != NUMB) {
		fputs("Can not compute \"add\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(vv[0]->data.numb + vv[1]->data.numb);
	return v;
}

/* subtract two or more numbers */
struct vlue *core_sub(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"sub\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB || vv[1]->type != NUMB) {
		fputs("Can not compute \"sub\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(vv[0]->data.numb - vv[1]->data.numb);
	return v;
}

/* multiply two or more numbers */
struct vlue *core_mul(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"mul\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB || vv[1]->type != NUMB) {
		fputs("Can not compute \"mul\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(vv[0]->data.numb * vv[1]->data.numb);
	return v;
}

/* divide two or more numbers */
struct vlue *core_div(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"div\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB || vv[1]->type != NUMB) {
		fputs("Can not compute \"div\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[1]->data.numb == 0.0L) {
		fputs("Can not compute \"div\" call. Division by zero.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(vv[0]->data.numb / vv[1]->data.numb);
	return v;
}

/* round number to the nearest integer */
struct vlue *core_rnd(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"rnd\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"rnd\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(roundl(vv[0]->data.numb));
	return v;
}

/* compute floor of the number */
struct vlue *core_flo(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"flo\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"flo\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(floorl(vv[0]->data.numb));
	return v;
}

/* compute ceiling of the number */
struct vlue *core_cil(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"cil\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"cil\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(ceill(vv[0]->data.numb));
	return v;
}

/* minimum number or minimum of two or more numbers */
struct vlue *core_min(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc == 0) {
		v = GC_malloc(sizeof(struct vlue));
		if (v == 0) {
			fputs("Out of memory.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->type = NUMB;
		v->data.numb = numb_norm(powl(10.0L, 1 - LDBL_DIG));
	} else if (vc == 2) {
		if (vv[0]->type != NUMB || vv[1]->type != NUMB) {
			fputs("Can not compute \"min\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v = vv[0]->data.numb < vv[1]->data.numb ? vv[0] : vv[1];
	} else {
		fputs("Can not compute \"min\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* maximum number or maximum of two or more numbers */
struct vlue *core_max(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc == 0) {
		v = GC_malloc(sizeof(struct vlue));
		if (v == 0) {
			fputs("Out of memory.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->type = NUMB;
		v->data.numb = numb_norm(powl(10.0L, LDBL_DIG - 1) - 0.1L);
	} else if (vc == 2) {
		if (vv[0]->type != NUMB || vv[1]->type != NUMB) {
			fputs("Can not compute \"max\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v = vv[0]->data.numb > vv[1]->data.numb ? vv[0] : vv[1];
	} else {
		fputs("Can not compute \"max\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* opossite of number (negation of number) */
struct vlue *core_ops(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"ops\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"ops\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(-vv[0]->data.numb);
	return v;
}

/* absolute value of number */
struct vlue *core_abs(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"abs\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"abs\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(vv[0]->data.numb < 0.0L ? -vv[0]->data.numb : vv[0]->data.numb);
	return v;
}

/* zero or check if zero */
struct vlue *core_zer(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc == 0) {
		v = GC_malloc(sizeof(struct vlue));
		if (v == 0) {
			fputs("Out of memory.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->type = NUMB;
		v->data.numb = 0.0L;
	} else if (vc == 1) {
		if (vv[0]->type != NUMB) {
			fputs("Can not compute \"zer\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v = GC_malloc(sizeof(struct vlue));
		if (v == 0) {
			fputs("Out of memory.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->type = BOOL;
		v->data.bool = vv[0]->data.numb == 0.0L;
	} else {
		fputs("Can not compute \"zer\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* check if number is positive */
struct vlue *core_pos(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"pos\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"pos\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = vv[0]->data.numb > 0.0L;
	return v;
}

/* check if number is negative */
struct vlue *core_neg(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"neg\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"neg\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = vv[0]->data.numb < 0.0L;
	return v;
}

/* check if numbers are equal */
struct vlue *core_equ(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"equ\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB || vv[1]->type != NUMB) {
		fputs("Can not compute \"equ\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = vv[0]->data.numb == vv[1]->data.numb;
	return v;
}

/* check if one number is greater than another */
struct vlue *core_gre(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"gre\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB || vv[1]->type != NUMB) {
		fputs("Can not compute \"gre\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = vv[0]->data.numb > vv[1]->data.numb;
	return v;
}

/* check is one number is less then another */
struct vlue *core_les(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"les\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB || vv[1]->type != NUMB) {
		fputs("Can not compute \"les\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = vv[0]->data.numb < vv[1]->data.numb;
	return v;
}

/* boolean true */
struct vlue *core_yes(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"yes\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = 0 == 0;
	return v;
}

/* boolean false */
struct vlue *core_no(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"no\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = 0 != 0;
	return v;
}

/* negation of boolean value */
struct vlue *core_not(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"not\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != BOOL) {
		fputs("Can not compute \"not\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = !vv[0]->data.bool;
	return v;
}

/* conjunction of two or more boolean values */
struct vlue *core_and(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"and\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != BOOL || vv[1]->type != BOOL) {
		fputs("Can not compute \"and\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = vv[0]->data.bool && vv[1]->data.bool;
	return v;
}


/* alternative of two or more boolean values */
struct vlue *core_or(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"or\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != BOOL || vv[1]->type != BOOL) {
		fputs("Can not compute \"or\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = vv[0]->data.bool || vv[1]->data.bool;
	return v;
}

/* convert text to number */
struct vlue *core_numb(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"numb\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	if (vv[0]->type == TEXT) {
		v->data.numb = text_numb(vv[0]->data.text);
	} else {
		fputs("Can not compute \"numb\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* convert text to name */
struct vlue *core_name(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *p;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"name\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NAME;
	if (vv[0]->type == TEXT) {
		p = vv[0]->data.text;
		if (!isalpha(*p)) {
			fputs("Can not compute \"name\" call. Wrong text format.\n", stderr);
			exit(EXIT_FAILURE);
		}
		while (*p != '\0') {
			if (*p == '_')
				p++;
			if (!isalnum(*p)) {
				fputs("Can not compute \"name\" call. Wrong text format.\n", stderr);
				exit(EXIT_FAILURE);
			}
			p++;
		}
		v->data.name = vv[0]->data.text;
	} else if (vv[0]->type == NODE) {
		v->data.name = vv[0]->data.node->name;
	} else {
		fputs("Can not compute \"name\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* convert number or name to text */
struct vlue *core_text(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"text\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TEXT;
	if (vv[0]->type == NUMB) {
		v->data.text = numb_text(vv[0]->data.numb);
	} else if (vv[0]->type == NAME) {
		v->data.text = vv[0]->data.name;
	} else {
		fputs("Can not compute \"text\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* length of name or text */
struct vlue *core_leng(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"leng\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	if (vv[0]->type == NAME) {
		v->data.numb = strlen(vv[0]->data.name);
	} else if (vv[0]->type == TEXT) {
		v->data.numb = strlen(vv[0]->data.text);
	} else {
		fputs("Can not compute \"leng\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* check if names or texts are the same */
struct vlue *core_same(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"same\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	if (vv[0]->type == NAME) {
		if (vv[1]->type != NAME) {
			fputs("Can not compute \"same\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->data.bool = strcmp(vv[0]->data.name, vv[1]->data.name) == 0;
	} else if (vv[0]->type == TEXT) {
		if (vv[1]->type != TEXT) {
			fputs("Can not compute \"same\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->data.bool = strcmp(vv[0]->data.text, vv[1]->data.text) == 0;
	} else {
		fputs("Can not compute \"same\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* check one name or text sorts before another */
struct vlue *core_bfor(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"bfor\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	if (vv[0]->type == NAME) {
		if (vv[1]->type != NAME) {
			fputs("Can not compute \"bfor\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->data.bool = strcmp(vv[0]->data.name, vv[1]->data.name) < 0;
	} else if (vv[0]->type == TEXT) {
		if (vv[1]->type != TEXT) {
			fputs("Can not compute \"bfor\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->data.bool = strcmp(vv[0]->data.text, vv[1]->data.text) < 0;
	} else {
		fputs("Can not compute \"bfor\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* check one name or text sorts after another */
struct vlue *core_aftr(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"aftr\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	if (vv[0]->type == NAME) {
		if (vv[1]->type != NAME) {
			fputs("Can not compute \"aftr\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->data.bool = strcmp(vv[0]->data.name, vv[1]->data.name) > 0;
	} else if (vv[0]->type == TEXT) {
		if (vv[1]->type != TEXT) {
			fputs("Can not compute \"aftr\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->data.bool = strcmp(vv[0]->data.text, vv[1]->data.text) > 0;
	} else {
		fputs("Can not compute \"aftr\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* escape text */
struct vlue *core_escp(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	size_t l;
	char *s, *d;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"escp\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TEXT) {
		fputs("Can not compute \"escp\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TEXT;
	l = strlen(vv[0]->data.text);
	if (l > (SIZE_MAX - 1) / 2) {
		fputs("Limit reached.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->data.text = GC_malloc(2 * l + 1);
	if (v->data.text == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	for (s = vv[0]->data.text, d = v->data.text; *s != '\0'; s++, d++) {
		if (*s == '"' || *s == '\\') {
			*d = '\\';
			d++;
		}
		*d = *s;
	}
	*d = '\0';
	return v;
}

/* unescape text */
struct vlue *core_unes(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *s, *d;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"unes\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TEXT) {
		fputs("Can not compute \"unes\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TEXT;
	v->data.text = GC_malloc(strlen(vv[0]->data.name) + 1);
	if (v->data.text == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	for (s = vv[0]->data.text, d = v->data.text; *s != '\0'; s++, d++) {
		if (*s == '\\') {
			s++;
			if (*s != '"' && *s != '\\') {
				fputs("Can not compute \"unes\" call. Wrong escape sequence.\n", stderr);
				exit(EXIT_FAILURE);
			}
		}
		*d = *s;
	}
	*d = '\0';
	return v;
}

/* text or name in upppercase */
struct vlue *core_uppr(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *p, *q;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"uppr\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type == NAME) {
		p = vv[0]->data.name;
	} else if (vv[0]->type == TEXT) {
		p = vv[0]->data.text;
	} else {
		fputs("Can not compute \"uppr\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TEXT;
	v->data.text = GC_malloc(strlen(p) + 1);
	for (q = v->data.text; *p != 0; p++, q++)
		*q = toupper(*p);
	*q = '\0';
	return v;
}

/* text or name in lowercase */
struct vlue *core_lowr(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *p, *q;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"lowr\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type == NAME) {
		p = vv[0]->data.name;
	} else if (vv[0]->type == TEXT) {
		p = vv[0]->data.text;
	} else {
		fputs("Can not compute \"lowr\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TEXT;
	v->data.text = GC_malloc(strlen(p) + 1);
	for (q = v->data.text; *p != 0; p++, q++)
		*q = tolower(*p);
	*q = '\0';
	return v;
}

/* beginning of name or text */
struct vlue *core_head(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *s, *d;
	size_t i, l;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"head\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type == NAME) {
		s = vv[0]->data.name;
	} else if (vv[0]->type == TEXT) {
		s = vv[0]->data.text;
	} else {
		fputs("Can not compute \"head\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[1]->type != NUMB) {
		fputs("Can not compute \"head\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (roundl(vv[1]->data.numb) != vv[1]->data.numb) {
		fputs("Can not compute \"head\" call. Index not integer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	l = strlen(s);
	if (vv[1]->data.numb < 0 || vv[1]->data.numb > l) {
		fputs("Can not compute \"head\" call. Index out of range.\n", stderr);
		exit(EXIT_FAILURE);
	}
	i = vv[1]->data.numb;
	d = GC_malloc(i + 1);
	if (d == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	strncpy(d, s, i);
	d[i] = '\0';
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = vv[0]->type;
	if (vv[0]->type == NAME) {
		v->data.name = d;
		if (!isalpha(d[0]) || !isalnum(d[i - 1])) {
			/* function will not produce valid name as expected */
			fputs("Can not compute \"head\" call. Not a name produced.\n", stderr);
			exit(EXIT_FAILURE);
		}
	} else {
		v->data.text = d;
	}
	return v;
}

/* end of name or text */
struct vlue *core_tail(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *s, *d;
	size_t i, l;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"tail\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type == NAME) {
		s = vv[0]->data.name;
	} else if (vv[0]->type == TEXT) {
		s = vv[0]->data.text;
	} else {
		fputs("Can not compute \"tail\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (roundl(vv[1]->data.numb) != vv[1]->data.numb) {
		fputs("Can not compute \"tail\" call. Index not integer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	l = strlen(s);
	if (vv[1]->data.numb < 0 || vv[1]->data.numb > l) {
		fputs("Can not compute \"tail\" call. Index out of range.\n", stderr);
		exit(EXIT_FAILURE);
	}
	i = vv[1]->data.numb;
	d = GC_malloc(i + 1);
	if (d == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	strncpy(d, s + l - i, i);
	d[i] = '\0';
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = vv[0]->type;
	if (vv[0]->type == NAME) {
		v->data.name = d;
		if (!isalpha(d[0]) || !isalnum(d[i - 1])) {
			/* function will not produce valid name as expected */
			fputs("Can not compute \"tail\" call. Not a name produced.\n", stderr);
			exit(EXIT_FAILURE);
		}
	} else {
		v->data.text = d;
	}
	return v;
}

/* join names or texts */
struct vlue *core_join(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	size_t k, l;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"join\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type == NAME) {
		v->type = NAME;
		if (vv[1]->type != NAME) {
			fputs("Can not compute \"join\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		l = strlen(vv[0]->data.name);
		k = strlen(vv[1]->data.name);
		if (l > SIZE_MAX - 1 - k - 1) {
			fputs("Limit reached.\n", stderr);
			exit(EXIT_FAILURE);
		}
		/* all chars from first string, underline, all chars 
		 * from second string, null char */
		v->data.name = GC_malloc(l + 1 + k + 1);
		if (v->data.name == 0) {
			fputs("Out of memory.\n", stderr);
			exit(EXIT_FAILURE);
		}
		strcpy(v->data.name, vv[0]->data.name);
		v->data.name[l] = '_';
		strcpy(v->data.name + l + 1, vv[1]->data.name);
	} else if (vv[0]->type == TEXT) {
		v->type = TEXT;
		if (vv[1]->type != TEXT) {
			fputs("Can not compute \"join\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		l = strlen(vv[0]->data.text);
		k = strlen(vv[1]->data.text);
		if (l > SIZE_MAX - k - 1) {
			fputs("Limit reached.\n", stderr);
			exit(EXIT_FAILURE);
		}
		/* all chars from first string, all chars from seconds 
		 * string, null char */
		v->data.text = GC_malloc(l + k + 1);
		if (v->data.text == 0) {
			fputs("Out of memory.\n", stderr);
			exit(EXIT_FAILURE);
		}
		strcpy(v->data.text, vv[0]->data.text);
		strcpy(v->data.text + l, vv[1]->data.text);
	} else {
		fputs("Can not compute \"join\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* check if one name or text is a part of another name or text */
struct vlue *core_part(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *a, *b;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"part\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type == NAME && vv[1]->type == NAME) {
		a = vv[0]->data.name;
		b = vv[1]->data.name;
	} else if (vv[0]->type == TEXT && vv[1]->type == TEXT) {
		a = vv[0]->data.text;
		b = vv[1]->data.text;
	} else {
		fputs("Can not compute \"part\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = strstr(a, b) != 0;
	return v;
}

/* find index of one name or text in another name or text */
struct vlue *core_indx(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *a, *b, *c;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"indx\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type == NAME && vv[1]->type == NAME) {
		a = vv[0]->data.name;
		b = vv[1]->data.name;
	} else if (vv[0]->type == TEXT && vv[1]->type == TEXT) {
		a = vv[0]->data.text;
		b = vv[1]->data.text;
	} else {
		fputs("Can not compute \"indx\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	c = strstr(a, b);
	if (c == 0) {
		fputs("Can not compute \"indx\" call. Part not valid.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->data.numb = c - a;
	return v;
}

/* test if name or text is valid regex (pattern) */
struct vlue *core_ptrn(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *p;
	regex_t r;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"ptrn\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* text to search in */
	if (vv[0]->type == NAME) {
		p = vv[0]->data.name;
	} else if (vv[0]->type == TEXT) {
		p = vv[0]->data.text;
	} else {
		fputs("Can not compute \"ptrn\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* check if pattern compiles */
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = regcomp(&r, p, REG_EXTENDED) == 0;
	regfree(&r);
	return v;
}

/* how many subexpressions pattern has */
struct vlue *core_subs(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *p;
	regex_t r;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"subs\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* text to search in */
	if (vv[0]->type == NAME) {
		p = vv[0]->data.name;
	} else if (vv[0]->type == TEXT) {
		p = vv[0]->data.text;
	} else {
		fputs("Can not compute \"subs\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* compile pattern */
	if (regcomp(&r, p, REG_EXTENDED) != 0) {
		fputs("Can not compute \"subs\" call. Pattern not valid.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* return number of subs */
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = r.re_nsub;
	regfree(&r);
	return v;
}

/* test if name or text matches regex */
struct vlue *core_mtch(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *t, *p;
	size_t n;
	regex_t r;
	regmatch_t *m;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2 && vc != 3) {
		fputs("Can not compute \"mtch\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* text to search in */
	if (vv[0]->type == NAME) {
		t = vv[0]->data.name;
	} else if (vv[0]->type == TEXT) {
		t = vv[0]->data.text;
	} else {
		fputs("Can not compute \"mtch\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* regex */
	if (vv[1]->type == NAME) {
		p = vv[1]->data.name;
	} else if (vv[1]->type == TEXT) {
		p = vv[1]->data.text;
	} else {
		fputs("Can not compute \"mtch\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* compile regex */
	if (regcomp(&r, p, REG_EXTENDED) != 0) {
		fputs("Can not compute \"mtch\" call. Pattern not valid.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* allocate subexpressions */
	if (r.re_nsub + 1 > SIZE_MAX / sizeof(regmatch_t)) {
		fputs("Limit reached.\n", stderr);
		exit(EXIT_FAILURE);
	}
	m = malloc((r.re_nsub + 1) * sizeof(regmatch_t));
	if (m == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* which subexpression to look at */
	if (vc == 2) {
		n = 0;
	} else {
		if (vv[2]->type != NUMB) {
			fputs("Can not compute \"mtch\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		if (roundl(vv[2]->data.numb) != vv[2]->data.numb) {
			fputs("Can not compute \"mtch\" call. Index not integer.\n", stderr);
			exit(EXIT_FAILURE);
		}
		if (vv[2]->data.numb < 1 || vv[2]->data.numb > r.re_nsub) {
			fputs("Can not compute \"mtch\" call. Index out of range.\n", stderr);
			exit(EXIT_FAILURE);
		}
		n = vv[2]->data.numb;
	}
	/* initialize value to true */
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = 0 == 0;
	/* execute regular expression */
	if (regexec(&r, t, r.re_nsub + 1, m, 0) != 0) {
		/* doesn't match at all */
		v->data.bool = 0 != 0;
	} else if (m[n].rm_so < 0 || m[n].rm_eo < 0) {
		/* selected subespression didn't catch */
		v->data.bool = 0 != 0;
	}
	free(m);
	regfree(&r);
	return v;
}

/* starting index of matched substring */
struct vlue *core_msta(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *t, *p;
	size_t n;
	regex_t r;
	regmatch_t *m;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2 && vc != 3) {
		fputs("Can not compute \"msta\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* text to search in */
	if (vv[0]->type == NAME) {
		t = vv[0]->data.name;
	} else if (vv[0]->type == TEXT) {
		t = vv[0]->data.text;
	} else {
		fputs("Can not compute \"msta\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* regex */
	if (vv[1]->type == NAME) {
		p = vv[1]->data.name;
	} else if (vv[1]->type == TEXT) {
		p = vv[1]->data.text;
	} else {
		fputs("Can not compute \"msta\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* compile regex */
	if (regcomp(&r, p, REG_EXTENDED) != 0) {
		fputs("Can not compute \"msta\" call. Pattern not valid.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* allocate subexpressions */
	if (r.re_nsub + 1 > SIZE_MAX / sizeof(regmatch_t)) {
		fputs("Limit reached.\n", stderr);
		exit(EXIT_FAILURE);
	}
	m = malloc((r.re_nsub + 1) * sizeof(regmatch_t));
	if (m == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* which subexpression to look at */
	if (vc == 2) {
		n = 0;
	} else {
		if (vv[2]->type != NUMB) {
			fputs("Can not compute \"msta\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		if (roundl(vv[2]->data.numb) != vv[2]->data.numb) {
			fputs("Can not compute \"msta\" call. Index not integer.\n", stderr);
			exit(EXIT_FAILURE);
		}
		if (vv[2]->data.numb < 1 || vv[2]->data.numb > r.re_nsub) {
			fputs("Can not compute \"msta\" call. Index out of range.\n", stderr);
			exit(EXIT_FAILURE);
		}
		n = vv[2]->data.numb;
	}
	/* execute regular expression */
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	if (regexec(&r, t, r.re_nsub + 1, m, 0) != 0) {
		/* doesn't match at all */
		fputs("Can not compute \"msta\" call. Pattern does not match.\n", stderr);
		exit(EXIT_FAILURE);
	} else if (m[n].rm_so < 0 || m[n].rm_eo < 0) {
		/* selected subespression didn't catch */
		fputs("Can not compute \"msta\" call. Subpattern does not match.\n", stderr);
		exit(EXIT_FAILURE);
	} else {
		v->data.numb = m[n].rm_so;
	}
	free(m);
	regfree(&r);
	return v;
}

/* starting index of matched substring */
struct vlue *core_mend(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	char *t, *p;
	size_t n;
	regex_t r;
	regmatch_t *m;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2 && vc != 3) {
		fputs("Can not compute \"mend\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* text to search in */
	if (vv[0]->type == NAME) {
		t = vv[0]->data.name;
	} else if (vv[0]->type == TEXT) {
		t = vv[0]->data.text;
	} else {
		fputs("Can not compute \"mend\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* regex */
	if (vv[1]->type == NAME) {
		p = vv[1]->data.name;
	} else if (vv[1]->type == TEXT) {
		p = vv[1]->data.text;
	} else {
		fputs("Can not compute \"mend\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* compile regex */
	if (regcomp(&r, p, REG_EXTENDED) != 0) {
		fputs("Can not compute \"mend\" call. Pattern not valid.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* allocate subexpressions */
	if (r.re_nsub + 1 > SIZE_MAX / sizeof(regmatch_t)) {
		fputs("Limit reached.\n", stderr);
		exit(EXIT_FAILURE);
	}
	m = malloc((r.re_nsub + 1) * sizeof(regmatch_t));
	if (m == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* which subexpression to look at */
	if (vc == 2) {
		n = 0;
	} else {
		if (vv[2]->type != NUMB) {
			fputs("Can not compute \"mend\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		if (roundl(vv[2]->data.numb) != vv[2]->data.numb) {
			fputs("Can not compute \"mend\" call. Index not integer.\n", stderr);
			exit(EXIT_FAILURE);
		}
		if (vv[2]->data.numb < 1 || vv[2]->data.numb > r.re_nsub) {
			fputs("Can not compute \"mend\" call. Index out of range.\n", stderr);
			exit(EXIT_FAILURE);
		}
		n = vv[2]->data.numb;
	}
	/* execute regular expression */
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	if (regexec(&r, t, r.re_nsub + 1, m, 0) != 0) {
		/* doesn't match at all */
		fputs("Can not compute \"mend\" call. Pattern does not match.\n", stderr);
		exit(EXIT_FAILURE);
	} else if (m[n].rm_so < 0 || m[n].rm_eo < 0) {
		/* selected subespression didn't catch */
		fputs("Can not compute \"mend\" call. Subpattern does not match.\n", stderr);
		exit(EXIT_FAILURE);
	} else {
		v->data.numb = m[n].rm_eo;
	}
	free(m);
	regfree(&r);
	return v;
}

/* new tree */
struct vlue *core_new(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"new\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TREE;
	v->data.tree = GC_malloc(sizeof(struct tree));
	if (v->data.tree == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->data.tree->root = 0;
	v->data.tree->frst = 0;
	v->data.tree->last = 0;
	return v;
}

/* true if both nodes or trees reference the same memory */
struct vlue *core_ref(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"ref\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	if (vv[0]->type == NODE) {
		if (vv[1]->type != NODE) {
			fputs("Can not compute \"ref\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->data.bool = vv[0]->data.node == vv[1]->data.node;
	} else if (vv[0]->type == TREE) {
		if (vv[1]->type != TREE) {
			fputs("Can not compute \"ref\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v->data.bool = vv[0]->data.tree == vv[1]->data.tree;
	} else {
		fputs("Can not compute \"ref\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* check if there are any nodes in tree */
struct vlue *core_any(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"any\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TREE) {
		fputs("Can not compute \"any\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = vv[0]->data.tree->frst != 0;
	return v;
}

/* number of nodes in tree */
struct vlue *core_qty(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	struct node *n;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"qty\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TREE) {
		fputs("Can not compute \"qty\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = 0.0L;
	for (n = vv[0]->data.tree->frst; n != 0; n = n->next)
		v->data.numb += 1.0L;
	return v;
}

/* check if node of given name is defined in tree */
struct vlue *core_def(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"def\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TREE || vv[1]->type != NAME) {
		fputs("Can not compute \"def\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = BOOL;
	v->data.bool = tree_search(vv[0]->data.tree, vv[1]->data.name) != 0;
	return v;
}

/* insert node to tree */
struct vlue *core_ins(size_t vc, struct vlue **vv)
{
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 3) {
		fputs("Can not compute \"ins\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TREE || vv[1]->type != NAME) {
		fputs("Can not compute \"ins\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (tree_insert(vv[0]->data.tree, vv[1]->data.name, vv[2]) == 0) {
		fprintf(stderr, "Can not compute \"ins\" call. Tree node \"%s\" already defined.\n", vv[1]->data.name);
		exit(EXIT_FAILURE);
	}
	return vv[0];
}

/* delete node from tree */
struct vlue *core_del(size_t vc, struct vlue **vv)
{
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 2) {
		fputs("Can not compute \"del\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TREE || vv[1]->type != NAME) {
		fputs("Can not compute \"del\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (tree_delete(vv[0]->data.tree, vv[1]->data.name) == 0) {
		fprintf(stderr, "Can not compute \"del\" call. Tree node \"%s\" not defined.\n", vv[1]->data.name);
		exit(EXIT_FAILURE);
	}
	return vv[0];
}

/* set value of node in tree or set value of node itself */
struct vlue *core_set(size_t vc, struct vlue **vv)
{
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc == 0) {
		fputs("Can not compute \"set\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type == NODE) {
		if (vc != 2) {
			fputs("Can not compute \"set\" call. Wrong number of parameters.\n", stderr);
			exit(EXIT_FAILURE);
		}
		vv[0]->data.node->vlue = vv[1];
	} else if (vv[0]->type == TREE) {
		if (vc != 3) {
			fputs("Can not compute \"set\" call. Wrong number of parameters.\n", stderr);
			exit(EXIT_FAILURE);
		}
		if (vv[1]->type != NAME) {
			fputs("Can not compute \"set\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		if (tree_update(vv[0]->data.tree, vv[1]->data.name, vv[2]) == 0) {
			fprintf(stderr, "Can not compute \"set\" call. Tree node \"%s\" not defined.\n", vv[1]->data.name);
			exit(EXIT_FAILURE);
		}
	} else {
		fputs("Can not compute \"set\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return vv[0];
}

/* get value of node or node in tree */
struct vlue *core_get(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc == 0) {
		fputs("Can not compute \"get\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type == NODE) {
		if (vc != 1) {
			fputs("Can not compute \"get\" call. Wrong number of parameters.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v = vv[0]->data.node->vlue;
	} else if (vv[0]->type == TREE) {
		if (vc != 2) {
			fputs("Can not compute \"get\" call. Wrong number of parameters.\n", stderr);
			exit(EXIT_FAILURE);
		}
		if (vv[1]->type != NAME) {
			fputs("Can not compute \"get\" call. Wrong type of parameter.\n", stderr);
			exit(EXIT_FAILURE);
		}
		v = (struct vlue *) tree_search(vv[0]->data.tree, vv[1]->data.name);
		if (v == 0) {
			fprintf(stderr, "Can not compute \"get\" call. Tree node \"%s\" not defined.\n", vv[1]->data.name);
			exit(EXIT_FAILURE);
		}
	} else {
		fputs("Can not compute \"get\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* root of tree */
struct vlue *core_root(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"root\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TREE) {
		fputs("Can not compute \"root\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->data.tree->root != 0) {
		v->type = NODE;
		v->data.node = vv[0]->data.tree->root;
	} else {
		v->type = VOID;
	}
	return v;
}

/* frst node of tree */
struct vlue *core_frst(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"frst\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TREE) {
		fputs("Can not compute \"frst\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->data.tree->frst != 0) {
		v->type = NODE;
		v->data.node = vv[0]->data.tree->frst;
	} else {
		v->type = VOID;
	}
	return v;
}

/* last node of tree */
struct vlue *core_last(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"last\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TREE) {
		fputs("Can not compute \"last\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->data.tree->last != 0) {
		v->type = NODE;
		v->data.node = vv[0]->data.tree->last;
	} else {
		v->type = VOID;
	}
	return v;
}

/* left child */
struct vlue *core_left(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"left\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NODE) {
		fputs("Can not compute \"left\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->data.node->left != 0) {
		v->type = NODE;
		v->data.node = vv[0]->data.node->left;
	} else {
		v->type = VOID;
	}
	return v;
}

/* right child */
struct vlue *core_rght(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"rght\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NODE) {
		fputs("Can not compute \"rght\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->data.node->rght != 0) {
		v->type = NODE;
		v->data.node = vv[0]->data.node->rght;
	} else {
		v->type = VOID;
	}
	return v;
}

/* next node */
struct vlue *core_next(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"next\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NODE) {
		fputs("Can not compute \"next\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->data.node->next != 0) {
		v->type = NODE;
		v->data.node = vv[0]->data.node->next;
	} else {
		v->type = VOID;
	}
	return v;
}

/* previous node */
struct vlue *core_prev(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"prev\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NODE) {
		fputs("Can not compute \"prev\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->data.node->prev != 0) {
		v->type = NODE;
		v->data.node = vv[0]->data.node->prev;
	} else {
		v->type = VOID;
	}
	return v;
}

/* value of node */
struct vlue *core_vlue(size_t vc, struct vlue **vv)
{
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"vlue\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NODE) {
		fputs("Can not compute \"vlue\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return vv[0]->data.node->vlue;
}

/* tree that node belongs to */
struct vlue *core_tree(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"tree\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NODE) {
		fputs("Can not compute \"tree\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TREE;
	v->data.tree = vv[0]->data.node->tree;
	return v;
}

/* main tree */
struct vlue *core_main(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"main\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TREE;
	v->data.tree = tree;	/* tree is global */
	return v;
}

/* read vlalue */
struct vlue *core_read(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"read\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (back != 0) {
		v = back;
		back = 0;
	} else {
		v = vlue_read();
	}
	return v;
}

/* put value back for reading in future */
struct vlue *core_back(size_t vc, struct vlue **vv)
{
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"back\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (back != 0) {
		fputs("Can not compute \"back\" call. Value already back.\n", stderr);
		exit(EXIT_FAILURE);
	}
	back = vv[0];
	return vv[0];
}

/* write value */
struct vlue *core_wrte(size_t vc, struct vlue **vv)
{
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"wrte\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	vlue_wrte(vv[0]);
	return vv[0];
}

/* write value, but text write literally */
struct vlue *core_dump(size_t vc, struct vlue **vv)
{
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"dump\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TEXT) {
		fputs("Can not compute \"dump\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	fputs(vv[0]->data.text, stdout);
	if (feof(stdout) || ferror(stdout)) {
		fputs("Output error.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return vv[0];
}

/* current time */
struct vlue *core_time(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"time\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = time(0);
	return v;
}

/* interpret number as time and return text representing it */
struct vlue *core_repr(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	size_t n;
	time_t t;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"repr\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NUMB) {
		fputs("Can not compute \"repr\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (roundl(vv[0]->data.numb) != vv[0]->data.numb) {
		fputs("Can not compute \"repr\" call. Time not integer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (roundl(vv[0]->data.numb) < -2147483648.0L || roundl(vv[0]->data.numb) > 2147483647.0L) {
		fputs("Can not compute \"repr\" call. Time out of range.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TEXT;
	v->data.text = GC_malloc(20);
	if (v->data.text == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	t = roundl(vv[0]->data.numb);
	n = strftime(v->data.text, 20, "%Y-%m-%d %H:%M:%S", localtime(&t));
	if (n != 19) {
		fputs("Internal problem.\n", stderr);
		exit(EXIT_FAILURE);
	}
	return v;
}

/* unique identifier starting with given name */
struct vlue *core_pars(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	regex_t r;
	struct tm m;
	char *c;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"pars\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != TEXT) {
		fputs("Can not compute \"pars\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* expected precise format */
	if (regcomp(&r, "^(19[0-9]|20[0-3])[0-9]-((0[1-9]|1[0-2])-(0[1-9]|1[0-9]|2[0-9])|(0[1,3-9]|1[0-2])-30|(0[13578]|1[02])-31) [0-5][0-9]:[0-5][0-9]:[0-5][0-9]$", REG_EXTENDED) != 0) {
		fputs("Internal problem.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (regexec(&r, vv[0]->data.text, 0, 0, 0) != 0) {
		fputs("Can not compute \"pars\" call. Wrong time format.\n", stderr);
		exit(EXIT_FAILURE);
	}
	regfree(&r);
	/* initialize broken-time structure, parse date into it, 
	 * compute number of seconds since epoch */
	c = strptime(vv[0]->data.text, "%Y-%m-%d %H:%M:%S", &m);
	if (c == 0 || *c != '\0') {
		fputs("Can not compute \"pars\" call. Wrong time format.\n", stderr);
		exit(EXIT_FAILURE);
	}
	/* know nothing about daylight saving time */
	m.tm_isdst = -1;
	/* return number of seconds */
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = timelocal(&m);
	return v;
}

/* random number */
struct vlue *core_rand(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"rand\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NUMB;
	v->data.numb = numb_norm(drand48());
	return v;
}

/* unique identifier starting with given name */
struct vlue *core_iden(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	size_t l;
	time_t n;
	struct tm *d;
	struct timespec t;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"iden\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != NAME) {
		fputs("Can not compute \"iden\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	l = strlen(vv[0]->data.name);
	if (l > SIZE_MAX - 27) {	/* underline + date + underline + time + underline + nanoseconds + null char */
		fputs("Limit reached.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = NAME;
	v->data.name = GC_malloc(l + 27);
	if (v->data.text == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	time(&n);
	d = localtime(&n);
	clock_gettime(CLOCK_REALTIME, &t);
	sprintf(v->data.text, "%s_%.4d%.2d%.2d_%.2d%.2d%.2d_%.9ld", vv[0]->data.name, d->tm_year + 1900, d->tm_mon + 1, d->tm_mday, d->tm_hour, d->tm_min, d->tm_sec, t.tv_nsec);
	return v;
}

/* version of compiled treep */
struct vlue *core_vers(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"vers\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TEXT;
	v->data.name = VERSION;
	return v;
}

/* void value */
struct vlue *core_void(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		/* any number of parameters allowed */
	};
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = VOID;
	return v;
}

/* space value */
struct vlue *core_spac(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"spac\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = SPAC;
	return v;
}

/* tablulator value */
struct vlue *core_tabu(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"tabu\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = TABU;
	return v;
}

/* new line value */
struct vlue *core_line(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"line\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = LINE;
	return v;
}

/* left parenthesis value */
struct vlue *core_lpar(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"lpar\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = LPAR;
	return v;
}

/* right parenthesis value */
struct vlue *core_rpar(size_t vc, struct vlue **vv)
{
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		fputs("Can not compute \"rpar\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v = GC_malloc(sizeof(struct vlue));
	if (v == 0) {
		fputs("Out of memory.\n", stderr);
		exit(EXIT_FAILURE);
	}
	v->type = RPAR;
	return v;
}

/* write values to standard error */
struct vlue *core_info(size_t vc, struct vlue **vv)
{
	size_t i;
	char *t;
	struct node *n;
	struct vlue *v;
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 0) {
		/* any number of parameters allowed */
	};
	for (i = 0; i < vc; i++) {
		if (vv[i]->type == VOID) {
			fputs("(void)", stderr);
		} else if (vv[i]->type == SPAC) {
			fputs("(spac)", stderr);
		} else if (vv[i]->type == TABU) {
			fputs("(tabu)", stderr);
		} else if (vv[i]->type == LINE) {
			fputs("(line)", stderr);
		} else if (vv[i]->type == LPAR) {
			fputs("(lpar)", stderr);
		} else if (vv[i]->type == RPAR) {
			fputs("(rpar)", stderr);
		} else if (vv[i]->type == NUMB) {
			fputs(numb_text(vv[i]->data.numb), stderr);
		} else if (vv[i]->type == NAME) {
			fputs(vv[i]->data.name, stderr);
		} else if (vv[i]->type == TEXT) {
			/* don't escape printed text */
			fputs(vv[i]->data.text, stderr);
		} else if (vv[i]->type == BOOL) {
			fputs(vv[i]->data.bool ? "(yes)" : "(no)", stderr);
		} else if (vv[i]->type == NODE) {
			fputs("(node ", stderr);
			fputs(vv[i]->data.node->name, stderr);
			fputc(' ', stderr);
			v = (struct vlue *) vv[i]->data.node->vlue;
			if (v->type == VOID) {
				fputs("(void)", stderr);
			} else if (v->type == SPAC) {
				fputs("(spac)", stderr);
			} else if (v->type == TABU) {
				fputs("(tabu)", stderr);
			} else if (v->type == LINE) {
				fputs("(line)", stderr);
			} else if (v->type == LPAR) {
				fputs("(lpar)", stderr);
			} else if (v->type == RPAR) {
				fputs("(rpar)", stderr);
			} else if (v->type == NUMB) {
				fputs(numb_text(v->data.numb), stderr);
			} else if (v->type == NAME) {
				fputs(v->data.name, stderr);
			} else if (v->type == TEXT) {
				fputc('"', stderr);
				for (t = v->data.text; *t != '\0'; t++) {
					if (*t == '"' || *t == '\\')
						fputc('\\', stderr);
					fputc(*t, stderr);
				}
				fputc('"', stderr);
			} else if (v->type == BOOL) {
				fputs(v->data.bool ? "(yes)" : "(no)", stderr);
			} else if (v->type == NODE) {
				fputs("(node ...)", stderr);
			} else if (v->type == TREE) {
				fputs("(tree ...)", stderr);
			} else {
				fputs("Wrong data.\n", stderr);
				exit(EXIT_FAILURE);
			}
			fputc(')', stderr);
		} else if (vv[i]->type == TREE) {
			fputs("(tree", stderr);
			for (n = vv[i]->data.tree->frst; n != 0; n = n->next) {
				fputc(' ', stderr);
				fputs(n->name, stderr);
				fputc(' ', stderr);
				v = (struct vlue *) n->vlue;
				if (v->type == VOID) {
					fputs("(void)", stderr);
				} else if (v->type == SPAC) {
					fputs("(spac)", stderr);
				} else if (v->type == TABU) {
					fputs("(tabu)", stderr);
				} else if (v->type == LINE) {
					fputs("(line)", stderr);
				} else if (v->type == LPAR) {
					fputs("(lpar)", stderr);
				} else if (v->type == RPAR) {
					fputs("(rpar)", stderr);
				} else if (v->type == NUMB) {
					fputs(numb_text(v->data.numb), stderr);
				} else if (v->type == NAME) {
					fputs(v->data.name, stderr);
				} else if (v->type == TEXT) {
					fputc('"', stderr);
					for (t = v->data.text; *t != '\0'; t++) {
						if (*t == '"' || *t == '\\')
							fputc('\\', stderr);
						fputc(*t, stderr);
					}
					fputc('"', stderr);
				} else if (v->type == BOOL) {
					fputs(v->data.bool ? "(yes)" : "(no)", stderr);
				} else if (v->type == NODE) {
					fputs("(node ...)", stderr);
				} else if (v->type == TREE) {
					fputs("(tree ...)", stderr);
				} else {
					fputs("Wrong data.\n", stderr);
					exit(EXIT_FAILURE);
				}
			}
			fputc(')', stderr);
		} else {
			fputs("Wrong data.\n", stderr);
			exit(EXIT_FAILURE);
		}
	}
	fputc('\n', stderr);
	return vv[vc - 1];
}

/* exit program */
struct vlue *core_exit(size_t vc, struct vlue **vv)
{
	if (vv == 0) {
		fputs("Null pointer.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vc != 1) {
		fputs("Can not compute \"exit\" call. Wrong number of parameters.\n", stderr);
		exit(EXIT_FAILURE);
	}
	if (vv[0]->type != BOOL) {
		fputs("Can not compute \"exit\" call. Wrong type of parameter.\n", stderr);
		exit(EXIT_FAILURE);
	}
	exit(vv[0]->data.bool ? EXIT_SUCCESS : EXIT_FAILURE);
	return vv[0];
}
