summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2008-05-15 23:28:07 +0000
committerPaul Buetow <paul@buetow.org>2008-05-15 23:28:07 +0000
commitbe839900419c7a74c4a46efd279d0ca16b35dc1f (patch)
tree1355c8f238d1c58ffd5cb8803bcc2adf987e79aa /src
parent33c945e58f86267b0d3bdca4c3421155e11eb0d9 (diff)
Moved stuff into trunk.
Diffstat (limited to 'src')
-rw-r--r--src/argv.c181
-rw-r--r--src/argv.h51
-rw-r--r--src/build.h41
-rw-r--r--src/core/convert.c185
-rw-r--r--src/core/convert.h53
-rw-r--r--src/core/function.c661
-rw-r--r--src/core/function.h50
-rw-r--r--src/core/garbage.c136
-rw-r--r--src/core/garbage.h54
-rw-r--r--src/core/interpret.c946
-rw-r--r--src/core/interpret.h75
-rw-r--r--src/core/scanner.c391
-rw-r--r--src/core/scanner.h71
-rw-r--r--src/core/scope.c150
-rw-r--r--src/core/scope.h59
-rw-r--r--src/core/symbol.c66
-rw-r--r--src/core/symbol.h64
-rw-r--r--src/core/token.c380
-rw-r--r--src/core/token.h183
-rw-r--r--src/data/array.c266
-rw-r--r--src/data/array.h86
-rw-r--r--src/data/dat.c267
-rw-r--r--src/data/dat.h88
-rw-r--r--src/data/hash.c290
-rw-r--r--src/data/hash.h80
-rw-r--r--src/data/list.c458
-rw-r--r--src/data/list.h105
-rw-r--r--src/data/map.c283
-rw-r--r--src/data/map.h82
-rw-r--r--src/data/queue.c210
-rw-r--r--src/data/queue.h81
-rw-r--r--src/data/stack.c234
-rw-r--r--src/data/stack.h76
-rw-r--r--src/data/tree.c250
-rw-r--r--src/data/tree.h106
-rw-r--r--src/data/tupel.c53
-rw-r--r--src/data/tupel.h47
-rw-r--r--src/data/types.h64
-rw-r--r--src/defines.h99
-rw-r--r--src/fype.c91
-rw-r--r--src/fype.h57
-rw-r--r--src/main.c45
42 files changed, 7215 insertions, 0 deletions
diff --git a/src/argv.c b/src/argv.c
new file mode 100644
index 0000000..07a3ea0
--- /dev/null
+++ b/src/argv.c
@@ -0,0 +1,181 @@
+/*:*
+ *: File: ./src/argv.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "argv.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "defines.h"
+#include "data/dat.h"
+
+#define ARGV_OSLEN 128
+
+char *BINARY;
+
+void
+argv_run(Fype *p_fype, int i_argc, char **pc_argv) {
+ Dat *p_dat_string = dat_new();
+
+ BINARY = pc_argv[0];
+ char *c_tmp = STR_NEW(ARGV_OSLEN);
+ c_tmp[0] = '\0';
+
+ p_fype->p_tupel_argv->a = p_dat_string;
+ p_fype->p_tupel_argv->b = c_tmp;
+
+ if (i_argc <= 1) {
+ argv_synopsis(p_fype->p_tupel_argv);
+ exit(1);
+ }
+
+ for (int i = 1; i < i_argc; ++i) {
+ if (pc_argv[i][0] != '-' && pc_argv[i][0] != '/') {
+ dat_push(p_dat_string, pc_argv[i]);
+ continue;
+ }
+
+ int i_len = strlen(pc_argv[i]);
+ unsigned i_argc_left = i_argc - i + dat_size(p_dat_string);
+
+ for (int j = 1; j < i_len; ++j)
+ argv_switch(pc_argv[i][j], p_fype->p_tupel_argv, i_argc_left);
+ }
+}
+
+void
+argv_switch(char c_arg, Tupel *p_tupel_argv, unsigned i_argc_left) {
+ switch (c_arg) {
+ case 'e':
+ case 'T':
+ case 'V':
+ argv_addopt(c_arg, p_tupel_argv);
+ return;
+ case 'h':
+ argv_help();
+ exit(0);
+ case 's':
+ argv_synopsis(p_tupel_argv);
+ exit(0);
+ case 'v':
+ printf("%s %s %d\n", NAME, VERSION, BUILDNR);
+ exit(0);
+ }
+
+ char buf[2];
+ buf[0] = c_arg;
+ buf[1] = '\0';
+
+ EPRINTF("Error: No such option '%s'!\n", buf);
+ exit(1);
+}
+
+void
+argv_synopsis(Tupel *p_tupel_argv) {
+ printf("Synopsis:\n");
+ printf("%s ", BINARY);
+ printf("[-[hsvTV]] file.fy\n");
+ printf("%s ", BINARY);
+ printf("-e \"code string;\"\n");
+
+ if (!argv_checkopt('h', p_tupel_argv))
+ printf("\t(Hint: Try -h for details)\n");
+}
+
+void
+argv_help() {
+ printf("%s %s %d\n", NAME, VERSION, BUILDNR);
+ printf("%s\n", COPYRIGHT);
+ printf("\t-e\tExecutes given code string (see synopses)\n");
+ printf("\t-h\tPrints this help\n");
+ printf("\t-s\tPrints the synopsis\n");
+ printf("\t-v\tPrints the current version\n");
+ printf("\t-T\tPrints token list after scanning\n");
+ printf("\t-V\tVerbose mode: Print all possible output\n");
+ exit(0);
+}
+
+void
+argv_addopt(char c_opt, Tupel *p_tupel_argv) {
+ char *c_opts = (char *) p_tupel_argv->b;
+ int i_len = strlen(c_opts), i;
+
+ for (i = 0; i < i_len; ++i)
+ if (c_opts[i] == c_opt)
+ return;
+
+ c_opts[i] = c_opt;
+ c_opts[i+1] = '\0';
+}
+
+_Bool
+argv_checkopt(char c_opt, Tupel *p_tupel_argv) {
+ char *c_opts = (char *) p_tupel_argv->b;
+ int i_len = strlen(c_opts);
+
+ for (int i = 0; i < i_len; ++i)
+ if (c_opts[i] == c_opt)
+ return 1;
+
+ return 0;
+}
+
+_Bool
+argv_checkopts(char *c_opts, Tupel *p_tupel_argv) {
+ int i_len = strlen(c_opts);
+
+ for (int i = 0; i < i_len; ++i)
+ if (argv_checkopt(c_opts[i], p_tupel_argv))
+ return 1;
+
+ return 0;
+}
+
+void
+argv_check_argc(int i_required, unsigned i_argc_left, Tupel *p_tupel_argv) {
+ if ((unsigned) ++i_required > i_argc_left) {
+ argv_synopsis(p_tupel_argv);
+ EPRINTF("%d argument(s) missing!\n", i_required-i_argc_left);
+ exit(1);
+ }
+}
+
+void
+argv_tupel_delete(Tupel *p_tupel_argv) {
+ dat_delete(p_tupel_argv->a);
+ free(p_tupel_argv->b);
+ tupel_delete(p_tupel_argv);
+}
+
diff --git a/src/argv.h b/src/argv.h
new file mode 100644
index 0000000..bcf7eb4
--- /dev/null
+++ b/src/argv.h
@@ -0,0 +1,51 @@
+/*:*
+ *: File: ./src/argv.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef ARGV_H
+#define ARGV_H
+
+#include "data/tupel.h"
+#include "fype.h"
+
+void argv_run(Fype *p_fype, int i_argc, char **pc_argv);
+void argv_switch(char c_arg, Tupel *p_tupel_argv, unsigned i_argc_left);
+void argv_synopsis(Tupel *p_tupel_argv);
+void argv_help();
+void argv_addopt(char c_opt, Tupel *p_tupel_argv);
+_Bool argv_checkopt(char c_opt, Tupel *p_tupel_argv);
+_Bool argv_checkopts(char *c_opts, Tupel *p_tupel_argv);
+void argv_check_argc(int i_required, unsigned i_argc_left, Tupel *p_tupel_argv);
+void argv_tupel_delete(Tupel *p_tupel_argv);
+
+#endif
diff --git a/src/build.h b/src/build.h
new file mode 100644
index 0000000..a4066a3
--- /dev/null
+++ b/src/build.h
@@ -0,0 +1,41 @@
+/*:*
+ *: File: ./src/build.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef BUILD_H
+#define BUILD_H
+
+#define BUILDNR 8867
+#define OS_FREEBSD
+
+#endif
diff --git a/src/core/convert.c b/src/core/convert.c
new file mode 100644
index 0000000..0d63619
--- /dev/null
+++ b/src/core/convert.c
@@ -0,0 +1,185 @@
+/*:*
+ *: File: ./src/core/convert.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "convert.h"
+
+void
+convert_to_integer(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ break;
+ case TT_DOUBLE:
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, (int)token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, atoi(token_get_val(p_token)));
+ break;
+ default:
+ ERROR("Ouups(%s)", tt_get_name(token_get_tt(p_token)));
+ break;
+ }
+}
+
+int
+convert_to_integer_get(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ return (token_get_ival(p_token));
+ case TT_DOUBLE:
+ return ((int) token_get_dval(p_token));
+ case TT_STRING:
+ return (atoi(token_get_val(p_token)));
+ default:
+ ERROR("Ouups(%s)", tt_get_name(token_get_tt(p_token)));
+ }
+
+ return (0); /* Never reach this point */
+}
+
+void
+convert_to_double(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ break;
+ case TT_STRING:
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, atof(token_get_val(p_token)));
+ break;
+ default:
+ token_print_val(p_token);
+ ERROR("Datatype conversion error '%s'", token_get_val(p_token));
+ break;
+ }
+}
+
+void
+convert_to_string(Token *p_token) {
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ {
+ token_set_tt(p_token, TT_STRING);
+ char c_tmp[1024];
+ sprintf(c_tmp, "%d", token_get_ival(p_token));
+ int i_len = strlen(c_tmp);
+ p_token->c_val = realloc(p_token->c_val, sizeof(char) * (i_len + 1));
+ strcpy(p_token->c_val, c_tmp);
+ p_token->c_val[i_len] = 0;
+ }
+ break;
+ case TT_DOUBLE:
+ {
+ token_set_tt(p_token, TT_STRING);
+ char c_tmp[1024];
+ sprintf(c_tmp, "%f", token_get_dval(p_token));
+ int i_len = strlen(c_tmp);
+ p_token->c_val = realloc(p_token->c_val, sizeof(char) * (i_len + 1));
+ strcpy(p_token->c_val, c_tmp);
+ p_token->c_val[i_len] = 0;
+ }
+ break;
+ case TT_STRING:
+ break;
+ default:
+ ERROR("Datatype conversion error");
+ break;
+ }
+}
+
+void
+convert_to_tt(Token *p_token, TokenType tt) {
+ switch (tt) {
+ case TT_INTEGER:
+ convert_to_integer(p_token);
+ break;
+ case TT_DOUBLE:
+ convert_to_double(p_token);
+ break;
+ case TT_STRING:
+ convert_to_string(p_token);
+ break;
+ default:
+ ERROR("Ouups!");
+ }
+}
+
+TokenType
+convert_to_highest(Token *p_token1, Token *p_token2) {
+ TokenType tt_highest = token_get_tt(p_token1);
+
+ if (tt_highest < token_get_tt(p_token2)) {
+ tt_highest = token_get_tt(p_token2);
+
+ convert_to_tt(p_token1, tt_highest);
+
+ } else {
+ convert_to_tt(p_token2, tt_highest);
+ }
+
+ return (tt_highest);
+}
+
+TokenType
+convert_function_arg_types_to_highest(Stack *p_stack_args, int i_args) {
+
+ if (i_args <= 0)
+ i_args = stack_size(p_stack_args);
+
+ StackIterator *p_iter = stackiterator_new(p_stack_args);
+ TokenType tt_highest = TT_INTEGER;
+
+ for (int i = 0; i < i_args && stackiterator_has_next(p_iter); ++i) {
+ Token *p_token = stackiterator_next(p_iter);
+ if (token_get_tt(p_token) > tt_highest)
+ tt_highest = token_get_tt(p_token);
+ }
+
+ stackiterator_delete(p_iter);
+ p_iter = stackiterator_new(p_stack_args);
+
+ for (int i = 0; i < i_args && stackiterator_has_next(p_iter); ++i) {
+ Token *p_token = stackiterator_next(p_iter);
+ convert_to_tt(p_token, tt_highest);
+ }
+
+ stackiterator_delete(p_iter);
+
+ return (tt_highest);
+}
+
diff --git a/src/core/convert.h b/src/core/convert.h
new file mode 100644
index 0000000..c4e0b1d
--- /dev/null
+++ b/src/core/convert.h
@@ -0,0 +1,53 @@
+/*:*
+ *: File: ./src/core/convert.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef CONVERT_H
+#define CONVERT_H
+
+#include "../defines.h"
+
+#include "../data/stack.h"
+
+#include "token.h"
+
+int convert_to_integer_get(Token *p_token);
+void convert_to_integer(Token *p_token);
+void convert_to_double(Token *p_token);
+void convert_to_string(Token *p_token);
+void convert_to_tt(Token *p_token, TokenType tt);
+TokenType convert_to_highest(Token *p_token1, Token *p_token2);
+TokenType convert_function_arg_types_to_highest(Stack *p_stack_args, int
+ i_args);
+
+#endif
diff --git a/src/core/function.c b/src/core/function.c
new file mode 100644
index 0000000..fd18ba0
--- /dev/null
+++ b/src/core/function.c
@@ -0,0 +1,661 @@
+/*:*
+ *: File: ./src/core/function.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "function.h"
+
+#include "convert.h"
+#include "scope.h"
+#include "symbol.h"
+
+#define _FUNCTION_ERROR(m,t) \
+ ERROR(\
+ "%s: Function error in %s line %d pos %d near '%s'", m, \
+ token_get_filename(t), \
+ token_get_line_nr(t), \
+ token_get_pos_nr(t), \
+ token_get_val(t) \
+ )
+
+void
+_process(Interpret *p_interpret, Token *p_token_store, Token *p_token_op,
+ Token *p_token_next) {
+
+ TokenType tt_op = token_get_tt(p_token_op);
+
+#ifdef DEBUG_FUNCTION_PROCESS
+ printf("PROCESS OPERATOR %s\n", tt_get_name(tt_op));
+
+ token_print(p_token_next);
+ printf("\n");
+ token_print(p_token_store);
+ printf("\n");
+#endif /* DEBUG_FUNCTION_PROCESS */
+
+
+ switch (tt_op) {
+ case TT_ASSIGN:
+ {
+ Token *p_token_assign = p_interpret->p_token_temp;
+ TokenType tt_assign = token_get_tt(p_token_assign);
+
+ if (tt_assign != TT_IDENT) {
+ _FUNCTION_ERROR("Can only assign to symbols",
+ p_token_store);
+ }
+
+ Symbol *p_symbol = scope_get(p_interpret->p_scope,
+ token_get_val(p_token_assign));
+
+ if (p_symbol == NULL) {
+ _FUNCTION_ERROR("No such symbol",
+ p_token_assign);
+ }
+
+ symbol_set_val(p_symbol, p_token_store);
+ symbol_set_sym(p_symbol, SYM_VARIABLE);
+
+ return;
+ }
+
+ break;
+ NO_DEFAULT;
+ }
+
+ p_token_next = token_new_copy(p_token_next);
+ TokenType tt_highest = convert_to_highest(p_token_store, p_token_next);
+
+#ifdef DEBUG_FUNCTION_PROCESS
+ printf("===> %s %s %s\n",
+ tt_get_name(tt_highest),
+ tt_get_name(tt_op),
+ tt_get_name(tt_highest));
+#endif /* DEBUG_FUNCTION_PROCESS */
+
+ switch (tt_op) {
+ case TT_ADD:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ token_get_ival(p_token_next) +
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) +
+ token_get_dval(p_token_store));
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) +
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_SUB:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ token_get_ival(p_token_next) -
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) -
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) -
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_MULT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ token_get_ival(p_token_next) *
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) *
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ atoi(token_get_val(p_token_next)) *
+ atoi(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_DIV:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) /
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token_store,
+ token_get_dval(p_token_next) /
+ token_get_dval(p_token_store));
+ break;
+ case TT_STRING:
+ token_set_dval(p_token_store,
+ atof(token_get_val(p_token_next)) /
+ atof(token_get_val(p_token_store)));
+ token_set_tt(p_token_store, TT_DOUBLE);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_EQ:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) ==
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) ==
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) == 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_NEQ:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) !=
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) !=
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) != 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_LT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) <
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) <
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) < 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_GT:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) >
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) >
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) > 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_LE:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) <=
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) <=
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) <= 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ case TT_GE:
+ switch (tt_highest) {
+ case TT_INTEGER:
+ token_set_ival(p_token_store,
+ (int) token_get_ival(p_token_next) >=
+ token_get_ival(p_token_store));
+ break;
+ case TT_DOUBLE:
+ token_set_ival(p_token_store,
+ token_get_dval(p_token_next) >=
+ token_get_dval(p_token_store));
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ case TT_STRING:
+ token_set_ival(p_token_store,
+ strcmp(token_get_val(p_token_next),
+ token_get_val(p_token_store)) >= 0);
+ token_set_tt(p_token_store, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ break;
+ default:
+ _FUNCTION_ERROR("No such function/operator", p_token_op);
+ }
+
+#ifdef DEBUG_FUNCTION_PROCESS
+ token_print(p_token_store);
+ printf("\n\n");
+#endif /* DEBUG_FUNCTION_PROCESS */
+
+ token_delete(p_token_next);
+}
+
+void
+function_process(Interpret *p_interpret, Token *p_token_op,
+ Stack *p_stack_args, int i_args) {
+
+ Token *p_token_store = token_new_copy(stack_pop(p_stack_args));
+
+ for (int i = 0; i < i_args -1 && !stack_empty(p_stack_args); ++i) {
+ Token *p_token_next = stack_pop(p_stack_args);
+
+ _process(p_interpret, p_token_store, p_token_op, p_token_next);
+ }
+
+ stack_push(p_stack_args, p_token_store);
+}
+
+_Bool
+function_is_buildin(Token *p_token_ident) {
+ if (strcmp("assert", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("decr", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("double", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("end", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("exit", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("fork", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("gc", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("incr", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("integer", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("ln", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("neg", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("no", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("put", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("say", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("string", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ if (strcmp("yes", token_get_val(p_token_ident)) == 0)
+ return (true);
+
+ return (false);
+}
+
+void
+function_process_buildin(Interpret *p_interpret, Token *p_token_ident,
+ Stack *p_stack_args) {
+
+ if (strcmp("assert", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = stack_top(p_stack_args);
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ if (token_get_ival(p_token) == 0)
+ _FUNCTION_ERROR("Assert failed", p_token);
+ break;
+ case TT_DOUBLE:
+ if (token_get_dval(p_token) == 0)
+ _FUNCTION_ERROR("Assert failed", p_token);
+ break;
+ case TT_STRING:
+ if (atoi(token_get_val(p_token)) == 0)
+ _FUNCTION_ERROR("Assert failed", p_token);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("decr", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = stack_top(p_stack_args);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, token_get_ival(p_token) - 1);
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, token_get_dval(p_token) - 1);
+ break;
+ case TT_STRING:
+ convert_to_integer(p_token);
+ token_set_ival(p_token, token_get_ival(p_token) - 1);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("double", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_double(p_token);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("end", token_get_val(p_token_ident)) == 0) {
+ exit(0);
+
+ } else if (strcmp("fork", token_get_val(p_token_ident)) == 0) {
+ Token *p_token = token_new_integer((int) fork());
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("gc", token_get_val(p_token_ident)) == 0) {
+ int i_count = garbage_collect();
+ printf("ICOUNT %d\n", i_count);
+ Token *p_token = token_new_integer(i_count);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("exit", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = stack_top(p_stack_args);
+ p_token = token_new_copy(p_token);
+ convert_to_integer(p_token);
+ exit(token_get_ival(p_token));
+
+ } else if (strcmp("incr", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = stack_top(p_stack_args);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, token_get_ival(p_token) + 1);
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, token_get_dval(p_token) + 1);
+ break;
+ case TT_STRING:
+ convert_to_integer(p_token);
+ token_set_ival(p_token, token_get_ival(p_token) + 1);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("integer", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_integer(p_token);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("ln", token_get_val(p_token_ident)) == 0) {
+ printf("\n");
+
+ } else if (strcmp("neg", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ stack_push(p_stack_args, p_token);
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, -token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, -token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token, -atoi(token_get_val(p_token)));
+ token_set_tt(p_token, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+
+ } else if (strcmp("no", token_get_val(p_token_ident)) == 0) {
+ Token *p_token = NULL;
+
+ if (0 == stack_size(p_stack_args)) {
+ p_token = token_new_integer(0);
+
+ } else {
+ p_token = token_new_copy(stack_pop(p_stack_args));
+
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ token_set_ival(p_token, !token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ token_set_dval(p_token, !token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ token_set_ival(p_token, !atoi(token_get_val(p_token)));
+ token_set_tt(p_token, TT_INTEGER);
+ break;
+ NO_DEFAULT;
+ }
+ }
+
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("put", token_get_val(p_token_ident)) == 0) {
+ StackIterator *p_iter = stackiterator_new(p_stack_args);
+ while (stackiterator_has_next(p_iter)) {
+ Token *p_token = stackiterator_next(p_iter);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ printf("%d", token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ printf("%f", token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ printf("%s", token_get_val(p_token));
+ break;
+ NO_DEFAULT;
+ }
+ }
+ stackiterator_delete(p_iter);
+
+ } else if (strcmp("say", token_get_val(p_token_ident)) == 0) {
+ StackIterator *p_iter = stackiterator_new(p_stack_args);
+ while (stackiterator_has_next(p_iter)) {
+ Token *p_token = stackiterator_next(p_iter);
+ switch (token_get_tt(p_token)) {
+ case TT_INTEGER:
+ printf("%d", token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ printf("%f", token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ printf("%s", token_get_val(p_token));
+ break;
+ NO_DEFAULT;
+ }
+ }
+ stackiterator_delete(p_iter);
+ printf("\n");
+
+ } else if (strcmp("string", token_get_val(p_token_ident)) == 0) {
+ if (0 == stack_size(p_stack_args))
+ _FUNCTION_ERROR("No argument given", p_token_ident);
+
+ Token *p_token = token_new_copy(stack_pop(p_stack_args));
+ convert_to_string(p_token);
+ stack_push(p_stack_args, p_token);
+
+ } else if (strcmp("yes", token_get_val(p_token_ident)) == 0) {
+ Token *p_token = NULL;
+
+ if (0 == stack_size(p_stack_args)) {
+ p_token = token_new_integer(1);
+
+ } else {
+ p_token = token_new_copy(stack_pop(p_stack_args));
+ token_set_ival(p_token, 1);
+ token_set_tt(p_token, TT_INTEGER);
+
+ }
+
+ stack_push(p_stack_args, p_token);
+ }
+}
+
+_Bool
+function_is_self_defined(Interpret *p_interpret) {
+ Symbol *p_symbol = scope_get(p_interpret->p_scope,
+ token_get_val(p_interpret->p_token));
+
+ if (p_symbol == NULL)
+ return (false);
+
+ switch (symbol_get_sym(p_symbol)) {
+ case SYM_PROCEDURE:
+ case SYM_FUNCTION:
+ return (true);
+ NO_DEFAULT;
+ }
+
+ return (false);
+}
+
+void
+function_process_self_defined(Interpret *p_interpret, Token *p_token_ident) {
+ Symbol *p_symbol = scope_get(p_interpret->p_scope,
+ token_get_val(p_token_ident));
+
+ switch (symbol_get_sym(p_symbol)) {
+ case SYM_PROCEDURE:
+ {
+ List *p_list_token = symbol_get_val(p_symbol);
+ interpret_subprocess(p_interpret, p_list_token);
+ }
+ break;
+ case SYM_FUNCTION:
+ {
+ List *p_list_token = symbol_get_val(p_symbol);
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_token);
+ scope_down(p_interpret->p_scope);
+ }
+ NO_DEFAULT;
+ }
+}
+
diff --git a/src/core/function.h b/src/core/function.h
new file mode 100644
index 0000000..9f12bb4
--- /dev/null
+++ b/src/core/function.h
@@ -0,0 +1,50 @@
+/*:*
+ *: File: ./src/core/function.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef FUNCTION_H
+#define FUNCTION_H
+
+#include "token.h"
+
+#include "interpret.h"
+#include "../data/stack.h"
+
+void function_process(Interpret *p_interp, Token *p_token_op, Stack
+ *p_stack_args, int i_args);
+_Bool function_is_buildin(Token *p_token_ident);
+void function_process_buildin(Interpret *p_interpret, Token *p_token_ident, Stack *p_stack_args);
+_Bool function_is_self_defined(Interpret *p_interpret);
+void function_process_self_defined(Interpret *p_interpret, Token *p_token_ident);
+
+#endif /* FUNCTION_H */
diff --git a/src/core/garbage.c b/src/core/garbage.c
new file mode 100644
index 0000000..b4dad22
--- /dev/null
+++ b/src/core/garbage.c
@@ -0,0 +1,136 @@
+/*:*
+ *: File: ./src/core/garbage.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "garbage.h"
+
+#define _GARBAGE_ERROR(m) \
+ ERROR("%s: Garbage error", m);
+
+List *LIST_GARBAGE = NULL;
+
+typedef struct {
+ void (*p_func)(void*);
+ int *p_ref_count;
+ void *p_2free;
+ GarbageType type;
+} _Garbage;
+
+void
+garbage_init() {
+ LIST_GARBAGE = list_new();
+}
+
+void
+_garbage_print(_Garbage *p_garbage) {
+ switch (p_garbage->type) {
+ case GC_TOKEN:
+ {
+ Token *p_token = p_garbage->p_2free;
+ token_print(p_token);
+ printf("\n");
+ }
+ break;
+ }
+}
+
+void
+garbage_destroy() {
+ garbage_collect();
+
+ if (!list_empty(LIST_GARBAGE)) {
+ EPRINTF("The garbage collector still has %d registered items which don't have"
+ " a zero ref count!\n", list_size(LIST_GARBAGE));
+
+ ListIterator *p_iter = listiterator_new(LIST_GARBAGE);
+ while (listiterator_has_next(p_iter)) {
+ _Garbage *p_garbage = listiterator_next(p_iter);
+ _garbage_print(p_garbage);
+ }
+ listiterator_delete(p_iter);
+
+ _GARBAGE_ERROR("Garbage left");
+ }
+
+ list_delete(LIST_GARBAGE);
+}
+
+int
+garbage_collect() {
+ ListIterator *p_iter = listiterator_new(LIST_GARBAGE);
+ List *p_list_garbage_new = list_new();
+ int i_count = 0;
+
+ while (listiterator_has_next(p_iter)) {
+ _Garbage *p_garbage = listiterator_next(p_iter);
+
+ if (p_garbage->p_ref_count == NULL || *p_garbage->p_ref_count <= 0) {
+ // _garbage_print(p_garbage);
+ (*p_garbage->p_func) (p_garbage->p_2free);
+ free(p_garbage);
+ ++i_count;
+
+ } else {
+ list_add_back(p_list_garbage_new, p_garbage);
+ }
+ }
+
+ listiterator_delete(p_iter);
+
+ list_delete(LIST_GARBAGE);
+ LIST_GARBAGE = p_list_garbage_new;
+
+ return (i_count);
+}
+
+void
+garbage_add(void *p, GarbageType type) {
+ garbage_add2(p, free, NULL, type);
+}
+
+void
+garbage_add2(void *p, void (*p_func)(void*), int *p_ref_count, GarbageType type) {
+ _Garbage *p_garbage = malloc(sizeof(_Garbage));
+
+ p_garbage->p_2free = p;
+ p_garbage->p_func = p_func;
+ p_garbage->p_ref_count = p_ref_count;
+ p_garbage->type = type;
+
+ list_add_back(LIST_GARBAGE, p_garbage);
+}
+
+void
+garbage_add_token(Token *p_token) {
+ garbage_add2(p_token, token_delete_cb, &p_token->i_ref_count, GC_TOKEN);
+}
diff --git a/src/core/garbage.h b/src/core/garbage.h
new file mode 100644
index 0000000..6a8007d
--- /dev/null
+++ b/src/core/garbage.h
@@ -0,0 +1,54 @@
+/*:*
+ *: File: ./src/core/garbage.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef GARBAGE_H
+#define GARBAGE_H
+
+#include "../defines.h"
+#include "../data/list.h"
+#include "token.h"
+
+typedef enum {
+ GC_TOKEN,
+} GarbageType;
+
+void garbage_init();
+void garbage_destroy();
+int garbage_collect();
+void garbage_add(void *p, GarbageType type);
+void garbage_add2(void *p, void (*p_func)(void*), int *p_ref_count,
+ GarbageType type);
+void garbage_add_token(Token *p_token);
+
+#endif
diff --git a/src/core/interpret.c b/src/core/interpret.c
new file mode 100644
index 0000000..97e19c2
--- /dev/null
+++ b/src/core/interpret.c
@@ -0,0 +1,946 @@
+/*:*
+ *: File: ./src/core/interpret.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "interpret.h"
+
+#include "../defines.h"
+#include "convert.h"
+#include "function.h"
+#include "symbol.h"
+
+#define _INTERPRET_ERROR(m,t) \
+ ERROR(\
+ "%s: Interpret error in %s line %d pos %d near '%s'", m, \
+ token_get_filename(t), \
+ token_get_line_nr(t), \
+ token_get_pos_nr(t), \
+ token_get_val(t) \
+ )
+
+#define _CHECK if (p_interpret->p_token == NULL) return (0);
+#define _HAS_NEXT listiterator_has_next(p_interpret->p_iter)
+#define _NEXT if (!_next(p_interpret)) { return (2); }
+#define _NEXT_TT _next_tt(p_interpret)
+#define _SKIP _next(p_interpret);
+
+void _print_lookahead(Interpret *p_interpret);
+int _next(Interpret *p_interpret);
+int _program(Interpret *p_interpret);
+int _var_decl(Interpret *p_interpret);
+int _var_assign(Interpret *p_interpret);
+int _var_list(Interpret *p_interpret);
+int _expression_get(Interpret *p_interpret, List *p_list_block);
+int _block_get(Interpret *p_interpret, List *p_list_block);
+int _block_skip(Interpret *p_interpret);
+int _proc_decl(Interpret *p_interpret);
+int _func_decl(Interpret *p_interpret);
+int _statement(Interpret *p_interpret);
+int _block(Interpret *p_interpret);
+int _expression(Interpret *p_interpret);
+int _expression_(Interpret *p_interpret);
+int _control(Interpret *p_interpret);
+int _compare(Interpret *p_interpret);
+int _sum(Interpret *p_interpret);
+int _product(Interpret *p_interpret);
+int _product2(Interpret *p_interpret);
+int _term(Interpret *p_interpret);
+
+Interpret*
+interpret_new(List *p_list_token, Hash *p_hash_syms) {
+ Interpret *p_interpret = malloc(sizeof(Interpret));
+
+ if (p_hash_syms != NULL) {
+ p_interpret->p_scope = scope_new(p_hash_syms);
+ p_interpret->b_scope_delete = true;
+
+ } else {
+ p_interpret->p_scope = NULL;
+ p_interpret->b_scope_delete = false;
+ }
+
+ p_interpret->p_list_token = p_list_token;
+ p_interpret->p_stack = stack_new();
+ p_interpret->tt = TT_NONE;
+ p_interpret->p_token = NULL;
+ p_interpret->tt_prev = TT_NONE;
+ p_interpret->p_token_prev = NULL;
+ p_interpret->p_token_temp = NULL;
+ p_interpret->ct = CONTROL_NONE;
+
+ return (p_interpret);
+}
+
+void
+interpret_delete(Interpret *p_interpret) {
+ if (!p_interpret)
+ return;
+
+ if (p_interpret->b_scope_delete)
+ scope_delete(p_interpret->p_scope);
+
+ stack_delete(p_interpret->p_stack);
+ free(p_interpret);
+}
+
+void
+_print_lookahead(Interpret *p_interpret) {
+ ListIterator *p_iter = p_interpret->p_iter;
+ ListIteratorState *p_state = listiterator_get_state(p_iter);
+
+ printf("LOOLAHEAD:\n");
+
+ token_print(p_interpret->p_token);
+ printf("\n");
+
+ while (listiterator_has_next(p_iter)) {
+ Token *p_token = listiterator_next(p_iter);
+ token_print(p_token);
+ printf("\n");
+ }
+
+ listiterator_set_state(p_iter, p_state);
+ listiteratorstate_delete(p_state);
+}
+
+int
+_next(Interpret *p_interpret) {
+ if (listiterator_has_next(p_interpret->p_iter)) {
+ p_interpret->p_token_prev = p_interpret->p_token;
+ p_interpret->tt_prev = p_interpret->tt;
+
+ p_interpret->p_token = listiterator_next(p_interpret->p_iter);
+ p_interpret->tt = token_get_tt(p_interpret->p_token);
+ return (1);
+ }
+
+ p_interpret->p_token = NULL;
+ p_interpret->tt = TT_NONE;
+
+ return (0);
+}
+
+TokenType
+_next_tt(Interpret *p_interpret) {
+ if (listiterator_has_next(p_interpret->p_iter)) {
+ Token *p_token = listiterator_current(p_interpret->p_iter);
+ return (token_get_tt(p_token));
+ }
+
+ return (TT_NONE);
+}
+
+int
+_program(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ while (_statement(p_interpret) == 1)
+ garbage_collect();
+
+ return (1);
+}
+
+int
+_var_decl(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_MY) {
+ if (_NEXT_TT != TT_IDENT)
+ _INTERPRET_ERROR("'my' expects identifier", p_interpret->p_token);
+
+ _NEXT
+
+ Token *p_token_ident = p_interpret->p_token;
+
+ _var_assign(p_interpret);
+ _var_list(p_interpret);
+
+ if (p_interpret->tt == TT_SEMICOLON) {
+ _NEXT
+ return (1);
+
+ } else if (p_interpret->p_token != NULL) {
+ _INTERPRET_ERROR("Expected ';'", p_interpret->p_token);
+
+ } else {
+ _INTERPRET_ERROR("Expected ';' after", p_token_ident);
+ }
+ }
+
+ return (0);
+}
+
+int
+_var_assign(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_IDENT) {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ char *c_name = token_get_val(p_token);
+ if (scope_exists(p_interpret->p_scope, c_name)) {
+ _INTERPRET_ERROR("Symbol already defined", p_token);
+ }
+
+ if (p_interpret->tt == TT_ASSIGN) {
+ _NEXT
+
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ if (_expression_(p_interpret)) {
+ function_process_buildin(p_interpret, p_token, p_interpret->p_stack);
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ p_token = stack_top(p_interpret->p_stack);
+ Symbol *p_symbol = symbol_new(SYM_VARIABLE, p_token);
+ scope_newset(p_interpret->p_scope, c_name, p_symbol);
+
+ } else {
+ return (0);
+ }
+
+ } else {
+ Token *p_token = token_new_integer(0);
+ Symbol *p_symbol = symbol_new(SYM_VARIABLE, p_token);
+ scope_newset(p_interpret->p_scope, c_name, p_symbol);
+ }
+ }
+
+ return (1);
+}
+
+int
+_var_list(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_COMMA) {
+ _NEXT
+ _var_assign(p_interpret);
+ _var_list(p_interpret);
+ }
+
+ return (1);
+}
+
+int
+_block_get(Interpret *p_interpret, List *p_list_block) {
+ if (p_interpret->tt != TT_PARANT_CL)
+ _INTERPRET_ERROR("Expected '{'", p_interpret->p_token);
+ _NEXT
+
+ int i_num_parant = 0;
+
+ for (;;) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ ++i_num_parant;
+
+ } else if (p_interpret->tt == TT_PARANT_CR) {
+ if (--i_num_parant == -1) {
+ _NEXT
+ break; /* for */
+ }
+ }
+
+ list_add_back(p_list_block, p_interpret->p_token);
+
+ _NEXT
+ }
+
+#ifdef DEBUG_BLOCK_GET
+ printf("====> BLOCK\n");
+ list_iterate(p_list_block, token_print_cb);
+ printf("<==== BLOCK\n");
+#endif /* DEBUG_BLOCK_GET */
+
+ return (1);
+}
+
+int
+_expression_get(Interpret *p_interpret, List *p_list_expression) {
+ for (;;) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ break; /* for */
+ }
+
+ list_add_back(p_list_expression, p_interpret->p_token);
+
+ _NEXT
+ }
+
+#ifdef DEBUG_EXPRESSION_GET
+ printf("====> EXPRESSION\n");
+ list_iterate(p_list_expression, token_print_cb);
+ printf("<==== EXPRESSION\n");
+#endif /* DEBUG_EXPRESSION_GET */
+
+ return (1);
+}
+
+int
+_block_skip(Interpret *p_interpret) {
+ if (p_interpret->tt != TT_PARANT_CL)
+ _INTERPRET_ERROR("Expected '{'", p_interpret->p_token);
+ _NEXT
+
+ int i_num_parant = 0;
+
+ for (;;) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ ++i_num_parant;
+
+ } else if (p_interpret->tt == TT_PARANT_CR) {
+ if (--i_num_parant == -1) {
+ _NEXT
+ break; /* for */
+ }
+ }
+
+ _NEXT
+ }
+
+ return (1);
+}
+
+int
+_proc_decl(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_PROC) {
+ _NEXT
+
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expected identifier", p_interpret->p_token);
+
+ Token *p_token_ident = p_interpret->p_token;
+ _NEXT
+
+ if (scope_exists(p_interpret->p_scope, token_get_val(p_token_ident))) {
+ _INTERPRET_ERROR("Symbol already defined", p_token_ident);
+ }
+
+ List *p_list_proc = list_new();
+
+ if (_block_get(p_interpret, p_list_proc)) {
+
+ Symbol *p_symbol = symbol_new(SYM_PROCEDURE, p_list_proc);
+ scope_newset(p_interpret->p_scope, token_get_val(p_token_ident),
+ p_symbol);
+
+ return (1);
+ }
+
+ list_delete(p_list_proc);
+ }
+
+ return (0);
+}
+
+int
+_func_decl(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (p_interpret->tt == TT_FUNC) {
+ _NEXT
+
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expected identifier", p_interpret->p_token);
+
+ Token *p_token_ident = p_interpret->p_token;
+ _NEXT
+
+ if (scope_exists(p_interpret->p_scope, token_get_val(p_token_ident))) {
+ _INTERPRET_ERROR("Symbol already defined", p_token_ident);
+ }
+
+ List *p_list_proc = list_new();
+
+ if (_block_get(p_interpret, p_list_proc)) {
+
+ Symbol *p_symbol = symbol_new(SYM_FUNCTION, p_list_proc);
+ scope_newset(p_interpret->p_scope, token_get_val(p_token_ident),
+ p_symbol);
+
+ return (1);
+ }
+
+ list_delete(p_list_proc);
+ }
+
+ return (0);
+}
+
+int
+_statement(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ for (int i = 0; i < 2; ++i) {
+ if (_proc_decl(p_interpret)) return (1);
+ if (_func_decl(p_interpret)) return (1);
+ if (_var_decl(p_interpret)) return (1);
+ if (_control(p_interpret)) return (1);
+ if (_expression(p_interpret)) return (1);
+ if (_block(p_interpret)) return (1);
+ }
+
+ return (0);
+}
+
+int
+_block(Interpret *p_interpret) {
+ if (p_interpret->tt == TT_PARANT_CL) {
+ List *p_list_block = list_new();
+
+ if (_block_get(p_interpret, p_list_block)) {
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+ list_delete(p_list_block);
+ return (1);
+ }
+
+ list_delete(p_list_block);
+ }
+
+ return (0);
+}
+
+int
+_expression(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_expression_(p_interpret)) {
+ if (p_interpret->tt == TT_SEMICOLON) {
+ _NEXT
+
+ } else {
+ _INTERPRET_ERROR("Expected ';'", p_interpret->p_token);
+ }
+
+ stack_clear(p_interpret->p_stack);
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_expression_(Interpret *p_interpret) {
+ return (_compare(p_interpret));
+}
+
+int
+_control(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ Token *p_token = p_interpret->p_token;
+
+ switch (p_interpret->tt) {
+ case TT_IF:
+ case TT_IFNOT:
+ {
+ TokenType tt = p_interpret->tt;
+ _NEXT
+ if (_expression_(p_interpret)) {
+ Token *p_token_top = stack_pop(p_interpret->p_stack);
+ List *p_list_block = list_new();
+ _block_get(p_interpret, p_list_block);
+ int ret = 0;
+
+ switch (tt) {
+ case TT_IF:
+ if (convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ ret = interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+ }
+ break;
+ case TT_IFNOT:
+ if (!convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ ret = interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+ }
+ break;
+ NO_DEFAULT;
+ }
+
+ list_delete(p_list_block);
+ return (1);
+
+ } else {
+ _INTERPRET_ERROR("Expected expression after control keyword", p_token);
+ }
+ }
+ break;
+ case TT_WHILE:
+ case TT_UNTIL:
+ {
+ TokenType tt = p_interpret->tt;
+ List *p_list_expr = list_new(), *p_list_block = list_new();
+ _Bool b_flag = true;
+
+ _NEXT
+
+ _expression_get(p_interpret, p_list_expr);
+ _block_get(p_interpret, p_list_block);
+ Token *p_token_backup = p_interpret->p_token;
+
+ do {
+ Stack *p_stack_backup = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ ListIterator *p_iter_backup = p_interpret->p_iter;
+ p_interpret->p_iter = listiterator_new(p_list_expr);
+
+ _NEXT
+
+ /* Dont use if here, because we want to check the p_itnerpret->ct */
+ if (_expression_(p_interpret)) {
+ Token *p_token_top = stack_pop(p_interpret->p_stack);
+
+ if (p_token_top == NULL) {
+ printf("FOO\n");
+ exit(0);
+ }
+ if (tt == TT_WHILE) {
+ if (convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+
+ } else {
+ b_flag = false;
+ }
+
+ } else if (tt == TT_UNTIL) {
+ if (!convert_to_integer_get(p_token_top)) {
+ scope_up(p_interpret->p_scope);
+ interpret_subprocess(p_interpret, p_list_block);
+ scope_down(p_interpret->p_scope);
+
+ } else {
+ b_flag = false;
+ }
+ }
+
+ /*
+ switch (p_interpret->ct) {
+ case CONTROL_BREAK:
+ p_interpret->ct = CONTROL_NONE;
+ b_flag = false;
+ break;
+ case CONTROL_NEXT:
+ p_interpret->ct = CONTROL_NONE;
+ break;
+ NO_DEFAULT;
+ }
+ */
+
+ } else {
+ _INTERPRET_ERROR("Expected expression after control keyword", p_token);
+ }
+
+ listiterator_delete(p_interpret->p_iter);
+ p_interpret->p_iter = p_iter_backup;
+
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack_backup;
+
+ } while (b_flag);
+
+ list_delete(p_list_expr);
+ list_delete(p_list_block);
+ p_interpret->p_token = p_token_backup;
+ p_interpret->tt = token_get_tt(p_token_backup);
+
+ return (1);
+ }
+ break;
+ NO_DEFAULT;
+ }
+
+ return (0);
+}
+
+int
+_compare(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_sum(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_EQ:
+ case TT_NEQ:
+ case TT_LT:
+ case TT_GT:
+ case TT_LE:
+ case TT_GE:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (!_sum(p_interpret))
+ _INTERPRET_ERROR("Expected sum", p_interpret->p_token);
+
+ function_process(p_interpret, p_token, p_interpret->p_stack, 2);
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_sum(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_product(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_ADD:
+ case TT_SUB:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (!_product(p_interpret))
+ _INTERPRET_ERROR("Expected product", p_token);
+
+ function_process(p_interpret, p_token, p_interpret->p_stack, 2);
+
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_product(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_product2(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_MULT:
+ case TT_DIV:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (!_product2(p_interpret))
+ _INTERPRET_ERROR("Expected product2", p_token);
+
+ function_process(p_interpret, p_token, p_interpret->p_stack, 2);
+
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_product2(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ if (_term(p_interpret)) {
+ _Bool b_flag = true;
+
+ do {
+ switch (p_interpret->tt) {
+ case TT_ASSIGN:
+ {
+ Token *p_token = p_interpret->p_token;
+ Token *p_token_temp = p_interpret->p_token_prev;
+ _NEXT
+
+ if (!_expression_(p_interpret))
+ _INTERPRET_ERROR("Expected expression", p_token);
+
+ p_interpret->p_token_temp = p_token_temp;
+ function_process(p_interpret, p_token, p_interpret->p_stack, 2);
+ p_interpret->p_token_temp = NULL;
+
+ }
+ break; /* case */
+
+ default:
+ b_flag = false;
+ break;
+
+ } /* switch */
+
+ } while (b_flag);
+
+ return (1);
+ }
+
+ return (0);
+}
+
+int
+_term(Interpret *p_interpret) {
+ _CHECK TRACK
+
+ switch (p_interpret->tt) {
+ case TT_INTEGER:
+ case TT_DOUBLE:
+ case TT_STRING:
+ stack_push(p_interpret->p_stack, p_interpret->p_token);
+ _NEXT
+ return (1);
+
+ case TT_IDENT:
+ {
+ if (_NEXT_TT != TT_ASSIGN) {
+ if (function_is_buildin(p_interpret->p_token)) {
+ Token *p_token = p_interpret->p_token;
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ if (_HAS_NEXT) {
+ _NEXT
+ if (_expression_(p_interpret));
+
+ } else {
+ _SKIP
+ }
+
+ function_process_buildin(p_interpret, p_token, p_interpret->p_stack);
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ return (1);
+
+ } else if (function_is_self_defined(p_interpret)) {
+ Token *p_token = p_interpret->p_token;
+ Stack *p_stack = p_interpret->p_stack;
+ p_interpret->p_stack = stack_new();
+
+ _NEXT
+ if (_expression_(p_interpret));
+
+ function_process_self_defined(p_interpret, p_token);
+
+ if (stack_empty(p_interpret->p_stack)) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, 0);
+ stack_push(p_interpret->p_stack, p_token);
+ }
+
+ stack_merge(p_stack, p_interpret->p_stack);
+ stack_delete(p_interpret->p_stack);
+ p_interpret->p_stack = p_stack;
+
+ return (1);
+ }
+ }
+
+ /* It is not a function, it is a variable or some sort of */
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Symbol *p_symbol = scope_get(p_interpret->p_scope, c_name);
+
+ if (p_symbol == NULL)
+ _INTERPRET_ERROR("No such symbol", p_interpret->p_token);
+
+ SymbolType st = symbol_get_sym(p_symbol);
+
+ switch (st) {
+ case SYM_VARIABLE:
+ stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
+ _NEXT
+ return (1);
+
+ /* Example: proc foo { foo = "Hello"; } foo; say foo; */
+ case SYM_PROCEDURE:
+ stack_push(p_interpret->p_stack, symbol_get_val(p_symbol));
+ _NEXT
+ return (1);
+
+ NO_DEFAULT;
+ }
+ }
+ break;
+ case TT_DEFINED:
+ {
+ _NEXT
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expexted identifier for 'defined'",
+ p_interpret->p_token);
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Token *p_token = token_new_integer(0);
+
+ if (scope_exists(p_interpret->p_scope, c_name))
+ token_set_ival(p_token, 1);
+
+ stack_push(p_interpret->p_stack, p_token);
+
+ _NEXT;
+ return (1);
+ }
+ break;
+
+ case TT_UNDEF:
+ {
+ _NEXT
+ if (p_interpret->tt != TT_IDENT)
+ _INTERPRET_ERROR("Expexted identifier for 'defined'",
+ p_interpret->p_token);
+
+ char *c_name = token_get_val(p_interpret->p_token);
+ Token *p_token = NULL;
+ Symbol *p_symbol = NULL;
+
+ if ((p_symbol = scope_remove(p_interpret->p_scope, c_name))) {
+ symbol_delete(p_symbol);
+ p_token = token_new_integer(1);
+
+ } else {
+ p_token = token_new_integer(0);
+ }
+
+ stack_push(p_interpret->p_stack, p_token);
+
+ _NEXT;
+ return (1);
+ }
+ break;
+
+ case TT_PARANT_L:
+ {
+ Token *p_token = p_interpret->p_token;
+ _NEXT
+
+ if (_expression_(p_interpret)) {
+ if (p_interpret->tt != TT_PARANT_R)
+ _INTERPRET_ERROR("Expected ')'", p_token);
+
+ } else {
+ _INTERPRET_ERROR("Expected expression", p_token);
+ }
+ }
+ _NEXT
+ return (1);
+
+ default:
+ break;
+ }
+
+ return (0);
+}
+
+int
+interpret_process(Interpret *p_interpret) {
+ p_interpret->p_iter = listiterator_new(p_interpret->p_list_token);
+
+ _NEXT
+ _program(p_interpret);
+
+ listiterator_delete(p_interpret->p_iter);
+
+ return (1);
+}
+
+
+int
+interpret_subprocess(Interpret *p_interpret, List *p_list_token) {
+ Interpret *p_interpret_sub = interpret_new(p_list_token,
+ NULL);
+
+ p_interpret_sub->p_scope = p_interpret->p_scope;
+
+ int i_ret = interpret_process(p_interpret_sub);
+ p_interpret->ct = p_interpret_sub->ct;
+
+ interpret_delete(p_interpret_sub);
+
+ return (i_ret);
+}
+
+void
+interpret_run(Fype *p_fype) {
+ Interpret *p_interpret =
+ interpret_new(p_fype->p_list_token, p_fype->p_hash_syms);
+
+ interpret_process(p_interpret);
+
+ interpret_delete(p_interpret);
+}
+
diff --git a/src/core/interpret.h b/src/core/interpret.h
new file mode 100644
index 0000000..e2f4cb7
--- /dev/null
+++ b/src/core/interpret.h
@@ -0,0 +1,75 @@
+/*:*
+ *: File: ./src/core/interpret.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef INTERPRET_H
+#define INTERPRET_H
+
+#include "../data/list.h"
+#include "../data/stack.h"
+#include "../data/hash.h"
+
+#include "../fype.h"
+
+#include "garbage.h"
+#include "scope.h"
+#include "token.h"
+
+typedef enum {
+ CONTROL_NONE,
+ CONTROL_NEXT,
+ CONTROL_BREAK,
+} ControlType;
+
+typedef struct {
+ List *p_list_token;
+ Scope *p_scope;
+ _Bool b_scope_delete;
+ Stack *p_stack;
+ ControlType ct;
+
+ ListIterator *p_iter;
+ Token *p_token;
+ TokenType tt;
+ Token *p_token_prev;
+ TokenType tt_prev;
+ Token *p_token_temp;
+} Interpret;
+
+Interpret* interpret_new(List *p_list_token, Hash *p_hash_syms);
+void interpret_delete(Interpret *p_interpret);
+void interpret_run(Fype *p_type);
+int interpret_process(Interpret *p_interpret);
+int interpret_subprocess(Interpret *p_interpret, List *p_list_token);
+
+#endif /* INTERPRET_H */
diff --git a/src/core/scanner.c b/src/core/scanner.c
new file mode 100644
index 0000000..85f0780
--- /dev/null
+++ b/src/core/scanner.c
@@ -0,0 +1,391 @@
+/*:*
+ *: File: ./src/core/scanner.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "scanner.h"
+
+#include <ctype.h>
+#include <string.h>
+
+const char const *KEYWORDS[] = {
+ "if",
+ "else",
+ "elsif",
+ "while",
+ "ret",
+ "const",
+};
+
+const char const *OPERATORS[] = {
+ "!",
+ "!=",
+ "(",
+ ")",
+ "*",
+ "+",
+ "++",
+ ",",
+ "-",
+ "--",
+ ".",
+ "/",
+ "\\",
+ ":",
+ "==",
+ ";",
+ "<<",
+ "<",
+ "<=",
+ "=",
+ ">=",
+ ">>",
+ ">",
+ "{",
+ "}",
+};
+
+const char TOKENENDS[] = "{}();:,.";
+int CODESTRING_INDEX = 0;
+
+Scanner*
+scanner_new(List *p_list_token, Tupel *p_tupel_argv) {
+ Scanner *p_scanner = malloc(sizeof(Scanner));
+
+ Dat *p_dat_string = p_tupel_argv->a;
+
+ if (dat_empty(p_dat_string))
+ ERROR("No source given");
+
+ if (argv_checkopts("e", p_tupel_argv)) {
+ p_scanner->c_codestring = dat_pop(p_dat_string);
+ p_scanner->c_filename = NULL;
+ p_scanner->fp = NULL;
+
+ } else {
+ p_scanner->c_codestring = NULL;
+ p_scanner->c_filename = dat_pop(p_dat_string);
+ p_scanner->fp = fopen(p_scanner->c_filename, "r");
+
+ if (!p_scanner->fp)
+ ERROR("Could not open '%s' for reading!", p_scanner->c_filename);
+ }
+
+ p_scanner->p_list_token = p_list_token;
+
+ p_scanner->i_current_line_nr = 1;
+ p_scanner->i_current_pos_nr = 0;
+
+ p_scanner->i_num_keywords = sizeof(KEYWORDS) / sizeof(char const *);
+ p_scanner->i_num_operators = sizeof(OPERATORS) / sizeof(char const *);
+ p_scanner->i_num_tokenends = strlen(TOKENENDS);
+
+ return p_scanner;
+}
+
+void
+scanner_delete(Scanner *p_scanner) {
+ if (p_scanner->fp)
+ fclose(p_scanner->fp);
+ free(p_scanner);
+}
+
+void
+scanner_post_task(Scanner *p_scanner) {
+ List *p_list_token = scanner_get_list_token(p_scanner);
+ ListIterator *p_iter = listiterator_new(p_list_token);
+
+ Token *pt_last[] = { NULL, NULL };
+ TokenType tt_last[] = { TT_NONE, TT_NONE };
+
+ while (listiterator_has_next(p_iter)) {
+ ListElem *p_le = listiterator_next_elem(p_iter);
+ Token *p_token = p_le->p_val;
+ TokenType tt_cur = token_get_tt(p_token);
+
+ if (pt_last[0]) {
+ if (tt_cur == TT_INTEGER && tt_last[1] == TT_DOT
+ && tt_last[0] == TT_INTEGER) {
+
+ token_ref_down(pt_last[0]);
+ token_ref_down(pt_last[1]);
+
+ char *c_2 = token_get_val(p_token);
+ char *c_0 = token_get_val(pt_last[0]);
+ int i_len = strlen(c_2) + strlen(c_0) + 1;
+ char *c_new = calloc(i_len+1, sizeof(char));
+
+ sprintf(c_new, "%s.%s", c_0, c_2);
+ free(c_2);
+ c_new[i_len] = 0;
+
+ token_set_val(p_token, c_new);
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, atof(c_new));
+
+ list_remove_elem(p_list_token, p_le->p_prev);
+ list_remove_elem(p_list_token, p_le->p_prev);
+
+ pt_last[0] = pt_last[1] = NULL;
+ tt_last[0] = tt_last[1] = TT_NONE;
+ }
+ }
+
+ tt_last[0] = tt_last[1];
+ tt_last[1] = tt_cur;
+
+ pt_last[0] = pt_last[1];
+ pt_last[1] = p_token;
+ }
+
+ listiterator_delete(p_iter);
+}
+
+_Bool
+_scanner_has_next_char(Scanner *p_scanner) {
+ if (p_scanner->fp)
+ return !feof(p_scanner->fp);
+
+ return p_scanner->c_codestring[CODESTRING_INDEX] != 0;
+}
+
+char
+_scanner_get_next_char(Scanner *p_scanner) {
+ if (p_scanner->fp)
+ return fgetc(p_scanner->fp);
+
+ return (p_scanner->c_codestring[CODESTRING_INDEX++]);
+}
+
+void
+scanner_run(Fype *p_fype) {
+ Scanner *p_scanner = scanner_new(p_fype->p_list_token, p_fype->p_tupel_argv);
+
+ int i_token_len = 0;
+ char *c_token = malloc(sizeof(char));
+
+ c_token[0] = 0;
+
+ while ( _scanner_has_next_char(p_scanner) ) {
+ //char c = fgetc(fp);
+ char c = _scanner_get_next_char(p_scanner);
+ ++p_scanner->i_current_pos_nr;
+
+ switch (c) {
+ case '#':
+ {
+ c = _scanner_get_next_char(p_scanner);
+ ++p_scanner->i_current_pos_nr;
+ _Bool b_multi_comment = c == '*';
+
+ do {
+ c = _scanner_get_next_char(p_scanner);
+ ++p_scanner->i_current_pos_nr;
+ if (c == '\n') {
+ ++p_scanner->i_current_line_nr;
+ p_scanner->i_current_pos_nr = 0;
+
+ if (!b_multi_comment)
+ break;
+
+ } else if (b_multi_comment && c == '*' &&
+ _scanner_has_next_char(p_scanner)) {
+ if ( (c = _scanner_get_next_char(p_scanner)) == '#')
+ break;
+
+ else if (c == '\n')
+ ++p_scanner->i_current_line_nr;
+ }
+
+ } while ( _scanner_has_next_char(p_scanner) );
+ }
+
+ break;
+
+ case '"':
+ if (i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ }
+ {
+ int i_num_nl = 0;
+ do {
+ // c = fgetc(fp);
+ c = _scanner_get_next_char(p_scanner);
+ if ( c == '\n' ) {
+ ++i_num_nl;
+ p_scanner->i_current_pos_nr = 0;
+
+ i_token_len += 2;
+ c_token = realloc(c_token, sizeof(char) * (i_token_len + 1));
+ c_token[i_token_len-2] = '\\';
+ c_token[i_token_len-1] = 'n';
+ c_token[i_token_len] = 0;
+
+ } else if (c == '"') {
+ if (i_token_len && c_token[i_token_len-1] == '\\')
+ c_token[i_token_len-1] = '"';
+
+ else
+ break;
+
+ } else {
+ ++i_token_len;
+ c_token = realloc(c_token, sizeof(char) * (i_token_len + 1));
+ c_token[i_token_len-1] = c;
+ c_token[i_token_len] = 0;
+ }
+
+ //} while ( !feof(fp) );
+ } while ( _scanner_has_next_char(p_scanner) );
+
+ scanner_add_token(p_scanner, &c_token, &i_token_len, TT_STRING);
+
+ if (i_num_nl)
+ p_scanner->i_current_line_nr += i_num_nl;
+ }
+
+ break;
+
+ case '\n':
+ case '\t':
+ case ' ':
+ if (i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ }
+
+ if (c == '\n') {
+ ++p_scanner->i_current_line_nr;
+ p_scanner->i_current_pos_nr = 0;
+ }
+
+ break;
+
+ default:
+ if (i_token_len) {
+ char d = c_token[i_token_len-1];
+ if ((!isalpha(d) && !isdigit(d) /*&& d != '-'*/) &&
+ (isalpha(c) || isdigit(c))) {
+
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+
+ } else {
+ for (int i = 0; i < p_scanner->i_num_tokenends; ++i) {
+ if (TOKENENDS[i] == c) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ break;
+ }
+ }
+ }
+ }
+
+ ++i_token_len;
+ c_token = realloc(c_token, sizeof(char) * i_token_len + 1);
+ c_token[i_token_len-1] = c;
+ c_token[i_token_len] = 0;
+ }
+ }
+
+ if (argv_checkopts("e", p_fype->p_tupel_argv) && i_token_len) {
+ TokenType tt_cur = scanner_get_tt_cur(c_token);
+ scanner_add_token(p_scanner, &c_token, &i_token_len, tt_cur);
+ }
+
+ scanner_post_task(p_scanner);
+
+ char *c_filename = scanner_get_filename(p_scanner);
+ scanner_delete(p_scanner);
+
+ if (argv_checkopts("TV", p_fype->p_tupel_argv))
+ list_iterate(p_fype->p_list_token, token_print_cb);
+
+ char *c_basename = NULL;
+ if (c_filename) {
+ int i_len = strlen(c_filename) - 3;
+ c_basename = calloc(i_len+1, sizeof(char));
+ strncpy(c_basename, c_filename, i_len);
+ c_basename[i_len] = 0;
+
+ } else {
+ char *c_basename = calloc(1, sizeof(char));
+ c_basename[0] = 0;
+ }
+
+ p_fype->c_basename = c_basename;
+
+ /*
+ c_token = calloc(2, sizeof(char*));
+ c_token[0] = ';';
+ c_token[1] = '\0';
+ i_token_len = 1;
+
+ scanner_add_token(p_scanner, &c_token, &i_token_len, TT_STRING);
+ */
+}
+
+void
+scanner_add_token(Scanner *p_scanner, char **cc_token, int *p_token_len,
+ TokenType tt_cur) {
+
+ List *p_list_token = scanner_get_list_token(p_scanner);
+ Token *p_token = token_new(*cc_token, tt_cur, p_scanner->i_current_line_nr,
+ p_scanner->i_current_pos_nr, p_scanner->c_filename);
+
+ list_add_back(p_list_token, p_token);
+ token_ref_up(p_token);
+
+ *cc_token = malloc(sizeof(char));
+ (*cc_token)[0] = 0;
+ *p_token_len = 0;
+}
+
+TokenType
+scanner_get_tt_cur(char *c_token) {
+ if (isdigit(c_token[0]))
+ return TT_INTEGER;
+
+ if (c_token[0] == '-' && 1 < strlen(c_token) && isdigit(c_token[1]))
+ return TT_INTEGER;
+
+ TokenType tt_cur = get_tt(c_token);
+
+ return tt_cur == TT_NONE ? TT_IDENT : tt_cur;
+}
+
+void
+scanner_cleanup_list_token_cb(void *p_void) {
+ Token *p_token = p_void;
+ token_delete(p_token);
+}
diff --git a/src/core/scanner.h b/src/core/scanner.h
new file mode 100644
index 0000000..fc07a28
--- /dev/null
+++ b/src/core/scanner.h
@@ -0,0 +1,71 @@
+/*:*
+ *: File: ./src/core/scanner.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef SCANNER_H
+#define SCANNER_H
+
+#include <stdio.h>
+#include <ctype.h>
+
+#include "token.h"
+#include "../fype.h"
+#include "../data/dat.h"
+
+#define scanner_get_list_token(s) s->p_list_token
+#define scanner_get_fp(s) s->fp
+#define scanner_get_filename(s) s->c_filename
+#define scanner_get_codestring(s) s->c_codestring
+
+typedef struct {
+ int i_current_line_nr;
+ int i_current_pos_nr;
+ int i_num_keywords;
+ int i_num_operators;
+ int i_num_tokenends;
+ char *c_filename;
+ char *c_codestring;
+ FILE *fp;
+ List *p_list_token;
+} Scanner;
+
+Scanner *scanner_new(List *p_list_token, Tupel *p_tupel_argv);
+void scanner_post_task(Scanner *p_scanner);
+void scanner_delete(Scanner *p_scanner);
+void scanner_run(Fype *p_fype);
+void scanner_add_token(Scanner *p_scanner, char **cc_token, int *p_token_len,
+ TokenType tt_cur);
+TokenType scanner_get_tt_cur(char *c_token);
+void scanner_cleanup_list_token_cb(void *p_void);
+
+#endif
diff --git a/src/core/scope.c b/src/core/scope.c
new file mode 100644
index 0000000..f1ca006
--- /dev/null
+++ b/src/core/scope.c
@@ -0,0 +1,150 @@
+/*:*
+ *: File: ./src/core/scope.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "garbage.h"
+#include "scope.h"
+#include "symbol.h"
+
+Scope*
+scope_new(Hash *p_hash_syms) {
+ Scope *p_scope = malloc(sizeof(Scope));
+
+ p_scope->p_hash_global = p_hash_syms;
+ p_scope->p_stack_scopes = stack_new();
+
+ return (p_scope);
+}
+
+void
+scope_delete(Scope *p_scope) {
+ while (!stack_empty(p_scope->p_stack_scopes))
+ scope_down(p_scope);
+
+ stack_delete(p_scope->p_stack_scopes);
+
+ free(p_scope);
+}
+
+void
+scope_up(Scope *p_scope) {
+ stack_push(p_scope->p_stack_scopes, hash_new(1024));
+}
+
+void
+scope_down(Scope *p_scope) {
+ Hash *p_hash_syms = stack_pop(p_scope->p_stack_scopes);
+ hash_iterate(p_hash_syms, symbol_cleanup_hash_syms_cb);
+ hash_delete(p_hash_syms);
+}
+
+static Hash*
+_scope_get_hash(Scope *p_scope, char *c_key) {
+ StackIterator *p_iter = stackiterator_new(p_scope->p_stack_scopes);
+
+ while (stackiterator_has_next(p_iter)) {
+ Hash *p_hash_syms = stackiterator_next(p_iter);
+ Symbol *p_symbol = hash_get(p_hash_syms, c_key);
+
+ if (p_symbol != NULL) {
+ stackiterator_delete(p_iter);
+ return (p_hash_syms);
+ }
+ }
+
+ stackiterator_delete(p_iter);
+
+ if (hash_get(p_scope->p_hash_global, c_key))
+ return (p_scope->p_hash_global);
+
+ return (NULL);
+}
+
+Symbol*
+scope_get(Scope *p_scope, char *c_key) {
+ Hash *p_hash_syms = _scope_get_hash(p_scope, c_key);
+
+ if (p_hash_syms == NULL)
+ return (NULL);
+
+ return (hash_get(p_hash_syms, c_key));
+}
+
+Symbol*
+scope_remove(Scope *p_scope, char *c_key) {
+ Hash *p_hash_syms = _scope_get_hash(p_scope, c_key);
+
+ if (p_hash_syms == NULL)
+ return (NULL);
+
+ Symbol *p_symbol = hash_remove(p_hash_syms, c_key);
+
+ return (p_symbol);
+}
+
+_Bool
+scope_exists(Scope *p_scope, char *c_key) {
+ return (scope_get(p_scope, c_key) != NULL);
+}
+
+_Bool
+scope_reset(Scope *p_scope, char *c_key, Symbol *p_symbol) {
+ Hash *p_hash_syms = _scope_get_hash(p_scope, c_key);
+
+ if (p_hash_syms == NULL)
+ return (false);
+
+ hash_remove(p_hash_syms, c_key);
+ hash_insert(p_hash_syms, c_key, p_symbol);
+
+ return (true);
+}
+
+_Bool
+scope_newset(Scope *p_scope, char *c_key, Symbol *p_symbol) {
+ Hash *p_hash_syms = NULL;
+
+ if (stack_empty(p_scope->p_stack_scopes)) {
+ if (hash_get(p_scope->p_hash_global, c_key) != NULL)
+ return (false);
+
+ p_hash_syms = p_scope->p_hash_global;
+
+ } else {
+ p_hash_syms = stack_top(p_scope->p_stack_scopes);
+ }
+
+ hash_insert(p_hash_syms, c_key, p_symbol);
+
+ return (true);
+}
diff --git a/src/core/scope.h b/src/core/scope.h
new file mode 100644
index 0000000..63a4373
--- /dev/null
+++ b/src/core/scope.h
@@ -0,0 +1,59 @@
+/*:*
+ *: File: ./src/core/scope.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef SCOPE_H
+#define SCOPE_H
+
+#include "../data/hash.h"
+#include "../data/stack.h"
+#include "../defines.h"
+#include "symbol.h"
+
+
+typedef struct {
+ Hash *p_hash_global;
+ Stack *p_stack_scopes;
+} Scope;
+
+Scope* scope_new(Hash *p_hash_syms);
+void scope_delete(Scope *p_scope);
+Symbol *scope_get(Scope *p_scope, char *c_key);
+Symbol *scope_remove(Scope *p_scope, char *c_key);
+_Bool scope_exists(Scope *p_scope, char *c_key);
+_Bool scope_newset(Scope *p_scope, char *c_key, Symbol *p_symbol);
+_Bool scope_reset(Scope *p_scope, char *c_key, Symbol *p_symbol);
+void scope_down(Scope *p_scope);
+void scope_up(Scope *p_scope);
+
+#endif /* SCOPE_H */
diff --git a/src/core/symbol.c b/src/core/symbol.c
new file mode 100644
index 0000000..721603a
--- /dev/null
+++ b/src/core/symbol.c
@@ -0,0 +1,66 @@
+/*:*
+ *: File: ./src/core/symbol.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "symbol.h"
+
+#include "../data/list.h"
+
+Symbol*
+symbol_new(SymbolType sym, void *p_val) {
+ Symbol *p_symbol = malloc(sizeof(Symbol));
+
+ p_symbol->sym = sym;
+ p_symbol->p_val = p_val;
+
+ return p_symbol;
+}
+
+void
+symbol_delete(Symbol *p_symbol) {
+ switch (symbol_get_sym(p_symbol)) {
+ case SYM_PROCEDURE:
+ {
+ List *p_list_token = symbol_get_val(p_symbol);
+ list_delete(p_list_token);
+ }
+ break;
+ NO_DEFAULT;
+ }
+ free(p_symbol);
+}
+
+void
+symbol_cleanup_hash_syms_cb(void *p_void) {
+ symbol_delete(p_void);
+}
diff --git a/src/core/symbol.h b/src/core/symbol.h
new file mode 100644
index 0000000..5744383
--- /dev/null
+++ b/src/core/symbol.h
@@ -0,0 +1,64 @@
+/*:*
+ *: File: ./src/core/symbol.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef SYMBOL_H
+#define SYMBOL_H
+
+#include "../defines.h"
+
+#define symbol_set_val(s,v) s->p_val = v
+#define symbol_set_sym(s,st) s->sym = st
+#define symbol_get_val(s) s->p_val
+#define symbol_get_sym(s) s->sym
+#define IS_A_FUNCTION(s) (s == SYM_INLINEFUNCTION || s == SYM_FUNCTION)
+#define IS_NOT_A_FUNCTION(s) !IS_A_FUNCTION(s)
+
+typedef enum {
+ SYM_CONSTANT,
+ SYM_VARIABLE,
+ SYM_BUILDIN,
+ SYM_PROCEDURE,
+ SYM_FUNCTION,
+} SymbolType;
+
+typedef struct {
+ SymbolType sym;
+ void *p_val;
+} Symbol;
+
+Symbol* symbol_new(SymbolType sym, void *p_val);
+void symbol_delete(Symbol *p_symbol);
+void symbol_cleanup_hash_syms_cb(void *p_void);
+
+#endif
diff --git a/src/core/token.c b/src/core/token.c
new file mode 100644
index 0000000..1573371
--- /dev/null
+++ b/src/core/token.c
@@ -0,0 +1,380 @@
+/*:*
+ *: File: ./src/core/token.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "token.h"
+
+#include "garbage.h"
+
+#define CHECK(...) if (!strcmp(c_token, __VA_ARGS__)) return
+
+long TOKEN_ID_COUNTER = 0;
+
+TokenType
+get_tt(char *c_token) {
+ CHECK("if") TT_IF;
+ CHECK("ifnot") TT_IFNOT;
+ CHECK("else") TT_ELSE;
+ CHECK("break") TT_BREAK;
+ CHECK("while") TT_WHILE;
+ CHECK("until") TT_UNTIL;
+ CHECK("int") TT_INT;
+ CHECK("next") TT_NEXT;
+ CHECK("defined") TT_DEFINED;
+ CHECK("undef") TT_UNDEF;
+ CHECK("ret") TT_RET;
+ CHECK("const") TT_CONST;
+ CHECK("proc") TT_PROC;
+ CHECK("func") TT_FUNC;
+ CHECK("my") TT_MY;
+ CHECK("not") TT_NOT;
+ CHECK("!=") TT_NEQ;
+ CHECK("=~") TT_RE;
+ CHECK("(") TT_PARANT_L;
+ CHECK(")") TT_PARANT_R;
+ CHECK("*") TT_MULT;
+ CHECK("+") TT_ADD;
+ CHECK("++") TT_INCR;
+ CHECK(",") TT_COMMA;
+ CHECK("-") TT_SUB;
+ CHECK("--") TT_DECR;
+ CHECK(".") TT_DOT;
+ CHECK("/") TT_DIV;
+ CHECK("\\") TT_VID;
+ CHECK(":") TT_DDOT;
+ CHECK("==") TT_EQ;
+ CHECK(";") TT_SEMICOLON;
+ CHECK("<<") TT_LSHIFT;
+ CHECK(">>") TT_RSHIFT;
+ CHECK("and") TT_AND;
+ CHECK("or") TT_OR;
+ CHECK("xor") TT_XOR;
+ CHECK("=") TT_ASSIGN;
+ CHECK("<") TT_LT;
+ CHECK(">") TT_GT;
+ CHECK(">=") TT_GE;
+ CHECK("<=") TT_LE;
+ CHECK("{") TT_PARANT_CL;
+ CHECK("}") TT_PARANT_CR;
+
+ return TT_NONE;
+}
+
+#define CASE(t,r) case t: return r;
+
+char*
+tt_get_name(TokenType tt_cur) {
+ switch (tt_cur) {
+ CASE(START_TERMINALS, "START_TERMINALS")
+ CASE(START_TYPES, "START_TYPES")
+ CASE(START_NUMERICAL, "START_NUMERICAL")
+ CASE(START_ASSIGNABLES, "START_ASSIGNABLES")
+ CASE(TT_IDENT, "TT_IDENT")
+ CASE(TT_DOUBLE,"TT_DOUBLE")
+ CASE(TT_STRING,"TT_STRING")
+ CASE(TT_INTEGER,"TT_INTEGER")
+ CASE(TT_BOOL,"TT_BOOL")
+ CASE(END_ASSIGNABLES, "END_ASSIGNABLES")
+ CASE(END_NUMERICAL, "END_NUMERICAL")
+ CASE(END_TYPES, "END_TYPES")
+
+ // Keywords
+ CASE(START_KEYWORDS, "START_KEYWORDS")
+ CASE(TT_ELSE,"TT_ELSE")
+ CASE(TT_BREAK,"TT_BREAK")
+ CASE(TT_IF,"TT_IF")
+ CASE(TT_IFNOT,"TT_IFNOT")
+ CASE(TT_RET,"TT_RET")
+ CASE(TT_CONST,"TT_CONST")
+ CASE(TT_PROC,"TT_PROC")
+ CASE(TT_FUNC,"TT_FUNC")
+ CASE(TT_MY,"TT_MY")
+ CASE(TT_WHILE,"TT_WHILE")
+ CASE(TT_UNTIL,"TT_UNTIL")
+ CASE(TT_NEXT,"TT_NEXT")
+ CASE(TT_DEFINED,"TT_DEFINED")
+ CASE(TT_UNDEF,"TT_UNDEF")
+ CASE(TT_INT,"TT_INT")
+ CASE(END_KEYWORDS, "END_KEYWORDS")
+
+ // Braces
+ CASE(START_PARANTS, "START_PARANTS")
+ CASE(TT_PARANT_CL,"TT_PARANT_CL")
+ CASE(TT_PARANT_CR,"TT_PARANT_CR")
+ CASE(TT_PARANT_L,"TT_PARANT_L")
+ CASE(TT_PARANT_R,"TT_PARANT_R")
+ CASE(END_PARANTS, "END_PARANTS")
+
+ // Operators
+ CASE(START_OPERATORS, "START_OPERATORS")
+ CASE(TT_ADD,"TT_ADD")
+ CASE(TT_ASSIGN,"TT_ASSIGN")
+ CASE(TT_COMMA,"TT_COMMA")
+ CASE(TT_DDOT,"TT_DDOT")
+ CASE(TT_DECR,"TT_DECR")
+ CASE(TT_DIV,"TT_DIV")
+ CASE(TT_VID,"TT_VID")
+ CASE(TT_DOT,"TT_DOT")
+ CASE(TT_EQ,"TT_EQ")
+ CASE(TT_LE,"TT_LE")
+ CASE(TT_LT,"TT_LT")
+ CASE(TT_GE,"TT_GE")
+ CASE(TT_GT,"TT_GT")
+ CASE(TT_INCR,"TT_INCR")
+ CASE(TT_LSHIFT,"TT_LSHIFT")
+ CASE(TT_RSHIFT,"TT_RSHIFT")
+ CASE(TT_AND,"TT_AND")
+ CASE(TT_OR,"TT_OR")
+ CASE(TT_XOR,"TT_XOR")
+ CASE(TT_NOT,"TT_NOT")
+ CASE(TT_MULT,"TT_MULT")
+ CASE(TT_NEQ,"TT_NEQ")
+ CASE(TT_RE,"TT_RE")
+ CASE(TT_NOTEQ,"TT_NOTEQ")
+ CASE(TT_SEMICOLON,"TT_SEMICOLON")
+ CASE(TT_SUB,"TT_SUB")
+ CASE(END_OPERATORS, "END_OPERATORS")
+ CASE(END_TERMINALS, "END_TERMINALS")
+
+ // Diverse
+ CASE(TT_NONE,"TT_NONE")
+ CASE(TT_END_OF_CODE,"TT_END_OF_CODE")
+ }
+
+ // Never reach this point
+ return "XXXXXXX";
+}
+
+Token*
+token_new(char *c_val, TokenType tt_cur, int i_line_nr, int i_pos_nr, char *c_filename) {
+ Token *p_token = token_new_dummy();
+
+ p_token->c_val = c_val;
+ p_token->i_val = 0;
+ p_token->d_val = 0;
+ p_token->tt_cur = tt_cur;
+ p_token->i_line_nr = i_line_nr;
+ p_token->i_pos_nr = i_pos_nr;
+ p_token->c_filename = c_filename;
+
+ switch (tt_cur) {
+ case TT_INTEGER:
+ p_token->i_val = atoi(c_val);
+ break;
+ case TT_DOUBLE:
+ {
+ p_token->d_val = atof(c_val);
+ break;
+ }
+ NO_DEFAULT;
+ }
+
+ return p_token;
+}
+
+Token*
+token_new_integer(int i_val) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_INTEGER);
+ token_set_ival(p_token, i_val);
+
+ return (p_token);
+}
+
+Token*
+token_new_double(double d_val) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_DOUBLE);
+ token_set_dval(p_token, d_val);
+
+ return (p_token);
+}
+
+Token*
+token_new_string(char *c_val) {
+ Token *p_token = token_new_dummy();
+ token_set_tt(p_token, TT_STRING);
+
+ p_token->c_val = calloc(strlen(c_val)+1, sizeof(char));
+ strcpy(p_token->c_val, c_val);
+
+ return (p_token);
+}
+
+
+Token*
+token_new_(char *c_val, TokenType tt_cur, char *c_filename) {
+ return token_new(c_val, tt_cur, -1, -1, c_filename);
+}
+
+Token*
+token_new_dummy() {
+ Token *p_token = malloc(sizeof(Token));
+
+ p_token->c_val = NULL;
+ p_token->tt_cur = TT_NONE;
+ p_token->i_line_nr = -1;
+ p_token->i_pos_nr = -1;
+ p_token->c_filename = NULL;
+ p_token->u_token_id = TOKEN_ID_COUNTER++;
+ p_token->i_ref_count = 0;
+
+ /* Register the token in the garbage collector */
+ garbage_add_token(p_token);
+
+ return p_token;
+}
+
+Token*
+token_new_copy(Token *p_token) {
+ Token *p_token_copy = malloc(sizeof(Token));
+ p_token->u_token_id = TOKEN_ID_COUNTER++;
+
+ if (p_token_copy == NULL)
+ ERROR("Memory alloc error");
+
+ token_copy_vals(p_token_copy, p_token);
+ p_token_copy->i_ref_count = 0;
+
+ /* Register the token in the garbage collector */
+ garbage_add_token(p_token_copy);
+
+ return (p_token_copy);
+}
+
+void token_copy_vals(Token *p_token_to, Token *p_token_from) {
+ int i_len;
+
+ // TODO: Check against mem leak
+ // if (p_token_to->c_val)
+ // free(p_token_to->c_val);
+
+ if (p_token_from->c_val) {
+ i_len = strlen(p_token_from->c_val);
+ p_token_to->c_val = calloc(i_len+1, sizeof(char));
+ strcpy(p_token_to->c_val, p_token_from->c_val);
+ } else {
+ p_token_to->c_val = NULL;
+ }
+
+ p_token_to->tt_cur = p_token_from->tt_cur;
+ p_token_to->i_val = p_token_from->i_val;
+ p_token_to->d_val = p_token_from->d_val;
+ p_token_to->i_line_nr = p_token_from->i_line_nr;
+ p_token_to->i_pos_nr = p_token_from->i_pos_nr;
+ p_token_to->c_filename = p_token_from->c_filename;
+}
+
+void
+token_delete_cb(void *p_void) {
+ token_delete(p_void);
+}
+
+void
+token_ref_down_cb(void *p_void) {
+ Token *p_token = p_void;
+ token_ref_down(p_token);
+}
+
+void*
+token_copy_cb(void *p_void) {
+ return (token_new_copy(p_void));
+}
+
+void
+token_delete(Token *p_token) {
+ if (token_ref_down(p_token) <= 0) {
+ if (p_token->i_ref_count == 0) {
+#ifdef DEBUG_TOKEN_REFCOUNT
+ printf("Token refcount debug: Token ref count is 0 == %d\n",
+ p_token->i_ref_count);
+#endif /* DEBUG_TOKEN_REFCOUNT */
+ if (p_token->c_val)
+ free(p_token->c_val);
+
+ free(p_token);
+ }
+#ifdef DEBUG_TOKEN_REFCOUNT
+ else {
+ printf("Token refcount debug: Token ref count is 0 > %d\n",
+ p_token->i_ref_count);
+ }
+#endif /* DEBUG_TOKEN_REFCOUNT */
+ }
+#ifdef DEBUG_TOKEN_REFCOUNT
+ else {
+ printf("Token refcount debug: Token ref count is 0 < %d\n",
+ p_token->i_ref_count);
+ }
+#endif /* DEBUG_TOKEN_REFCOUNT */
+}
+
+void
+token_print(Token *p_token) {
+ printf("(id=%05u, line=%05d, pos=%04d, type=%s, val=%s, ival=%d, dval=%f,"
+ " refs=%d)",
+ p_token->u_token_id,
+ p_token->i_line_nr,
+ p_token->i_pos_nr,
+ tt_get_name(p_token->tt_cur),
+ p_token->c_val,
+ p_token->i_val,
+ p_token->d_val,
+ p_token->i_ref_count);
+}
+
+void
+token_print_val(Token *p_token) {
+ TokenType tt = token_get_tt(p_token);
+ switch (tt) {
+ case TT_INTEGER:
+ printf("(%s, %d)", tt_get_name(tt), token_get_ival(p_token));
+ break;
+ case TT_DOUBLE:
+ printf("(%s, %f)", tt_get_name(tt), token_get_dval(p_token));
+ break;
+ case TT_STRING:
+ printf("(%s, %s)", tt_get_name(tt), token_get_val(p_token));
+ break;
+ default:
+ ERROR("Ouups(%s)!", tt_get_name(tt));
+ }
+}
+
+void
+token_print_cb(void *p_void) {
+ Token *p_token = p_void;
+ printf("Token ");
+ token_print(p_token);
+ printf("\n");
+}
diff --git a/src/core/token.h b/src/core/token.h
new file mode 100644
index 0000000..b363279
--- /dev/null
+++ b/src/core/token.h
@@ -0,0 +1,183 @@
+/*:*
+ *: File: ./src/core/token.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef TOKEN_H
+#define TOKEN_H
+
+#include "../defines.h"
+
+#define IS_TERMINAL(t) (START_TERMINALS < t && t < END_TERMINALS)
+#define IS_NOT_TERMINAL(t) !IS_TERMINAL(t)
+#define IS_TYPE(t) (START_TYPES < t && t < END_TYPES)
+#define IS_NOT_TYPE(t) !IS_TYPE(t)
+#define IS_KEYWORD(t) (START_KEYWORDS < t && t < END_KEYWORDS)
+#define IS_NOT_KEYWORD(t) !IS_KEYWORD(t)
+#define IS_OPERATOR(t) (START_OPERATORS < t && t < END_OPERATORS)
+#define IS_NOT_OPERATOR(t) !IS_OPERATOR(t)
+#define IS_NON_TERMINAL(t) (START_NON_TERMINALS < t && t < END_NON_TERMINALS)
+#define IS_NOT_NON_TERMINAL(t) !IS_NON_TERMINAL(t)
+#define IS_IDENT(t) (t == TT_IDENT)
+#define IS_NOT_IDENT(t) !(IS_IDENT(t))
+#define IS_ASSIGNABLE(t) (START_ASSIGNABLES < t && t < END_ASSIGNABLES)
+#define IS_NUMERICAL(t) (START_NUMERICAL < t && t < END_NUMERICAL)
+#define IS_NOT_NUMERICAL(t) !(IS_NUMERICAL(t))
+
+#define token_get_filename(t) \
+ (t->c_filename != NULL ? t->c_filename : "Code string")
+#define token_get_line_nr(t) t->i_line_nr
+#define token_get_pos_nr(t) t->i_pos_nr
+#define token_get_tt(t) (t ? t->tt_cur : TT_NONE)
+#define token_get_val(t) t->c_val
+#define token_get_ival(t) t->i_val
+#define token_get_dval(t) t->d_val
+#define token_set_tt(t,tt) t->tt_cur = tt
+#define token_set_val(t,c) t->c_val = c
+#define token_set_ival(t,i) t->i_val = i
+#define token_set_dval(t,d) t->d_val = d
+#define token_set_pos(t, l, p) t->i_line_nr = l; t->i_pos_nr = p
+#define token_get_posnr(t) t->i_pos_nr
+#define token_get_linenr(t) t->i_line_nr
+#define token_ref_up(t) ++t->i_ref_count
+#define token_ref_down(t) --t->i_ref_count
+
+typedef enum {
+ // Diverse
+ TT_NONE,
+ TT_END_OF_CODE,
+ TT_BOOL, // Temporaly disabled, maybe NUMERICAL in future again
+
+ // Diverse types
+ START_TERMINALS,
+ START_TYPES,
+ START_ASSIGNABLES,
+ START_NUMERICAL,
+ TT_INTEGER,
+ TT_DOUBLE,
+ END_NUMERICAL,
+ TT_STRING,
+ END_ASSIGNABLES,
+ TT_IDENT,
+ END_TYPES,
+
+ // Keywords
+ START_KEYWORDS,
+ TT_ELSE,
+ TT_BREAK,
+ TT_IF,
+ TT_IFNOT,
+ TT_RET,
+ TT_CONST,
+ TT_PROC,
+ TT_FUNC,
+ TT_MY,
+ TT_WHILE,
+ TT_UNTIL,
+ TT_NEXT,
+ TT_INT,
+ TT_DEFINED,
+ TT_UNDEF,
+ END_KEYWORDS,
+
+ START_PARANTS,
+ TT_PARANT_CL,
+ TT_PARANT_CR,
+ TT_PARANT_L,
+ TT_PARANT_R,
+ END_PARANTS,
+
+ // Operators
+ START_OPERATORS,
+ TT_ADD,
+ TT_AND,
+ TT_ASSIGN,
+ TT_COMMA,
+ TT_DDOT,
+ TT_DECR,
+ TT_DIV,
+ TT_DOT,
+ TT_EQ,
+ TT_GE,
+ TT_GT,
+ TT_INCR,
+ TT_LE,
+ TT_LSHIFT,
+ TT_LT,
+ TT_MULT,
+ TT_NEQ,
+ TT_NOT,
+ TT_NOTEQ,
+ TT_OR,
+ TT_RE,
+ TT_RSHIFT,
+ TT_SEMICOLON,
+ TT_SUB,
+ TT_VID,
+ TT_XOR,
+ END_OPERATORS,
+
+ END_TERMINALS,
+
+} TokenType;
+
+typedef struct {
+ TokenType tt_cur;
+ char *c_val;
+ int i_val;
+ double d_val;
+ int i_line_nr;
+ int i_pos_nr;
+ char *c_filename;
+ unsigned int u_token_id;
+ int i_ref_count;
+} Token;
+
+Token* token_new(char *c_val, TokenType tt_cur, int i_line_nr, int i_pos_nr, char *c_filename);
+Token* token_new_integer(int i_val);
+Token* token_new_couble(double d_val);
+Token* token_new_string(char *c_val);
+Token* token_new_copy(Token *p_token);
+Token* token_new_(char *c_val, TokenType tt_cur, char *c_filename);
+Token* token_new_dummy();
+void token_copy_vals(Token *p_token_to, Token *p_token_from);
+void token_delete(Token *p_token);
+void token_delete_cb(void *p_token);
+void token_ref_down_cb(void *p_token);
+void* token_copy_cb(void *p_token);
+char* tt_get_name(TokenType tt_cur);
+void token_print_cb(void *p_void);
+void token_print(Token *p_token);
+void token_print_val(Token *p_token);
+TokenType get_tt(char *c_token);
+
+#endif
diff --git a/src/data/array.c b/src/data/array.c
new file mode 100644
index 0000000..e893a6d
--- /dev/null
+++ b/src/data/array.c
@@ -0,0 +1,266 @@
+/*:*
+ *: File: ./src/data/array.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "array.h"
+
+Array*
+array_new() {
+ Array *p_array = malloc(sizeof(Array));
+
+ p_array->i_size = 0;
+ p_array->pp_ae = NULL;
+
+ return p_array;
+}
+
+
+void
+array_delete(Array *p_array) {
+ if (!p_array)
+ return;
+
+ if (p_array->i_size)
+ for (int i = p_array->i_size - 1; i >= 0; --i)
+ arrayelement_delete(p_array->pp_ae[i]);
+
+ if (p_array->pp_ae)
+ free(p_array->pp_ae);
+
+ free(p_array);
+}
+
+void
+array_set(Array *p_array, int i_index, void *p_val) {
+ if (p_array->i_size > i_index) {
+ p_array->pp_ae[i_index]->p_val = p_val;
+
+ } else {
+ array_resize(p_array, i_index + 1);
+ p_array->pp_ae[i_index]->p_val = p_val;
+ }
+}
+
+void
+array_insert(Array *p_array, int i_index, void *p_val) {
+ if (p_array->i_size <= i_index) {
+ array_set(p_array, i_index, p_val);
+
+ } else {
+ array_resize(p_array, p_array->i_size + 1);
+
+ ArrayElement *p_ae = p_array->pp_ae[p_array->i_size-1];
+ int i;
+ for (i = p_array->i_size - 1; i > i_index; --i)
+ p_array->pp_ae[i] = p_array->pp_ae[i-1];
+
+ p_array->pp_ae[i] = p_ae;
+ p_ae->p_val = p_val;
+ }
+}
+
+void*
+array_remove(Array *p_array, int i_index) {
+ if (p_array->i_size <= i_index)
+ return NULL;
+
+ ArrayElement *p_ae = p_array->pp_ae[i_index];
+ void *p_ret = p_ae->p_val;
+ int i;
+
+ for (i = i_index+1; i < p_array->i_size; ++i)
+ p_array->pp_ae[i-1] = p_array->pp_ae[i];
+
+ p_array->pp_ae[i-1] = p_ae;
+
+ array_resize(p_array, p_array->i_size - 1);
+
+ return p_ret;
+}
+
+void
+array_print_int(Array *p_array) {
+ printf("Array:");
+ for (int i = 0; i < p_array->i_size; ++i)
+ printf(" (%d,%d)", i, (int) array_get(p_array, i));
+ printf("\n");
+}
+
+void
+array_resize(Array *p_array, int i_size) {
+ if (i_size == p_array->i_size)
+ return;
+
+ if (i_size < p_array->i_size)
+ for (int i = p_array->i_size - 1; i >= i_size; --i)
+ arrayelement_delete(p_array->pp_ae[i]);
+
+ if (i_size == 0) {
+ free(p_array->pp_ae);
+ p_array->pp_ae = NULL;
+
+ } else if (p_array->pp_ae != NULL) {
+ p_array->pp_ae = realloc(p_array->pp_ae,
+ sizeof(ArrayElement) * i_size);
+
+ } else {
+ p_array->pp_ae = malloc(sizeof(ArrayElement) * i_size);
+ }
+
+ if (i_size > p_array->i_size)
+ for (int i = p_array->i_size; i < i_size; ++i)
+ p_array->pp_ae[i] = arrayelement_new(NULL);
+
+ p_array->i_size = i_size;
+}
+
+void*
+array_get(Array *p_array, int i_index) {
+ if (p_array->i_size > i_index)
+ return p_array->pp_ae[i_index]->p_val;
+
+ return NULL;
+}
+
+_Bool
+array_defined(Array *p_array, int i_index) {
+ if (i_index >= p_array->i_size)
+ return false;
+
+ return p_array->pp_ae[i_index]->p_val != NULL;
+}
+
+void
+array_splice(Array *p_array, int i_index, Array *p_array2) {
+ if (i_index >= array_get_size(p_array))
+ return;
+
+ array_remove(p_array, i_index);
+
+ int i_size1= array_get_size(p_array);
+ int i_size2 = array_get_size(p_array2);
+ int i_size = i_size1 + i_size2;
+
+ array_resize(p_array, i_size);
+
+ for (int i = i_size1 - 1; i >= i_index; --i)
+ p_array->pp_ae[i+i_size2]->p_val = p_array->pp_ae[i]->p_val;
+
+ for (int i = 0; i < i_size2; ++i)
+ p_array->pp_ae[i+i_index]->p_val = p_array2->pp_ae[i]->p_val;
+
+}
+
+void
+array_unshift(Array *p_array, void *p_void) {
+ int i_size = array_get_size(p_array);
+ array_set(p_array, i_size, p_void);
+}
+
+void
+array_push(Array *p_array, void *p_void) {
+ int i_size = array_get_size(p_array);
+ array_resize(p_array, ++i_size);
+
+ for (int i = i_size - 1; i > 0; --i)
+ p_array->pp_ae[i]->p_val = p_array->pp_ae[i-1]->p_val;
+
+ array_set(p_array, 0, p_void);
+}
+
+void
+array_iterate(Array *p_array, void (*func)(void *)) {
+ if (!p_array)
+ return;
+
+ for (int i = 0; i < array_get_size(p_array); ++i)
+ (*func) (array_get(p_array, i));
+}
+
+void
+array_iterate2(Array *p_array, void (*func)(void *, void *), void *p_void) {
+ if (!p_array)
+ return;
+
+ for (int i = 0; i < array_get_size(p_array); ++i)
+ (*func) (array_get(p_array, i), p_void);
+}
+
+ArrayElement*
+arrayelement_new(void *p_val) {
+ ArrayElement *p_ae = malloc(sizeof(ArrayElement));
+
+ p_ae->p_val = p_val;
+
+ return p_ae;
+}
+
+void
+arrayelement_delete(ArrayElement *p_ae) {
+ if (!p_ae)
+ return;
+
+ free(p_ae);
+}
+
+ArrayIterator*
+arrayiterator_new(Array *p_array) {
+ if (!p_array)
+ return NULL;
+
+ ArrayIterator *p_arrayiterator = malloc(sizeof(ArrayIterator));
+ p_arrayiterator->p_array = p_array;
+ p_arrayiterator->i_cur_pos = 0;
+
+ return p_arrayiterator;
+}
+
+void
+arrayiterator_delete(ArrayIterator *p_arrayiterator) {
+ if (p_arrayiterator)
+ free(p_arrayiterator);
+}
+
+_Bool
+arrayiterator_has_next(ArrayIterator *p_arrayiterator) {
+ return p_arrayiterator->i_cur_pos <
+ array_get_size(p_arrayiterator->p_array);
+}
+
+void*
+arrayiterator_next(ArrayIterator *p_arrayiterator) {
+ if (!arrayiterator_has_next(p_arrayiterator))
+ return NULL;
+
+ return array_get(p_arrayiterator->p_array, p_arrayiterator->i_cur_pos++);
+}
diff --git a/src/data/array.h b/src/data/array.h
new file mode 100644
index 0000000..a60fa03
--- /dev/null
+++ b/src/data/array.h
@@ -0,0 +1,86 @@
+/*:*
+ *: File: ./src/data/array.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef ARRAY_H
+#define ARRAY_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../defines.h"
+
+#define array_get_size(a) a->i_size
+#define array_empty(a) a->i_size == 0
+#define array_clear(a) array_resize(a, 0)
+#define array_get_first(a) array_get(a, 0)
+#define array_get_last(a) array_get(a, array_get_size(a)-1)
+
+typedef struct {
+ void *p_val;
+} ArrayElement;
+
+typedef struct {
+ ArrayElement **pp_ae;
+ int i_size;
+} Array;
+
+typedef struct {
+ Array *p_array;
+ int i_cur_pos;
+} ArrayIterator;
+
+Array *array_new();
+void array_delete(Array *p_array);
+void array_set(Array *p_array, int i_index, void *p_val);
+void array_insert(Array *p_array, int i_index, void *p_val);
+void *array_remove(Array *p_array, int i_index);
+void *array_get(Array *p_array, int i_index);
+void array_resize(Array *p_array, int i_size);
+_Bool array_defined(Array *p_array, int i_index);
+void array_print_int(Array *p_array);
+void array_splice(Array *p_array, int i_index, Array *p_array2);
+void array_push(Array *p_array, void *p_void);
+void array_unshift(Array *p_array, void *p_void);
+void array_iterate(Array *p_array, void (*func)(void *));
+void array_iterate2(Array *p_array, void (*func)(void *, void *),
+ void *p_void);
+
+ArrayElement *arrayelement_new(void *p_val);
+void arrayelement_delete(ArrayElement *p_ae);
+
+ArrayIterator *arrayiterator_new(Array *p_array);
+void arrayiterator_delete(ArrayIterator *p_arrayiterator);
+_Bool arrayiterator_has_next(ArrayIterator *p_arrayiterator);
+void *arrayiterator_next(ArrayIterator *p_arrayiterator);
+#endif
diff --git a/src/data/dat.c b/src/data/dat.c
new file mode 100644
index 0000000..1becf25
--- /dev/null
+++ b/src/data/dat.c
@@ -0,0 +1,267 @@
+/*:*
+ *: File: ./src/data/dat.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "dat.h"
+
+#include <stdlib.h>
+
+Dat*
+dat_new() {
+ Dat *p_dat = (Dat *) malloc(sizeof(Dat));
+
+ p_dat->p_first = 0;
+ p_dat->p_last = 0;
+ p_dat->i_size = 0;
+
+ return p_dat;
+}
+
+DatElem*
+datelem_new() {
+ return datelem_new_t(TYPE_UNKNOWN);
+}
+
+DatElem*
+datelem_new_t(TYPE type) {
+ DatElem *p_elem = (DatElem *) malloc(sizeof(DatElem));
+
+ p_elem->p_next = 0;
+ p_elem->p_val = 0;
+ p_elem->type = type;
+
+ return p_elem;
+}
+
+_Bool
+dat_empty(Dat *p_dat) {
+ if (p_dat == NULL)
+ return 0;
+
+ return p_dat->i_size == 0;
+}
+
+void
+dat_push(Dat *p_dat, void *p_val) {
+ dat_push_t(p_dat, p_val, TYPE_UNKNOWN);
+}
+
+void
+dat_push_t(Dat *p_dat, void *p_val, TYPE type) {
+ DatElem *p_elem = datelem_new_t(type);
+ p_elem->p_val = p_val;
+
+ if (0 == p_dat->i_size++)
+ p_dat->p_first = p_elem;
+ else
+ p_dat->p_last->p_next = p_elem;
+
+ p_dat->p_last = p_elem;
+}
+
+void*
+dat_pop(Dat *p_dat) {
+ TYPE type;
+ return dat_pop_t(p_dat, &type);
+}
+
+void*
+dat_pop_t(Dat *p_dat, TYPE *p_type) {
+ if (dat_empty(p_dat))
+ return 0;
+
+ DatElem *p_elem = p_dat->p_first;
+ p_dat->p_first = p_elem->p_next;
+
+ --p_dat->i_size;
+
+ void *p_ret = p_elem->p_val;
+ *p_type = p_elem->type;
+ free(p_elem);
+ return p_ret;
+}
+
+void
+dat_clear(Dat *p_dat) {
+ for (;!dat_empty(p_dat); dat_pop(p_dat));
+}
+
+void
+dat_delete(Dat *p_dat) {
+ dat_clear(p_dat);
+ free(p_dat);
+}
+
+unsigned
+dat_size(Dat *p_dat) {
+ return p_dat->i_size;
+}
+
+void
+dat_iterate(Dat *p_dat, void (*func)(void *)) {
+ DatElem *p_elem = p_dat->p_first;
+ while (p_elem) {
+ if (p_elem->p_val)
+ (*func) (p_elem->p_val);
+
+ p_elem = p_elem->p_next;
+ }
+}
+
+void
+dat_iterate_t(Dat *p_dat, void (*func)(void *, TYPE)) {
+ DatElem *p_elem = p_dat->p_first;
+ while (p_elem) {
+ if (p_elem->p_val)
+ (*func) (p_elem->p_val, p_elem->type);
+
+ p_elem = p_elem->p_next;
+ }
+}
+
+void
+dat_iterate_tl(Dat *p_dat, void (*func)(void *, TYPE, _Bool)) {
+ DatElem *p_elem = p_dat->p_first;
+ while (p_elem) {
+ if (p_elem->p_val)
+ (*func) (p_elem->p_val, p_elem->type, p_elem->p_next == NULL);
+
+ p_elem = p_elem->p_next;
+ }
+}
+
+void*
+dat_first(Dat *p_dat) {
+ if (dat_empty(p_dat))
+ return NULL;
+
+ return p_dat->p_first->p_val;
+}
+
+void*
+dat_second(Dat *p_dat) {
+ if ( 2 > dat_size(p_dat))
+ return NULL;
+
+ return p_dat->p_first->p_next->p_val;
+}
+
+void*
+dat_last(Dat *p_dat) {
+ if (dat_empty(p_dat))
+ return NULL;
+
+ return p_dat->p_last->p_val;
+}
+
+void*
+dat_first_t(Dat *p_dat, TYPE *p_type) {
+ if (dat_empty(p_dat))
+ return NULL;
+
+ *p_type = p_dat->p_first->type;
+ return p_dat->p_first->p_val;
+}
+
+void*
+dat_second_t(Dat *p_dat, TYPE *p_type) {
+ if ( 2 > dat_size(p_dat))
+ return NULL;
+
+ *p_type = p_dat->p_first->p_next->type;
+ return p_dat->p_first->p_next->p_val;
+}
+
+void*
+dat_last_t(Dat *p_dat, TYPE *p_type) {
+ if (dat_empty(p_dat))
+ return NULL;
+
+ *p_type = p_dat->p_last->type;
+ return p_dat->p_last->p_val;
+}
+
+DatIter*
+datiter_new(Dat *p_dat) {
+ DatIter *p_iter =
+ (DatIter *) malloc(sizeof(DatIter));
+
+ p_iter->p_current = NULL;
+ p_iter->p_next = p_dat->p_first;
+ p_iter->i_left = dat_size(p_dat);
+ p_iter->p_dat = p_dat;
+
+ return p_iter;
+}
+
+void
+datiter_delete(DatIter *p_iter) {
+ free(p_iter);
+}
+
+void
+datiter_skip(DatIter *p_iter, unsigned i_num) {
+ for (int i = 0; i < i_num; ++i)
+ datiter_next(p_iter);
+}
+
+void*
+datiter_next(DatIter *p_iter) {
+ TYPE type;
+ return datiter_next_t(p_iter, &type);
+}
+
+void*
+datiter_next_t(DatIter *p_iter, TYPE *p_type) {
+ if (p_iter->p_next == NULL)
+ return NULL;
+
+ void *p_ret = p_iter->p_next->p_val;
+ *p_type = p_iter->p_next->type;
+ p_iter->p_current = p_iter->p_next;
+ p_iter->p_next = p_iter->p_next->p_next;
+ --p_iter->i_left;
+
+ return p_ret;
+}
+
+unsigned
+datiter_left(DatIter *p_iter) {
+ return p_iter->i_left;
+}
+
+Dat*
+datiter_dat(DatIter *p_iter) {
+ return p_iter->p_dat;
+}
+
diff --git a/src/data/dat.h b/src/data/dat.h
new file mode 100644
index 0000000..82264e4
--- /dev/null
+++ b/src/data/dat.h
@@ -0,0 +1,88 @@
+/*:*
+ *: File: ./src/data/dat.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef DAT_H
+#define DAT_H
+
+#include "types.h"
+
+typedef struct DatElem_ {
+ struct DatElem_ *p_next;
+ void *p_val;
+ TYPE type;
+} DatElem;
+
+typedef struct {
+ DatElem *p_first;
+ DatElem *p_last;
+ unsigned i_size;
+} Dat;
+
+typedef struct {
+ unsigned i_left;
+ Dat *p_dat;
+ DatElem *p_current;
+ DatElem *p_next;
+} DatIter;
+
+Dat *dat_new();
+DatElem *datelem_new();
+DatElem *datelem_new_t(TYPE type);
+_Bool dat_empty(Dat *p_dat);
+void dat_push(Dat *p_dat, void *p_val);
+void dat_push_t(Dat *p_dat, void *p_val, TYPE type);
+void *dat_pop(Dat *p_dat);
+void *dat_pop_t(Dat *p_dat, TYPE *p_type);
+void dat_clear(Dat *p_dat);
+void dat_delete(Dat *p_dat);
+unsigned dat_size(Dat *p_dat);
+void dat_iterate(Dat *p_dat, void (*func)(void *));
+void dat_iterate_t(Dat *p_dat, void (*func)(void *, TYPE));
+void dat_iterate_tl(Dat *p_dat, void (*func)(void *, TYPE, _Bool));
+void *dat_first(Dat *p_dat);
+void *dat_second(Dat *p_dat);
+void *dat_last(Dat *p_dat);
+void *dat_first_t(Dat *p_dat, TYPE *p_type);
+void *dat_second_t(Dat *p_dat, TYPE *p_type);
+void *dat_last_t(Dat *p_dat, TYPE *p_type);
+
+DatIter *datiter_new(Dat *p_dat);
+void datiter_delete(DatIter *p_iter);
+void datiter_skip(DatIter *p_iter, unsigned i_num);
+void *datiter_next(DatIter *p_iter);
+void *datiter_next_t(DatIter *p_iter, TYPE *p_type);
+unsigned datiter_left(DatIter *p_iter);
+Dat *datiter_dat(DatIter *p_iter);
+
+#endif
diff --git a/src/data/hash.c b/src/data/hash.c
new file mode 100644
index 0000000..cc32a6b
--- /dev/null
+++ b/src/data/hash.c
@@ -0,0 +1,290 @@
+/*:*
+ *: File: ./src/data/hash.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "hash.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+Hash*
+hash_new(unsigned i_size) {
+ Hash *p_hash = (Hash *) malloc(sizeof(Hash));
+
+ p_hash->i_size = i_size;
+ p_hash->i_cur_size = 0;
+ p_hash->p_elems = (HashElem *) calloc(i_size, sizeof(HashElem));
+
+ /*Set all positions as "free" */
+ for (int i = 0; i < i_size; ++i)
+ p_hash->p_elems[i].flag = 'f';
+
+ return p_hash;
+}
+
+void
+hash_delete(Hash *p_hash) {
+ if (p_hash->p_elems) {
+ free(p_hash->p_elems);
+ p_hash->p_elems = 0;
+ }
+
+ free(p_hash);
+}
+
+RETCODE
+hash_insert_ht(Hash *p_hash, char *c_key, void *p_val, TYPE type) {
+ if (p_hash->i_cur_size == p_hash->i_size)
+ hash_size(p_hash, p_hash->i_size *2);
+
+ int i_addr = hash_getaddr(p_hash, c_key, free_ADDR);
+
+ if (i_addr == RET_ERROR )
+ return RET_NO_SPACE;
+
+ strncpy(p_hash->p_elems[i_addr].c_key, c_key, HASH_MKEYLEN);
+
+ p_hash->p_elems[i_addr].flag = 'o';
+ p_hash->p_elems[i_addr].type = type;
+ p_hash->p_elems[i_addr].p_val = p_val;
+ p_hash->i_cur_size++;
+
+ return RET_OK;
+}
+
+RETCODE
+hash_insert(Hash *p_hash, char *c_key, void *p_val) {
+ return hash_insert_ht(p_hash, c_key, p_val, TYPE_VOIDP);
+}
+
+void*
+hash_remove(Hash *p_hash, char *c_key) {
+ if (p_hash->i_cur_size < p_hash->i_size / 3)
+ hash_size(p_hash, p_hash->i_size / 2);
+
+ int i_addr = hash_getaddr(p_hash, c_key, OCC_ADDR);
+
+ if (i_addr == -1 )
+ return 0;
+
+ void *p_val = p_hash->p_elems[i_addr].p_val;
+ p_hash->p_elems[i_addr].flag = 'm';
+ p_hash->p_elems[i_addr].p_val = 0;
+ --p_hash->i_cur_size;
+
+ return p_val;
+}
+
+void*
+hash_get_ht(Hash *p_hash, char *c_key, TYPE *p_type) {
+ int i_addr;
+ return hash_get_ht_addr(p_hash, c_key, p_type, &i_addr);
+}
+
+void*
+hash_get_ht_addr(Hash *p_hash, char *c_key, TYPE *p_type, int *p_addr) {
+ int i_addr = *p_addr = hash_getaddr(p_hash, c_key, OCC_ADDR);
+
+ if (i_addr == -1 )
+ return 0;
+
+ *p_type = p_hash->p_elems[i_addr].type;
+ return p_hash->p_elems[i_addr].p_val;
+}
+
+void*
+hash_get(Hash *p_hash, char *c_key) {
+ TYPE type;
+ return hash_get_ht(p_hash, c_key, &type);
+}
+
+int
+hash_getaddr(Hash *p_hash, char *c_key, HASH_OP OP) {
+ int i_len = strlen(c_key);
+ int i_addr = 0;
+
+ if (i_len > HASH_MKEYLEN) {
+ ERROR(": Key length %d is greater than HASH_MKEYLEN = %d!",
+ i_len, HASH_MKEYLEN);
+ //i_len = HASH_MKEYLEN;
+ }
+
+ for (int i= 0; i < i_len; ++i)
+ i_addr = (i_addr *p_hash->i_size + (int) c_key[i]) % p_hash->i_size;
+
+ switch (OP) {
+ case free_ADDR:
+ if (!hash_addrisfree(p_hash,i_addr))
+ return i_addr;
+ break;
+
+ case OCC_ADDR:
+ if (!hash_addrisocc(p_hash,i_addr, c_key))
+ return i_addr;
+ break;
+
+ default:
+ return RET_ERROR;
+ }
+
+ return hash_nextaddr(p_hash, p_hash->i_size, c_key, i_addr, OP);
+}
+
+RETCODE
+hash_addrisfree(Hash *p_hash, int i_addr) {
+ if (p_hash->p_elems[i_addr].flag == 'f' ||
+ p_hash->p_elems[i_addr].flag == 'm')
+ return RET_OK;
+
+ return RET_ERROR;
+}
+
+RETCODE
+hash_addrisocc(Hash *p_hash, int i_addr, char *c_key) {
+ if (p_hash->p_elems[i_addr].flag == 'o' &&
+ !strcmp(p_hash->p_elems[i_addr].c_key, c_key))
+ return RET_OK;
+
+ return RET_ERROR;
+}
+
+int
+hash_nextaddr(Hash *p_hash, int i_max_tries, char *c_key, int i_addr,
+ HASH_OP OP) {
+ if ( --i_max_tries < 0 )
+ return RET_ERROR;
+
+ i_addr = (i_addr + 1) % p_hash->i_size;
+
+ switch (OP) {
+ case free_ADDR:
+ if (!hash_addrisfree(p_hash,i_addr))
+ return i_addr;
+ break;
+
+ case OCC_ADDR:
+ if (!hash_addrisocc(p_hash,i_addr, c_key))
+ return i_addr;
+ break;
+ }
+
+ return hash_nextaddr(p_hash, i_max_tries, c_key, i_addr, OP);
+}
+
+void
+hash_print(Hash *p_hash) {
+ printf("hash_print [size:%d,cur:%d] syntax (flag[,key][=TYPE[<val>]]):\n -> ",
+ p_hash->i_size,p_hash->i_cur_size);
+
+ for (int i = 0; i < p_hash->i_size; ++i) {
+ switch (p_hash->p_elems[i].flag) {
+ case 'f':
+ printf("(f");
+ break;
+ case 'm':
+ printf("(m,%s=", p_hash->p_elems[i].c_key);
+ hash_print_addrval(p_hash, i);
+ break;
+ case 'o':
+ printf("(o,%s=", p_hash->p_elems[i].c_key);
+ hash_print_addrval(p_hash, i);
+ break;
+ }
+ printf(") ");
+ }
+
+ printf("\n");
+
+}
+
+void
+hash_print_addrval(Hash *p_hash, int i_addr) {
+ switch (p_hash->p_elems[i_addr].type) {
+ case TYPE_NUMBER: {
+ double d_val = *(double *) p_hash->p_elems[i_addr].p_val;
+
+ if ( (int) d_val == d_val )
+ printf("TYPE_NUMBER<%.0f>",d_val);
+ else
+ printf("TYPE_NUMBER<%f>",d_val);
+ }
+ break;
+
+ case TYPE_STRING:
+ printf("TYPE_STRING<%s>", (char *) p_hash->p_elems[i_addr].p_val);
+ break;
+
+ case TYPE_VOIDP:
+ printf("TYPE_VOIDP");
+ break;
+
+ default:
+ printf("UNKNOWN");
+ break;
+ }
+}
+
+RETCODE
+hash_size(Hash *p_hash, int i_size) {
+ if (i_size < p_hash->i_cur_size) {
+ ERROR("The new hash has not enough elements"
+ "to contain the old hash!");
+ }
+
+ HashElem *p_old_elems = p_hash->p_elems;
+ unsigned i_old_size = p_hash->i_size;
+
+ p_hash->p_elems = (HashElem *) calloc(i_size, sizeof(HashElem));
+ p_hash->i_size = i_size;
+ p_hash->i_cur_size = 0;
+
+ /*Set all positions as "free" */
+ for (int i = 0; i < i_size; ++i)
+ p_hash->p_elems[i].flag = 'f';
+
+ for (int i = 0; i < i_old_size; ++i)
+ if (p_old_elems[i].flag == 'o')
+ hash_insert_ht(p_hash, p_old_elems[i].c_key,
+ p_old_elems[i].p_val, p_old_elems[i].type);
+
+ free(p_old_elems);
+ return RET_OK;
+}
+
+void
+hash_iterate(Hash *p_hash, void (*func)(void *)) {
+ for (int i = 0; i < p_hash->i_size; ++i)
+ if (p_hash->p_elems[i].flag == 'o')
+ (*func) (p_hash->p_elems[i].p_val);
+}
diff --git a/src/data/hash.h b/src/data/hash.h
new file mode 100644
index 0000000..8616549
--- /dev/null
+++ b/src/data/hash.h
@@ -0,0 +1,80 @@
+/*:*
+ *: File: ./src/data/hash.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef HASH_H
+#define HASH_H
+
+#include "../defines.h"
+#include "types.h"
+
+typedef enum HASH_OP_ {
+ free_ADDR,
+ OCC_ADDR
+} HASH_OP;
+
+typedef struct {
+ char c_key[HASH_MKEYLEN];
+ char flag;
+ TYPE type;
+ void *p_val;
+} HashElem;
+
+typedef struct {
+ HashElem *p_elems;
+ unsigned i_size;
+ unsigned i_cur_size;
+} Hash;
+
+Hash*hash_new(unsigned i_size);
+void hash_delete(Hash *p_hash);
+RETCODE hash_insert(Hash *p_hash, char *c_key, void *p_val);
+RETCODE hash_insert_ht(Hash *p_hash, char *c_key, void *p_val, TYPE type);
+void*hash_get(Hash *p_hash, char *c_key);
+void*hash_get_ht(Hash *p_hash, char *c_key, TYPE *p_type);
+void*hash_get_ht_addr(Hash *p_hash, char *c_key, TYPE *p_type, int *p_addr);
+void*hash_remove(Hash *p_hash, char *c_key);
+void hash_print(Hash *p_hash);
+void hash_print_addrval(Hash *p_hash, int i_addr);
+RETCODE hash_size(Hash *p_hash, int i_size);
+
+int hash_getaddr(Hash *p_hash, char *c_key, HASH_OP OP);
+RETCODE hash_addrisfree(Hash *p_hash, int i_addr);
+RETCODE hash_addrisocc(Hash *p_hash, int i_addr, char *c_key);
+int hash_nextaddr(Hash *p_hash, int i_max_tries, char *c_key, int i_addr, HASH_OP OP);
+void hash_iterate(Hash *p_hash, void (*func)(void *));
+
+#define hash_get_cur_size(hash) hash->i_cur_size
+#define hash_get_size(hash) hash->i_size
+
+#endif
diff --git a/src/data/list.c b/src/data/list.c
new file mode 100644
index 0000000..00e5a72
--- /dev/null
+++ b/src/data/list.c
@@ -0,0 +1,458 @@
+/*:*
+ *: File: ./src/data/list.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "list.h"
+
+List*
+list_new() {
+ List *p_list = malloc(sizeof(List));
+
+ p_list->p_first = NULL;
+ p_list->p_last = NULL;
+ p_list->i_size = 0;
+
+ return p_list;
+}
+
+void
+_list_copy_cb(void *p_void1, void *p_cpy) {
+ ListElem *p_elem = p_void1;
+ list_add_back(p_cpy, p_elem->p_val);
+}
+
+List*
+list_copy(List *p_list) {
+ List *p_list_cpy = list_new();
+ list_iterate2(p_list, _list_copy_cb, p_list_cpy);
+ return (p_list_cpy);
+}
+
+List*
+list_copy2(List *p_list, void* (*func)(void *)) {
+ List *p_list_cpy = list_new();
+ ListIterator *p_iter = listiterator_new(p_list);
+
+ while (listiterator_has_next(p_iter))
+ list_add_back(p_list_cpy, (*func) (listiterator_next(p_iter)));
+
+ listiterator_delete(p_iter);
+
+ return (p_list_cpy);
+}
+
+ListElem*
+listelem_new() {
+ ListElem *p_elem = malloc(sizeof(ListElem));
+
+ p_elem->p_next = NULL;
+ p_elem->p_prev = NULL;
+ p_elem->p_val = NULL;
+ return p_elem;
+}
+
+_Bool
+list_empty(List *p_list) {
+ return p_list->i_size == 0;
+}
+
+void
+list_concat_front(List *p_list1, List *p_list2) {
+ if (!p_list1 || !p_list2 || !p_list2->p_last)
+ return;
+
+ ListElem *p_first = p_list1->p_first;
+
+ if (!p_first) {
+ p_list1->p_first = p_list2->p_first;
+ p_list1->p_last = p_list2->p_last;
+
+ } else {
+ p_list2->p_last->p_next = p_list1->p_first;
+ p_list1->p_first->p_prev = p_list2->p_last;
+ p_list1->p_first = p_list2->p_first;
+ }
+
+ p_list1->i_size += p_list2->i_size;
+ p_list2->i_size = 0;
+ p_list2->p_first = NULL;
+ p_list2->p_last = NULL;
+}
+
+void
+list_concat_back(List *p_list1, List *p_list2) {
+ if (!p_list1 || !p_list2 || !p_list2->p_first)
+ return;
+
+ ListElem *p_last = p_list1->p_last;
+
+ if (!p_last) {
+ p_list1->p_first = p_list2->p_first;
+ p_list1->p_last = p_list2->p_last;
+
+ } else {
+ p_last->p_next = p_list2->p_first;
+ p_list2->p_first->p_prev = p_last;
+ p_list1->p_last = p_list2->p_last;
+ }
+
+ p_list1->i_size += p_list2->i_size;
+ p_list2->i_size = 0;
+ p_list2->p_first = NULL;
+ p_list2->p_last = NULL;
+
+}
+
+void
+list_add_front(List *p_list, void *p_val) {
+ ListElem *p_elem = listelem_new();
+
+ p_elem->p_val = p_val;
+ if (p_list->p_first == NULL) {
+ p_list->p_first = p_elem;
+ p_list->p_last = p_elem;
+
+ } else {
+ p_elem->p_next = p_list->p_first;
+ p_list->p_first->p_prev = p_elem;
+ p_list->p_first = p_elem;
+ }
+
+ ++p_list->i_size;
+}
+
+void
+list_add_back(List *p_list, void *p_val) {
+ ListElem *p_elem = listelem_new();
+
+ p_elem->p_val = p_val;
+ if (p_list->p_last == NULL) {
+ p_list->p_first = p_elem;
+ p_list->p_last = p_elem;
+
+ } else {
+ p_elem->p_prev = p_list->p_last;
+ p_list->p_last->p_next = p_elem;
+ p_list->p_last = p_elem;
+ }
+
+ ++p_list->i_size;
+}
+
+void*
+list_remove_front(List *p_list) {
+ if (list_empty(p_list))
+ return NULL;
+
+ ListElem *p_elem = p_list->p_first;
+ p_list->p_first = p_elem->p_next;
+
+ if (p_list->p_first)
+ p_list->p_first->p_prev = NULL;
+
+ void *p_val = p_elem->p_val;
+ free(p_elem);
+
+ --p_list->i_size;
+
+ return p_val;
+}
+
+void*
+list_remove_back(List *p_list) {
+ if (list_empty(p_list))
+ return NULL;
+
+ ListElem *p_elem = p_list->p_last;
+ p_list->p_last = p_elem->p_prev;
+ p_list->p_last->p_next = NULL;
+
+ void *p_val = p_elem->p_val;
+ free(p_elem);
+
+ --p_list->i_size;
+
+ return p_val;
+}
+
+void
+list_clear(List *p_list) {
+ for (;!list_empty(p_list); list_remove_front(p_list));
+}
+
+void
+list_clear_and_free_vals(List *p_list) {
+ void *p_void = NULL;
+ for (;!list_empty(p_list); p_void = list_remove_front(p_list))
+ if (p_void)
+ free(p_void);
+}
+
+void
+list_delete(List *p_list) {
+ list_clear(p_list);
+ free(p_list);
+}
+
+void
+list_delete_cb(void *p_list) {
+ list_delete(p_list);
+}
+
+void
+list_delete_and_free_vals(List *p_list) {
+ list_clear_and_free_vals(p_list);
+ free(p_list);
+}
+
+unsigned
+list_size(List *p_list) {
+ return p_list->i_size;
+}
+
+void
+list_iterate(List *p_list, void (*func)(void *)) {
+ ListElem *p_elem = p_list->p_first;
+
+ while (p_elem) {
+ (*func) (p_elem->p_val);
+ p_elem = p_elem->p_next;
+ }
+}
+
+void
+list_iterate2(List *p_list, void (*func)(void *, void *), void *p_void) {
+ ListElem *p_elem = p_list->p_first;
+
+ while (p_elem) {
+ (*func) (p_elem->p_val, p_void);
+ p_elem = p_elem->p_next;
+ }
+}
+
+void
+list_iterate2_ptr(List *p_list, void (*func)(void *, void *), void *p_void) {
+ ListElem *p_elem = p_list->p_first;
+
+ while (p_elem) {
+ (*func) (&p_elem->p_val, p_void);
+ p_elem = p_elem->p_next;
+ }
+}
+
+void
+list_iterate3(List *p_list, void (*func)(void *, void *, void *), void *p_void1, void *p_void2) {
+ ListElem *p_elem = p_list->p_first;
+
+ while (p_elem) {
+ (*func) (p_elem->p_val, p_void1, p_void2);
+ p_elem = p_elem->p_next;
+ }
+}
+
+void
+list_iterate3_ptr(List *p_list, void (*func)(void *, void *, void *),
+ void *p_void1, void *p_void2) {
+ ListElem *p_elem = p_list->p_first;
+
+ while (p_elem) {
+ (*func) (&p_elem->p_val, p_void1, p_void2);
+ p_elem = p_elem->p_next;
+ }
+}
+
+void
+list_remove_elem(List *p_list, ListElem *p_elem_remove) {
+ ListElem *p_elem = p_list->p_first;
+
+ if (p_elem == p_elem_remove) {
+ p_list->p_first = p_elem->p_next;
+ p_list->p_first->p_prev = NULL;
+ --p_list->i_size;
+ return;
+ }
+
+ while ((p_elem = p_elem->p_next)) {
+ if (p_elem == p_elem_remove) {
+ ListElem *p_prev = p_elem->p_prev;
+ ListElem *p_next = p_elem->p_next;
+
+ if (p_next) {
+ p_prev->p_next = p_next;
+ p_next->p_prev = p_prev;
+
+ } else {
+ p_prev->p_next = NULL;
+ p_list->p_last = p_prev;
+ }
+
+ --p_list->i_size;
+ free(p_elem_remove);
+ return;
+ }
+ }
+}
+
+ListIterator*
+listiterator_new(List *p_list) {
+ if (!p_list)
+ return NULL;
+
+ ListIterator *p_iter = malloc(sizeof(ListIterator));
+
+ p_iter->p_cur = p_list->p_first;
+ p_iter->b_reverse = false;
+ p_iter->func = NULL;
+
+ return p_iter;
+}
+
+ListIterator*
+listiterator_new_reverse(List *p_list) {
+ if (!p_list)
+ return NULL;
+
+ ListIterator *p_iter = listiterator_new(p_list);
+
+ p_iter->p_cur = p_list->p_last;
+ p_iter->b_reverse = true;
+
+ return p_iter;
+}
+
+void
+listiterator_delete(ListIterator *p_iter) {
+ if (p_iter)
+ free(p_iter);
+}
+
+void*
+listiterator_next(ListIterator *p_iter) {
+ if (p_iter->p_cur) {
+ void *p_ret = p_iter->p_cur->p_val;
+
+ if (p_iter->b_reverse)
+ p_iter->p_cur = p_iter->p_cur->p_prev;
+
+ else
+ p_iter->p_cur = p_iter->p_cur->p_next;
+
+ if (p_iter->func)
+ return ((*p_iter->func) (p_ret));
+
+ else
+ return (p_ret);
+ }
+
+ return (NULL);
+}
+
+void*
+listiterator_prev(ListIterator *p_iter) {
+ if (p_iter->p_cur) {
+ void *p_ret = p_iter->p_cur->p_val;
+
+ if (!p_iter->b_reverse)
+ p_iter->p_cur = p_iter->p_cur->p_prev;
+
+ else
+ p_iter->p_cur = p_iter->p_cur->p_next;
+
+ if (p_iter->func)
+ return ((*p_iter->func) (p_ret));
+
+ else
+ return (p_ret);
+ }
+
+ return (NULL);
+}
+
+void*
+listiterator_current(ListIterator *p_iter) {
+ if (p_iter->p_cur)
+ return (p_iter->p_cur->p_val);
+
+ return (NULL);
+}
+
+void*
+listiterator_end(ListIterator *p_iter) {
+ void *p_ret = NULL;
+
+ while (listiterator_has_next(p_iter))
+ p_ret = listiterator_next(p_iter);
+
+ return (p_ret);
+}
+
+ListElem*
+listiterator_next_elem(ListIterator *p_iter) {
+ if (p_iter->p_cur) {
+ ListElem *p_ret = p_iter->p_cur;
+
+ p_iter->p_cur = p_iter->b_reverse ?
+ p_iter->p_cur->p_prev : p_iter->p_cur->p_next;
+
+ return (p_ret);
+ }
+
+ return (NULL);
+}
+
+_Bool
+listiterator_has_next(ListIterator *p_iter) {
+ return (p_iter->p_cur != NULL ? true : false);
+}
+
+
+ListIteratorState*
+listiterator_get_state(ListIterator *p_iter) {
+ ListIteratorState *p_state = malloc(sizeof(ListIteratorState));
+
+ p_state->p_cur = p_iter->p_cur;
+ p_state->b_reverse = p_iter->b_reverse;
+
+ return (p_state);
+}
+
+void
+listiterator_set_state(ListIterator *p_iter, ListIteratorState *p_state) {
+ p_iter->p_cur = p_state->p_cur;
+ p_iter->b_reverse = p_state->b_reverse;
+}
+
+void
+listiteratorstate_delete(ListIteratorState *p_state) {
+ free(p_state);
+}
diff --git a/src/data/list.h b/src/data/list.h
new file mode 100644
index 0000000..cb22887
--- /dev/null
+++ b/src/data/list.h
@@ -0,0 +1,105 @@
+/*:*
+ *: File: ./src/data/list.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef LIST_H
+#define LIST_H
+
+#include <stdlib.h>
+
+#include "../defines.h"
+
+#define list_first(l) l->p_first->p_val
+#define list_last(l) l->p_last->p_val
+#define listiterator_set_callback(i,cb) i->func = cb
+
+typedef struct ListElem_ {
+ struct ListElem_ *p_next;
+ struct ListElem_ *p_prev;
+ void *p_val;
+} ListElem;
+
+typedef struct {
+ ListElem *p_first;
+ ListElem *p_last;
+ unsigned i_size;
+} List;
+
+typedef struct {
+ ListElem *p_cur;
+ _Bool b_reverse;
+ void* (*func)(void *);
+} ListIterator;
+
+typedef struct {
+ ListElem *p_cur;
+ _Bool b_reverse;
+} ListIteratorState;
+
+List *list_new();
+List *list_copy(List *p_list);
+List *list_copy2(List *p_list, void* (*func)(void *));
+ListElem *listelem_new();
+_Bool list_empty(List *p_list);
+void list_concat_front(List *p_list1, List *p_list2);
+void list_concat_back(List *p_list1, List *p_list2);
+void list_add_front(List *p_list, void *p_val);
+void list_add_back(List *p_list, void *p_val);
+void *list_remove_front(List *p_list);
+void *list_remove_back(List *p_list);
+void list_clear(List *p_list);
+void list_clear_and_free_vals(List *p_list);
+void list_delete(List *p_list);
+void list_delete_cb(void *p_list);
+void list_delete_and_free_vals(List *p_list);
+unsigned list_size(List *p_list);
+void list_iterate(List *p_list, void (*func)(void *));
+void list_iterate2_ptr(List *p_list, void (*func)(void *, void *), void *p_void);
+void list_iterate2(List *p_list, void (*func)(void *, void *), void *p_void);
+void list_iterate3(List *p_list, void (*func)(void *, void *, void *), void *p_void1, void *p_void2);
+void list_iterate3_ptr(List *p_list, void (*func)(void *, void *, void *), void *p_void1, void *p_void2);
+ListIterator *listiterator_new(List *p_list);
+ListIterator *listiterator_new_reverse(List *p_list);
+void listiterator_delete(ListIterator *p_iter);
+void *listiterator_next(ListIterator *p_iter);
+void *listiterator_prev(ListIterator *p_iter);
+void *listiterator_current(ListIterator *p_iter);
+void *listiterator_end(ListIterator *p_iter);
+_Bool listiterator_has_next(ListIterator *p_iter);
+ListElem* listiterator_next_elem(ListIterator *p_iter);
+void list_remove_elem(List *p_list, ListElem *p_elem_remove);
+ListIteratorState* listiterator_get_state(ListIterator *p_iter);
+void listiterator_set_state(ListIterator *p_iter, ListIteratorState *p_state);
+void listiteratorstate_delete(ListIteratorState *p_state);
+
+#endif
diff --git a/src/data/map.c b/src/data/map.c
new file mode 100644
index 0000000..24c8ac0
--- /dev/null
+++ b/src/data/map.c
@@ -0,0 +1,283 @@
+/*:*
+ *: File: ./src/data/map.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "map.h"
+
+Map*
+map_new(int i_max_size) {
+ return map_new_named(i_max_size, "noname");
+}
+
+Map*
+map_new_named(int i_max_size, char *c_name) {
+ Map *p_map = malloc(sizeof(Map));
+
+ p_map->c_name = c_name;
+ p_map->pc_keys = calloc(i_max_size, sizeof(char*));
+ p_map->pp_vals = calloc(i_max_size, sizeof(void*));
+
+ for (int i = 0; i < i_max_size; ++i) {
+ p_map->pc_keys[i] = NULL;
+ p_map->pp_vals[i] = NULL;
+ }
+
+ p_map->i_size = 0;
+ p_map->i_max_size = i_max_size;
+
+ return p_map;
+}
+
+_Bool
+map_empty(Map *p_map) {
+ return p_map->i_size == 0;
+}
+
+_Bool
+map_full(Map *p_map) {
+ return p_map->i_size == p_map->i_max_size;
+}
+
+int
+map_next_free_addr(Map *p_map) {
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] == NULL)
+ return i;
+
+ ERROR("No free space left in the map (%s)", p_map->c_name);
+
+ // This point should not be reached!
+ return 0;
+}
+
+_Bool
+map_insert(Map *p_map, char *c_key, void *p_val) {
+ int i_free_addr = map_next_free_addr(p_map);
+ int i_len = strlen(c_key);
+
+ p_map->pc_keys[i_free_addr] = STR_NEW(i_len+1);
+ strncpy(p_map->pc_keys[i_free_addr], c_key, i_len);
+ p_map->pp_vals[i_free_addr] = p_val;
+
+ ++p_map->i_size;
+ return true;
+}
+
+_Bool
+map_insert2(Map *p_map, char *c_key1, char *c_key2, void *p_val) {
+ char c_key[HASH_MKEYLEN];
+ sprintf(c_key, "%s%s%s", c_key1, SEP, c_key2);
+ return map_insert(p_map, c_key, p_val);
+}
+
+_Bool
+map_insert_if_not_exists(Map *p_map, char *c_key, void *p_val) {
+ void *p_void = map_get(p_map, c_key);
+
+ if (p_void)
+ return false;
+
+ return map_insert(p_map, c_key, p_val);
+
+ return true;
+}
+
+void
+map_remove(Map *p_map, char *c_key) {
+ if (map_empty(p_map))
+ return;
+
+ int i_index = map_get_addr(p_map, c_key);
+ if (i_index < 0)
+ return;
+
+ free(p_map->pc_keys[i_index]);
+ p_map->pc_keys[i_index] = NULL;
+ p_map->pp_vals[i_index] = NULL;
+ --p_map->i_size;
+}
+
+void*
+map_get(Map *p_map, char *c_key) {
+ if (map_empty(p_map))
+ return NULL;
+
+ int i_index = map_get_addr(p_map, c_key);
+ return i_index >= 0 ? p_map->pp_vals[i_index] : NULL;
+}
+
+void*
+map_get2(Map *p_map, char *c_key1, char *c_key2) {
+ char c_key[HASH_MKEYLEN];
+ sprintf(c_key, "%s%s%s", c_key1, SEP, c_key2);
+ return map_get(p_map, c_key);
+}
+
+
+_Bool
+map_exists(Map *p_map, char *c_key) {
+ if (map_empty(p_map))
+ return false;
+
+ int i_index = map_get_addr(p_map, c_key);
+ return i_index >= 0 ? true : false;
+}
+
+_Bool
+map_exists2(Map *p_map, char *c_key1, char *c_key2) {
+ if (map_empty(p_map))
+ return false;
+
+ char c_key[HASH_MKEYLEN];
+ sprintf(c_key, "%s%s%s:", c_key1, SEP, c_key2);
+
+ int i_index = map_get_addr(p_map, c_key);
+ return i_index >= 0 ? true : false;
+}
+
+char*
+map_get_key(Map *p_map, void *p_val) {
+ if (map_empty(p_map))
+ return NULL;
+
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if ((unsigned) p_map->pp_vals[i] == (unsigned) p_val)
+ return p_map->pc_keys[i];
+
+ return NULL;
+}
+
+int
+map_get_addr(Map *p_map, char *c_key) {
+ if (map_empty(p_map))
+ return -1;
+
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL && strcmp(p_map->pc_keys[i], c_key) == 0)
+ return i;
+
+ return -1;
+}
+
+void
+map_clear(Map *p_map) {
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL) {
+ free(p_map->pc_keys[i]);
+ p_map->pc_keys[i] = NULL;
+ p_map->pp_vals[i] = NULL;
+ }
+
+ p_map->i_size = 0;
+}
+
+void
+map_clear_and_free_vals(Map *p_map) {
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL) {
+ free(p_map->pc_keys[i]);
+
+ if (p_map->pp_vals[i])
+ free(p_map->pp_vals[i]);
+
+ p_map->pc_keys[i] = NULL;
+ p_map->pp_vals[i] = NULL;
+ }
+
+ p_map->i_size = 0;
+}
+
+void
+map_delete(Map *p_map) {
+ map_clear(p_map);
+ free(p_map);
+}
+
+void
+map_delete_and_free_vals(Map *p_map) {
+ map_clear_and_free_vals(p_map);
+ free(p_map);
+}
+
+void
+map_print(Map *p_map) {
+ printf("Map<size=%d, max_size=%d>:",
+ map_get_size(p_map), map_get_max_size(p_map));
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL)
+ printf("(%d,%s)", i, p_map->pc_keys[i]);
+ puts("");
+}
+
+void
+map_iterate(Map *p_map, void (*func) (void *)) {
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL)
+ (*func) (p_map->pp_vals[i]);
+}
+
+void
+map_iterate_keys(Map *p_map, void (*func) (void *, char *)) {
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL)
+ (*func) (p_map->pp_vals[i], p_map->pc_keys[i]);
+}
+
+void
+map_iterate2(Map *p_map, void (*func) (void *, void *), void *p_void) {
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL)
+ (*func) (p_map->pp_vals[i], p_void);
+}
+
+void
+map_iterate2_keys(Map *p_map, void (*func) (void *, void *, char *), void *p_void) {
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL)
+ (*func) (p_map->pp_vals[i], p_void, p_map->pc_keys[i]);
+}
+
+void
+map_iterate3(Map *p_map, void (*func) (void *, void *, void *), void *p_void1, void *p_void2) {
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL)
+ (*func) (p_map->pp_vals[i], p_void1, p_void2);
+}
+
+void
+map_iterate3_keys(Map *p_map, void (*func) (void *, void *, void *, char *), void *p_void1, void *p_void2) {
+ for (int i = 0; i < p_map->i_max_size; ++i)
+ if (p_map->pc_keys[i] != NULL)
+ (*func) (p_map->pp_vals[i], p_void1, p_void2, p_map->pc_keys[i]);
+}
+
diff --git a/src/data/map.h b/src/data/map.h
new file mode 100644
index 0000000..4ea6184
--- /dev/null
+++ b/src/data/map.h
@@ -0,0 +1,82 @@
+/*:*
+ *: File: ./src/data/map.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef MAP_H
+#define MAP_H
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "../defines.h"
+#define SEP "::"
+
+typedef struct {
+ char *c_name;
+ char **pc_keys;
+ void **pp_vals;
+ int i_size;
+ int i_max_size;
+} Map;
+
+Map *map_new(int i_max_size);
+Map *map_new_named(int i_max_size, char *c_name);
+_Bool map_empty(Map *p_map);
+_Bool map_full(Map *p_map);
+int map_next_free_addr(Map *p_map);
+_Bool map_insert(Map *p_map, char *c_key, void *p_val);
+_Bool map_insert2(Map *p_map, char *c_key1, char *c_key2, void *p_val);
+_Bool map_insert_if_not_exists(Map *p_map, char *c_key, void *p_val);
+void map_remove(Map *p_map, char *c_key);
+void *map_get(Map *p_map, char *c_key);
+void *map_get2(Map *p_map, char *c_key1, char *c_key2);
+_Bool map_exists(Map *p_map, char *c_key);
+_Bool map_exists2(Map *p_map, char *c_key1, char *c_key2);
+char *map_get_key(Map *p_map, void *p_val);
+int map_get_addr(Map *p_map, char *c_key);
+void map_clear(Map *p_map);
+void map_clear_and_free_vals(Map *p_map);
+void map_delete(Map *p_map);
+void map_delete_and_free_vals(Map *p_map);
+void map_print(Map *p_map);
+void map_iterate(Map *p_map, void (*func) (void *));
+void map_iterate_keys(Map *p_map, void (*func) (void *, char *));
+void map_iterate2(Map *p_map, void (*func) (void *, void *), void *p_void);
+void map_iterate2_keys(Map *p_map, void (*func) (void *, void *, char *), void *p_void);
+void map_iterate3(Map *p_map, void (*func) (void *, void *, void *), void *p_void1, void *p_void2);
+void map_iterate3_keys(Map *p_map, void (*func) (void *, void *, void *, char *), void *p_void1, void *p_void2);
+
+#define map_get_size(map) map->i_size
+#define map_get_max_size(map) map->i_max_size
+
+#endif
diff --git a/src/data/queue.c b/src/data/queue.c
new file mode 100644
index 0000000..c9eb29f
--- /dev/null
+++ b/src/data/queue.c
@@ -0,0 +1,210 @@
+/*:*
+ *: File: ./src/data/queue.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "queue.h"
+
+#include <stdlib.h>
+
+Queue*
+queue_new() {
+ Queue *p_queue = (Queue *) malloc(sizeof(Queue));
+
+ p_queue->p_first = 0;
+ p_queue->p_last = 0;
+ p_queue->i_size = 0;
+
+ return p_queue;
+}
+
+QueueElem*
+queueelem_new() {
+ return queueelem_new_t(TYPE_UNKNOWN);
+}
+
+QueueElem*
+queueelem_new_t(TYPE type) {
+ QueueElem *p_elem = (QueueElem *) malloc(sizeof(QueueElem));
+
+ p_elem->p_next = 0;
+ p_elem->p_val = 0;
+ p_elem->type = type;
+
+ return p_elem;
+}
+
+_Bool
+queue_empty(Queue *p_queue) {
+ if (p_queue == NULL)
+ return 0;
+
+ return p_queue->i_size == 0;
+}
+
+void
+queue_push(Queue *p_queue, void *p_val) {
+ queue_push_t(p_queue, p_val, TYPE_UNKNOWN);
+}
+
+void
+queue_push_t(Queue *p_queue, void *p_val, TYPE type) {
+ QueueElem *p_elem = queueelem_new_t(type);
+ p_elem->p_val = p_val;
+
+ if (0 == p_queue->i_size++)
+ p_queue->p_first = p_elem;
+ else
+ p_queue->p_last->p_next = p_elem;
+
+ p_queue->p_last = p_elem;
+}
+
+void*
+queue_pop(Queue *p_queue) {
+ TYPE type;
+ return queue_pop_t(p_queue, &type);
+}
+
+void*
+queue_pop_t(Queue *p_queue, TYPE *p_type) {
+ if (queue_empty(p_queue))
+ return 0;
+
+ QueueElem *p_elem = p_queue->p_first;
+ p_queue->p_first = p_elem->p_next;
+
+ --p_queue->i_size;
+
+ void *p_ret = p_elem->p_val;
+ *p_type = p_elem->type;
+ free(p_elem);
+ return p_ret;
+}
+
+void
+queue_clear(Queue *p_queue) {
+ for (;!queue_empty(p_queue); queue_pop(p_queue));
+}
+
+void
+queue_delete(Queue *p_queue) {
+ queue_clear(p_queue);
+ free(p_queue);
+}
+
+unsigned
+queue_size(Queue *p_queue) {
+ return p_queue->i_size;
+}
+
+void
+queue_iterate(Queue *p_queue, void (*func)(void *)) {
+ QueueElem *p_elem = p_queue->p_first;
+ while (p_elem) {
+ if (p_elem->p_val)
+ (*func) (p_elem->p_val);
+
+ p_elem = p_elem->p_next;
+ }
+}
+
+void
+queue_iterate_t(Queue *p_queue, void (*func)(void *, TYPE)) {
+ QueueElem *p_elem = p_queue->p_first;
+ while (p_elem) {
+ if (p_elem->p_val)
+ (*func) (p_elem->p_val, p_elem->type);
+
+ p_elem = p_elem->p_next;
+ }
+}
+
+void
+queue_iterate_tl(Queue *p_queue, void (*func)(void *, TYPE, _Bool)) {
+ QueueElem *p_elem = p_queue->p_first;
+ while (p_elem) {
+ if (p_elem->p_val)
+ (*func) (p_elem->p_val, p_elem->type, p_elem->p_next == NULL);
+
+ p_elem = p_elem->p_next;
+ }
+}
+
+QueueIter*
+queueiter_new(Queue *p_queue) {
+ QueueIter *p_iter =
+ (QueueIter *) malloc(sizeof(QueueIter));
+
+ p_iter->p_current = NULL;
+ p_iter->p_next = p_queue->p_first;
+ p_iter->i_left = queue_size(p_queue);
+ p_iter->p_queue = p_queue;
+
+ return p_iter;
+}
+
+void
+queueiter_delete(QueueIter *p_iter) {
+ free(p_iter);
+}
+
+void*
+queueiter_next(QueueIter *p_iter) {
+ TYPE type;
+ return queueiter_next_t(p_iter, &type);
+}
+
+void*
+queueiter_next_t(QueueIter *p_iter, TYPE *p_type) {
+ if (p_iter->p_next == NULL)
+ return NULL;
+
+ void *p_ret = p_iter->p_next->p_val;
+ *p_type = p_iter->p_next->type;
+ p_iter->p_current = p_iter->p_next;
+ p_iter->p_next = p_iter->p_next->p_next;
+ --p_iter->i_left;
+
+ return p_ret;
+}
+
+unsigned
+queueiter_left(QueueIter *p_iter) {
+ return p_iter->i_left;
+}
+
+Queue*
+queueiter_queue(QueueIter *p_iter) {
+ return p_iter->p_queue;
+}
+
diff --git a/src/data/queue.h b/src/data/queue.h
new file mode 100644
index 0000000..950be07
--- /dev/null
+++ b/src/data/queue.h
@@ -0,0 +1,81 @@
+/*:*
+ *: File: ./src/data/queue.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef QUEUE_H
+#define QUEUE_H
+
+#include "types.h"
+
+typedef struct QueueElem_ {
+ struct QueueElem_ *p_next;
+ void *p_val;
+ TYPE type;
+} QueueElem;
+
+typedef struct {
+ QueueElem *p_first;
+ QueueElem *p_last;
+ unsigned i_size;
+} Queue;
+
+typedef struct {
+ unsigned i_left;
+ Queue *p_queue;
+ QueueElem *p_current;
+ QueueElem *p_next;
+} QueueIter;
+
+Queue *queue_new();
+QueueElem *queueelem_new();
+QueueElem *queueelem_new_t(TYPE type);
+_Bool queue_empty(Queue *p_queue);
+void queue_push(Queue *p_queue, void *p_val);
+void queue_push_t(Queue *p_queue, void *p_val, TYPE type);
+void *queue_pop(Queue *p_queue);
+void *queue_pop_t(Queue *p_queue, TYPE *p_type);
+void queue_clear(Queue *p_queue);
+void queue_delete(Queue *p_queue);
+unsigned queue_size(Queue *p_queue);
+void queue_iterate(Queue *p_queue, void (*func)(void *));
+void queue_iterate_t(Queue *p_queue, void (*func)(void *, TYPE));
+void queue_iterate_tl(Queue *p_queue, void (*func)(void *, TYPE, _Bool));
+
+QueueIter *queueiter_new(Queue *p_queue);
+void queueiter_delete(QueueIter *p_iter);
+void *queueiter_next(QueueIter *p_iter);
+void *queueiter_next_t(QueueIter *p_iter, TYPE *p_type);
+unsigned queueiter_left(QueueIter *p_iter);
+Queue *queueiter_queue(QueueIter *p_iter);
+
+#endif
diff --git a/src/data/stack.c b/src/data/stack.c
new file mode 100644
index 0000000..f0392d0
--- /dev/null
+++ b/src/data/stack.c
@@ -0,0 +1,234 @@
+/*:*
+ *: File: ./src/data/stack.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "stack.h"
+
+#include "../defines.h"
+
+Stack*
+stack_new() {
+ Stack *p_stack = (Stack *) malloc(sizeof(Stack));
+
+ p_stack->p_first = p_stack->p_last = NULL;
+ p_stack->i_size = 0;
+
+ return (p_stack);
+}
+
+StackElem*
+stackelem_new() {
+ StackElem *p_elem = (StackElem *) malloc(sizeof(StackElem));
+
+ p_elem->p_next = NULL;
+ p_elem->p_val = NULL;
+
+ return (p_elem);
+}
+
+_Bool
+stack_empty(Stack *p_stack) {
+ return (p_stack->i_size == 0);
+}
+
+void
+stack_push(Stack *p_stack, void *p_val) {
+ StackElem *p_elem = stackelem_new();
+
+ p_elem->p_val = p_val;
+ p_elem->p_next = p_stack->p_first;
+ p_stack->p_first = p_elem;
+
+ if (p_stack->p_last == NULL)
+ p_stack->p_last = p_stack->p_first;
+
+ ++p_stack->i_size;
+}
+
+void*
+stack_pop(Stack *p_stack) {
+ if (stack_empty(p_stack))
+ return (NULL);
+
+ StackElem *p_elem = p_stack->p_first;
+ p_stack->p_first = p_elem->p_next;
+
+ void *p_val = p_elem->p_val;
+ free(p_elem);
+ --p_stack->i_size;
+
+ if (p_stack->i_size == 0)
+ p_stack->p_last = NULL;
+
+ return (p_val);
+}
+
+void
+stack_clear(Stack *p_stack) {
+ for (;!stack_empty(p_stack); stack_pop(p_stack));
+}
+
+void
+stack_delete(Stack *p_stack) {
+ stack_clear(p_stack);
+ free(p_stack);
+}
+
+void
+stack_delete_and_free(Stack *p_stack) {
+ for (;!stack_empty(p_stack); free(stack_pop(p_stack)));
+ stack_delete(p_stack);
+}
+
+unsigned
+stack_size(Stack *p_stack) {
+ if (!p_stack)
+ return (0);
+
+ return (p_stack->i_size);
+}
+
+void
+stack_merge(Stack *p_stack, Stack *p_stack_merge) {
+ if (stack_empty(p_stack_merge))
+ return;
+
+ if (stack_empty(p_stack)) {
+ p_stack->p_first = p_stack_merge->p_first;
+ p_stack->p_last = p_stack_merge->p_last;
+ p_stack->i_size = p_stack_merge->i_size;
+
+ } else {
+ StackElem *p_old_first = p_stack->p_first;
+
+ p_stack->p_first = p_stack_merge->p_first;
+ p_stack_merge->p_last->p_next = p_old_first;
+ p_stack->i_size += p_stack_merge->i_size;
+ }
+
+ p_stack_merge->p_first = p_stack_merge->p_last = NULL;
+ p_stack_merge->i_size = 0;
+}
+
+void
+stack_concat(Stack *p_stack, Stack *p_stack_concat) {
+ if (stack_empty(p_stack_concat))
+ return;
+
+ Stack *p_stack_tmp = stack_new();
+
+ StackIterator *p_iter = stackiterator_new(p_stack_concat);
+
+ while (stackiterator_has_next(p_iter))
+ stack_push(p_stack_tmp, stackiterator_next(p_iter));
+
+ stackiterator_delete(p_iter);
+
+ while (!stack_empty(p_stack_tmp))
+ stack_push(p_stack, stack_pop(p_stack_tmp));
+
+ stack_delete(p_stack_tmp);
+}
+
+void
+stack_iterate(Stack *p_stack, void (*func)(void *p_void)) {
+ if (!p_stack)
+ return;
+
+ StackElem *p_elem = p_stack->p_first;
+
+ while (p_elem) {
+ (*func)(p_elem->p_val);
+ p_elem = p_elem->p_next;
+ }
+}
+
+StackIterator*
+stackiterator_new(Stack *p_stack) {
+ StackIterator *p_iter = malloc(sizeof(StackIterator));
+
+ p_iter->p_current = p_stack->p_first;
+ p_iter->p_prev = NULL;
+
+ return (p_iter);
+}
+
+void
+stackiterator_delete(StackIterator *p_iter) {
+ free(p_iter);
+}
+
+void*
+stackiterator_next(StackIterator *p_iter) {
+ if (!p_iter)
+ return (NULL);
+
+ StackElem *p_elem = p_iter->p_current;
+
+ if (!p_elem)
+ return (NULL);
+
+ p_iter->p_prev = p_iter->p_current;
+ p_iter->p_current = p_elem->p_next;
+
+ return (p_elem->p_val);
+}
+
+_Bool
+stackiterator_has_next(StackIterator *p_iter) {
+ return (p_iter->p_current ? true : false);
+}
+
+_Bool
+stackiterator_remove_prev(StackIterator *p_iter) {
+ StackElem *p_prev = p_iter->p_prev;
+
+ if (p_prev == NULL)
+ return (false);
+
+ StackElem *p_next = p_prev->p_next;
+
+ if (p_next == NULL)
+ return (false);
+
+ p_prev->p_val = p_next->p_val;
+ p_prev->p_next = p_next->p_next;
+
+
+ free(p_next);
+
+ p_iter->p_current = p_prev;
+ p_iter->p_prev = NULL;
+
+ return (true);
+}
diff --git a/src/data/stack.h b/src/data/stack.h
new file mode 100644
index 0000000..f5f91c2
--- /dev/null
+++ b/src/data/stack.h
@@ -0,0 +1,76 @@
+/*:*
+ *: File: ./src/data/stack.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef STACK_H
+#define STACK_H
+
+#define stack_top(s) s->p_first->p_val;
+
+#include <stdlib.h>
+
+typedef struct StackElem_ {
+ struct StackElem_ *p_next;
+ void *p_val;
+} StackElem;
+
+typedef struct {
+ StackElem *p_first;
+ StackElem *p_last; // Only needed for stack_merge
+ unsigned i_size;
+} Stack;
+
+typedef struct {
+ StackElem *p_current;
+ StackElem *p_prev;
+} StackIterator;
+
+Stack *stack_new();
+StackElem *stackelem_new();
+_Bool stack_empty(Stack *p_stack);
+void stack_iterate(Stack *p_stack, void (*func)(void *p_void));
+void stack_push(Stack *p_stack, void *p_val);
+void *stack_pop(Stack *p_stack);
+void stack_clear(Stack *p_stack);
+void stack_delete(Stack *p_stack);
+void stack_delete_and_free(Stack *p_stack);
+unsigned stack_size(Stack *p_stack);
+void stack_merge(Stack *p_stack, Stack *p_stack_merge);
+void stack_concat(Stack *p_stack, Stack *p_stack_concat);
+StackIterator* stackiterator_new(Stack *p_stack);
+void stackiterator_delete(StackIterator *p_iter);
+_Bool stackiterator_has_next(StackIterator *p_iter);
+void* stackiterator_next(StackIterator *p_iter);
+_Bool stackiterator_remove_prev(StackIterator *p_iter);
+
+#endif
diff --git a/src/data/tree.c b/src/data/tree.c
new file mode 100644
index 0000000..c1f01c1
--- /dev/null
+++ b/src/data/tree.c
@@ -0,0 +1,250 @@
+/*:*
+ *: File: ./src/data/tree.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "tree.h"
+
+Tree*
+tree_new() {
+ Tree *p_tree = malloc(sizeof(Tree));
+
+ p_tree->p_treenode_root = NULL;
+
+ return p_tree;
+}
+
+
+void
+tree_delete(Tree *p_tree) {
+ if (!p_tree)
+ return;
+
+ if (p_tree->p_treenode_root)
+ treenode_delete(p_tree->p_treenode_root);
+
+ free(p_tree);
+}
+
+void _tree_print(TreeNode *p_treenode, int i_indent);
+
+void _indent(int i_indent) {
+ for (int i = 0; i < i_indent; ++i)
+ if (i % TREE_PRINT_INDENT)
+ printf(" ");
+ else
+ printf("|");
+}
+
+void
+_tree_print_cb2(void *p_void, void *p_indent) {
+ _tree_print(p_void, (int) p_indent);
+}
+
+void
+_tree_print_cb(void *p_void, void *p_indent) {
+ TreeNode *ptn = p_void;
+ _indent((int) p_indent);
+
+#ifdef FYPE
+ TokenType tt = (TokenType) treenode_get_val(ptn);
+
+ if (IS_NOT_TERMINAL(tt))
+ goto no_token_val;
+
+ Token *p_token = treenode_get_val2(ptn);
+
+ if (!p_token)
+ goto no_token_val;
+
+ char *c_token_val = token_get_val(p_token);
+ TokenType tt_token = token_get_tt(p_token);
+
+ if (!c_token_val)
+ c_token_val = "";
+
+ printf(" %s=%s", tt_get_name(tt_token), c_token_val);
+ return;
+
+no_token_val:
+ printf(" %s", tt_get_name(tt));
+
+#else
+ printf(" %d", (int) treenode_get_val(ptn));
+#endif
+}
+
+void
+_tree_print(TreeNode *p_treenode, int i_indent) {
+ TokenType tt = (TokenType)treenode_get_val(p_treenode);
+
+#ifdef FYPE
+ _Bool b_print_nl = false;
+ if (IS_NOT_TERMINAL(tt)) {
+ _indent(i_indent);
+ printf("%s:", tt_get_name(tt));
+ b_print_nl = true;
+ }
+#else
+ _indent(i_indent);
+ printf("%s:", tt_get_name(tt));
+#endif
+
+ array_iterate2(p_treenode->p_array_childs, _tree_print_cb, (void*) 0);
+
+#ifdef FYPE
+ if (b_print_nl)
+#endif
+ printf("\nTree ");
+
+ array_iterate2(p_treenode->p_array_childs, _tree_print_cb2, (void*) (i_indent + TREE_PRINT_INDENT));
+}
+
+void
+tree_print(Tree *p_tree) {
+ if (!p_tree)
+ return;
+
+ printf("\nTree ");
+ _tree_print(tree_get_root(p_tree), 0);
+ printf("\n");
+}
+
+TreeNode*
+treenode_new(void *p_val) {
+ return treenode_new2(p_val, NULL);
+}
+
+TreeNode*
+treenode_new2(void *p_val, void *p_val2) {
+ TreeNode *p_treenode = malloc(sizeof(TreeNode));
+
+ p_treenode->tnt = IS_LEAF;
+ p_treenode->p_array_childs = array_new();
+ p_treenode->p_val = p_val;
+ p_treenode->p_val2 = p_val2;
+
+ return p_treenode;
+}
+
+void
+treenode_delete(TreeNode *p_treenode) {
+ if (!p_treenode)
+ return;
+
+ int i_size = array_get_size(p_treenode->p_array_childs);
+
+ for (int i = 0; i < i_size; ++i)
+ treenode_delete(array_get(p_treenode->p_array_childs, i));
+
+ array_delete(p_treenode->p_array_childs);
+
+ free(p_treenode);
+}
+
+void
+treenode_insert_left(TreeNode *p_treenode, TreeNode *p_treenode2) {
+ array_unshift(p_treenode->p_array_childs, p_treenode2);
+}
+
+void
+treenode_insert_right(TreeNode *p_treenode, TreeNode *p_treenode2) {
+ array_push(p_treenode->p_array_childs, p_treenode2);
+}
+
+TreeIteratorState*
+treeiteratorstate_new(TreeNode *ptn) {
+ TreeIteratorState *p_state = malloc(sizeof(TreeIteratorState));
+
+ p_state->ptn = ptn;
+ p_state->i_pos = 0;
+
+ return p_state;
+}
+
+void
+treeiteratorstate_delete(TreeIteratorState *p_state) {
+ free(p_state);
+}
+
+TreeIterator*
+treeiterator_new(Tree *p_tree) {
+ TreeIterator *p_iter = malloc(sizeof(TreeIterator));
+
+ p_iter->p_stack = stack_new();
+ p_iter->p_state = treeiteratorstate_new(tree_get_root(p_tree));
+
+ return p_iter;
+}
+
+void
+treeiterator_delete(TreeIterator *p_iter) {
+ while (!stack_empty(p_iter->p_stack))
+ treeiteratorstate_delete(stack_pop(p_iter->p_stack));
+
+ stack_delete(p_iter->p_stack);
+
+ if (p_iter->p_state)
+ treeiteratorstate_delete(p_iter->p_state);
+}
+
+_Bool
+treeiterator_has_next(TreeIterator *p_iter) {
+ return p_iter->p_state != NULL;
+}
+
+TreeNode*
+treeiterator_next(TreeIterator *p_iter) {
+ if (!treeiterator_has_next(p_iter))
+ return NULL;
+
+ TreeNode *ptn = p_iter->p_state->ptn;
+
+ Array *p_array_childs = treenode_get_childs(ptn);
+ int i_num_childs = array_get_size(p_array_childs);
+
+ if (p_iter->p_state->i_pos >= i_num_childs) {
+ treeiteratorstate_delete(p_iter->p_state);
+
+ p_iter->p_state =
+ stack_empty(p_iter->p_stack) ? NULL : stack_pop(p_iter->p_stack);
+
+ return ptn;
+ }
+
+ TreeNode *ptn_next = array_get(p_array_childs, p_iter->p_state->i_pos++);
+ stack_push(p_iter->p_stack, p_iter->p_state);
+ p_iter->p_state = treeiteratorstate_new(ptn_next);
+
+ return ptn;
+}
+
diff --git a/src/data/tree.h b/src/data/tree.h
new file mode 100644
index 0000000..9b98d86
--- /dev/null
+++ b/src/data/tree.h
@@ -0,0 +1,106 @@
+/*:*
+ *: File: ./src/data/tree.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef TREE_H
+#define TREE_H
+
+#include "../defines.h"
+#include "array.h"
+#include "stack.h"
+
+#ifdef FYPE
+#include "../core/token.h"
+#endif
+
+#define TREE_PRINT_INDENT 3
+
+#define tree_get_root(t) t->p_treenode_root
+#define tree_set_root(t,tn) t->p_treenode_root = tn
+#define treenode_get_num_childs(tn) array_get_size(tn->p_array_childs)
+#define treenode_get_tnt(tn) tn->tnt
+#define treenode_get_val(tn) tn->p_val
+#define treenode_get_val2(tn) tn->p_val2
+#define treenode_set_tnt(tn,t) tn->tnt = t
+#define treenode_set_val(tn,v) tn->p_val = v
+#define treenode_set_val2(tn,v) tn->p_val2 = v
+#define treenode_insert_child treenode_insert_right
+#define treenode_get_childs(tn) tn->p_array_childs
+#define treenode_get_child(tn,i) array_get(tn->p_array_childs,i)
+#define treenode_get_first_child(tn) array_get_first(tn->p_array_childs)
+#define treenode_get_last_child(tn) array_get_last(tn->p_array_childs)
+
+typedef enum {
+ IS_NOTLEAF,
+ IS_LEAF,
+} TreeNodeType;
+
+typedef struct {
+ TreeNodeType tnt;
+ Array *p_array_childs;
+ void *p_val;
+ void *p_val2;
+} TreeNode;
+
+typedef struct {
+ TreeNode *p_treenode_root;
+} Tree;
+
+typedef struct {
+ TreeNode *ptn;
+ int i_pos;
+} TreeIteratorState;
+
+typedef struct {
+ Stack *p_stack;
+ TreeIteratorState *p_state;
+} TreeIterator;
+
+Tree* tree_new();
+void tree_delete(Tree *p_tree);
+void tree_print(Tree *p_tree);
+TreeNode* treenode_new(void *p_val);
+TreeNode* treenode_new2(void *p_val, void *p_val2);
+void treenode_delete(TreeNode *p_treenode);
+void treenode_insert_left(TreeNode *p_treenode, TreeNode *p_treenode2);
+void treenode_insert_right(TreeNode *p_treenode, TreeNode *p_treenode2);
+
+TreeIteratorState* treeiteratorstate_new(TreeNode *ptn);
+void treeiteratorstate_delete(TreeIteratorState *p_state);
+
+TreeIterator* treeiterator_new(Tree *p_tree);
+void treeiterator_delete(TreeIterator *p_iter);
+_Bool treeiterator_has_next(TreeIterator *p_iter);
+TreeNode* treeiterator_next(TreeIterator *p_iter);
+
+#endif
diff --git a/src/data/tupel.c b/src/data/tupel.c
new file mode 100644
index 0000000..c5ec5a4
--- /dev/null
+++ b/src/data/tupel.c
@@ -0,0 +1,53 @@
+/*:*
+ *: File: ./src/data/tupel.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "tupel.h"
+
+#include <stdlib.h>
+
+Tupel*
+tupel_new() {
+ Tupel *p_tupel = (Tupel *) malloc(sizeof(Tupel));
+
+ p_tupel->a = NULL;
+ p_tupel->b = NULL;
+ p_tupel->c = NULL;
+
+ return p_tupel;
+}
+
+void
+tupel_delete(Tupel *p_tupel) {
+ free(p_tupel);
+}
diff --git a/src/data/tupel.h b/src/data/tupel.h
new file mode 100644
index 0000000..ae5bdcc
--- /dev/null
+++ b/src/data/tupel.h
@@ -0,0 +1,47 @@
+/*:*
+ *: File: ./src/data/tupel.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef TUPEL_H
+#define TUPEL_H
+
+typedef struct {
+ void *a;
+ void *b;
+ void *c;
+} Tupel;
+
+Tupel *tupel_new();
+void tupel_delete(Tupel *p_tupel);
+
+#endif
diff --git a/src/data/types.h b/src/data/types.h
new file mode 100644
index 0000000..f47f258
--- /dev/null
+++ b/src/data/types.h
@@ -0,0 +1,64 @@
+/*:*
+ *: File: ./src/data/types.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef TYPES_H
+#define TYPES_H
+
+typedef enum {
+ TYPE_UNKNOWN,
+ TYPE_NUMBER,
+ TYPE_STRING,
+ TYPE_VOIDP,
+ TYPE_SYMVAR,
+ TYPE_VARIABLE,
+ TYPE_REGEXPR,
+ TYPE_OPERATOR,
+ TYPE_STACK,
+ TYPE_TUPEL,
+ TYPE_HASH,
+ TYPE_DAT,
+ TYPE_ARG_DAT,
+ TYPE_ARGS_DAT,
+ TYPE_STATEMENT_DAT,
+ TYPE_CODE_DAT
+} TYPE;
+
+typedef enum {
+ RET_OK,
+ RET_ERROR = -1,
+ RET_NO_SPACE = -2,
+ RET_OCCUPIED = -3
+} RETCODE;
+
+#endif
diff --git a/src/defines.h b/src/defines.h
new file mode 100644
index 0000000..83887b2
--- /dev/null
+++ b/src/defines.h
@@ -0,0 +1,99 @@
+/*:*
+ *: File: ./src/defines.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#ifndef DEFINES_H
+#define DEFINES_H
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "build.h"
+
+#define COPYRIGHT "Copyright by Paul C. Buetow (2005 - 2008) <fype@dev.buetow.org>"
+#define FYPE
+#define GRAMMAR_MAP_SIZES 128
+#define HASH_MAXOCC 5
+#define HASH_MKEYLEN 32
+#define HASH_SCALE 10
+#define NAME "Fype"
+#define ASSEMBLER "yasm"
+#define LINKER "cc"
+#define SCANNER_BUFSIZE 512
+#define URL "<http://www.Fype.org>"
+#define VERSION "v0.0-devel Build"
+
+
+
+#ifndef false
+#define false (_Bool)0
+#endif
+
+#ifndef true
+#define true (_Bool)1
+#endif
+
+// Makes the compiler always happy (end of switch statements) :)
+#define NO_DEFAULT default: if (0)
+
+#define EPRINTF(...) fprintf(stdout, __VA_ARGS__)
+#define ERROR(...) { fprintf(stdout, __VA_ARGS__); \
+ fprintf(stdout, " (%s @ %s line %d)\n", NAME, __FILE__, __LINE__); \
+ exit(1); }
+#define DPRINTF(...) printf("DEBUG("); printf(__VA_ARGS__); printf(")\n");
+
+/*
+#define DEBUG_TOKEN_REFCOUNT
+#define DEBUG_FUNCTION_PROCESS
+#define DEBUG_TRACK
+#define DEBUG_BLOCK_GET
+#define DEBUG_EXPRESSION_GET
+*/
+
+#ifdef DEBUG_TRACK
+#define TRACK \
+ DPRINTF("Track: %s:%s:%d", \
+ __FILE__, __FUNCTION__, __LINE__); \
+ if (p_interpret && p_interpret->p_token) \
+ DPRINTF("Token: %s", token_get_val(p_interpret->p_token));
+#else
+#define TRACK
+#endif /* DEBUG_TRACK */
+
+#define STR_NEW(len) (char *) calloc(len, sizeof(char))
+#define STR_RESIZE(str, len) (char *) realloc(str, len *sizeof(char))
+#define STRLST(str) str[strlen(str)-1]
+
+#endif
diff --git a/src/fype.c b/src/fype.c
new file mode 100644
index 0000000..206cf17
--- /dev/null
+++ b/src/fype.c
@@ -0,0 +1,91 @@
+/*:*
+ *: File: ./src/fype.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include "fype.h"
+
+#include "argv.h"
+#include "core/garbage.h"
+#include "core/interpret.h"
+#include "core/scanner.h"
+#include "core/symbol.h"
+
+Fype*
+fype_new() {
+ Fype *p_fype = malloc(sizeof(Fype));
+
+ p_fype->p_hash_syms = hash_new(512);
+ p_fype->p_list_token = list_new();
+ p_fype->p_tupel_argv = tupel_new();
+ p_fype->c_basename = NULL;
+
+ garbage_init();
+
+ return (p_fype);
+}
+
+void
+fype_delete(Fype *p_fype) {
+ argv_tupel_delete(p_fype->p_tupel_argv);
+
+ hash_iterate(p_fype->p_hash_syms, symbol_cleanup_hash_syms_cb);
+ hash_delete(p_fype->p_hash_syms);
+
+ //list_iterate(p_fype->p_list_token, token_print_cb);
+ list_iterate(p_fype->p_list_token, token_ref_down_cb);
+ //list_iterate(p_fype->p_list_token, token_print_cb);
+ list_delete(p_fype->p_list_token);
+
+ if (p_fype->c_basename)
+ free(p_fype->c_basename);
+
+ garbage_destroy();
+}
+
+int
+fype_run(int i_argc, char **pc_argv) {
+ Fype *p_fype = fype_new();
+
+ // argv: Maintains command line options
+ argv_run(p_fype, i_argc, pc_argv);
+
+ // scanner: Creates a list of token
+ scanner_run(p_fype);
+
+ // interpret: Interpret the list of token
+ interpret_run(p_fype);
+
+ fype_delete(p_fype);
+
+ return (0);
+}
diff --git a/src/fype.h b/src/fype.h
new file mode 100644
index 0000000..5a4df9c
--- /dev/null
+++ b/src/fype.h
@@ -0,0 +1,57 @@
+/*:*
+ *: File: ./src/fype.h
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "argv.h"
+#include "data/hash.h"
+#include "data/list.h"
+#include "data/tupel.h"
+
+#ifndef FYPE_H
+#define FYPE_H
+
+typedef struct {
+ Tupel *p_tupel_argv; // Contains command line options
+ List *p_list_token; // Initial list of token
+ Hash *p_hash_syms; // Symbol table
+ char *c_basename;
+} Fype;
+
+Fype *fype_new();
+void fype_delete(Fype *p_fype);
+int fype_run(int i_argc, char **pc_argv);
+
+#endif /* FYPE_H */
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..e6a528c
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,45 @@
+/*:*
+ *: File: ./src/main.c
+ *: A simple interpreter
+ *:
+ *: WWW : http://fype.buetow.org
+ *: E-Mail : fype@dev.buetow.org
+ *:
+ *: Copyright (c) 2005 2006 2007 2008, Paul Buetow (http://www.pblabs.net)
+ *: All rights reserved.
+ *:
+ *: Redistribution and use in source and binary forms, with or without modi-
+ *: fication, are permitted provided that the following conditions are met:
+ *: * Redistributions of source code must retain the above copyright
+ *: notice, this list of conditions and the following disclaimer.
+ *: * Redistributions in binary form must reproduce the above copyright
+ *: notice, this list of conditions and the following disclaimer in the
+ *: documentation and/or other materials provided with the distribution.
+ *: * Neither the name of P. B. Labs nor the names of its contributors may
+ *: be used to endorse or promote products derived from this software
+ *: without specific prior written permission.
+ *:
+ *: THIS SOFTWARE IS PROVIDED BY Paul Buetow AS IS'' AND ANY EXPRESS OR
+ *: IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ *: WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ *: DISCLAIMED. IN NO EVENT SHALL Paul Buetow BE LIABLE FOR ANY DIRECT,
+ *: INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ *: (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ *: SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ *: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ *: STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ *: IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ *: POSSIBILITY OF SUCH DAMAGE.
+ *:*/
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "fype.h"
+#include "./data/list.h"
+
+int
+main(int i_argc, char **pc_argv) {
+ return (fype_run(i_argc, pc_argv));
+}
+