aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCamil Staps2016-01-28 20:27:19 +0100
committerCamil Staps2016-01-28 20:27:19 +0100
commitaa5ad07bb3c56a8d013cb76a693afefe0d28cfd5 (patch)
tree604c61592c3aeb35875a6af4c2181003d70db26a
Inital commit
-rw-r--r--.gitignore15
-rw-r--r--Clean.h43
-rw-r--r--cleanc.c129
-rw-r--r--cleanc.dcl10
-rw-r--r--cleanc.h10
-rw-r--r--cleanc.icl17
-rw-r--r--test.icl12
7 files changed, 236 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..32fd324
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+# Executables
+*.exe
+*.out
+test
+
+# Directory used to store object files, abc files and assembly files
+Clean System Files/
+
+# iTasks environment extra data
+*-data/
+sapl/
+
+# Object files
+*.o
+
diff --git a/Clean.h b/Clean.h
new file mode 100644
index 0000000..a22eb4d
--- /dev/null
+++ b/Clean.h
@@ -0,0 +1,43 @@
+
+#define Clean(a)
+
+typedef struct clean_string *CleanString;
+
+/* a string in Clean is:
+ struct clean_string {
+ int clean_string_length;
+ char clean_string_characters[clean_string_length];
+ };
+ The string does not end with a '\0' !
+*/
+
+/* CleanStringLength(clean_string) returns the length of the clean_string in characters */
+#define CleanStringLength(clean_string) (*(unsigned long *)(clean_string))
+
+/* CleanStringCharacters(clean_string) returns a pointer to the characters of the clean_string */
+#define CleanStringCharacters(clean_string) ((char*)(1+(unsigned long *)(clean_string)))
+
+/* CleanStringSizeInts(string_length) return size of *CleanString in integers */
+#define CleanStringSizeInts(string_length) (1+(((unsigned int)(string_length)+3)>>2))
+
+/* CleanStringVariable(clean_string,string_length) defines variable clean_string with length string_length,
+ before using the clean_string variable, cast to CleanString, except for the macros above */
+#define CleanStringVariable(clean_string,string_length) unsigned int clean_string[CleanStringSizeInts(string_length)]
+
+/* CleanStringSizeBytes(string_length) return size of *CleanString in bytes */
+#define CleanStringSizeBytes(string_length) (4+(((unsigned int)(string_length)+3) & -4))
+
+typedef int *CleanIntArray;
+
+/* CleanIntArraySize(clean_array) returns the size (number of elements) of the clean_int_array */
+#define CleanIntArraySize(clean_int_array) (((unsigned int *)(clean_int_array))[-2])
+
+typedef double *CleanRealArray;
+
+/* CleanRealArraySize(clean_real_array) returns the size (number of elements) of the clean_real_array */
+#define CleanRealArraySize(clean_real_array) (((unsigned int *)(clean_real_array))[-2])
+
+typedef unsigned char *CleanCharArray;
+
+/* CleanCharArraySize(clean_char_array) returns the size (number of elements) of the clean_char_array */
+#define CleanCharArraySize(clean_char_array) (((unsigned int *)(clean_char_array))[-1])
diff --git a/cleanc.c b/cleanc.c
new file mode 100644
index 0000000..bc73574
--- /dev/null
+++ b/cleanc.c
@@ -0,0 +1,129 @@
+#include <fcntl.h>
+#include <stdio.h>
+#include <elf.h>
+#include <libelf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <inttypes.h>
+#include "Clean.h"
+
+void call_funcname(char*);
+
+void hello(void) {
+ printf("Hello world!\n");
+}
+
+void* parameters[100];
+uint8_t param_ptr = 0;
+
+void init(void) {
+ parameters[0] = NULL;
+ param_ptr = 0;
+}
+
+void puti(long i) {
+ printf("puti %d %d\n", param_ptr, i);
+ parameters[param_ptr] = malloc(sizeof(long));
+ *((long*)parameters[param_ptr]) = i;
+ param_ptr++;
+}
+
+char* cleantocstring(CleanString s) {
+ char* cs = malloc(sizeof(char) * CleanStringLength(s) + 1);
+ int i;
+ for (i = 0; i < CleanStringLength(s); i++)
+ cs[i] = CleanStringCharacters(s)[i];
+ cs[i] = 0;
+ return cs;
+}
+
+void call(CleanString fname) {
+ char*f = cleantocstring(fname);
+ call_funcname(f);
+ param_ptr = 0;
+ // todo
+}
+
+long geti(void) {
+ printf("geti %d\n", param_ptr);
+ return (long)*((long*)parameters[param_ptr++]);
+}
+
+void call_funcname(char* fname) {
+ // http://stackoverflow.com/a/1118808/1544337
+ Elf64_Shdr * shdr;
+ Elf64_Ehdr * ehdr;
+ Elf * elf;
+ Elf_Scn * scn;
+ Elf_Data * data;
+ int cnt;
+ void (*fp)() = NULL;
+
+ int fd = 0;
+
+ /* This is probably Linux specific - Read in our own executable*/
+ if ((fd = open("/proc/self/exe", O_RDONLY)) == -1)
+ exit(1);
+
+ elf_version(EV_CURRENT);
+
+ if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
+ fprintf(stderr, "file is not an ELF binary\n");
+ exit(1);
+ }
+ /* Let's get the elf sections */
+ if (((ehdr = elf64_getehdr(elf)) == NULL) ||
+ ((scn = elf_getscn(elf, ehdr->e_shstrndx)) == NULL) ||
+ ((data = elf_getdata(scn, NULL)) == NULL)) {
+ fprintf(stderr, "Failed to get SOMETHING\n");
+ exit(1);
+ }
+
+ /* Let's go through each elf section looking for the symbol table */
+ for (cnt = 1, scn = NULL; scn = elf_nextscn(elf, scn); cnt++) {
+ if ((shdr = elf64_getshdr(scn)) == NULL)
+ exit(1);
+
+ if (shdr->sh_type == SHT_SYMTAB) {
+ char *name;
+ char *strName;
+ data = 0;
+ if ((data = elf_getdata(scn, data)) == 0 || data->d_size == 0) {
+ fprintf(stderr, "No data in symbol table\n");
+ continue;
+ }
+
+ Elf64_Sym *esym = (Elf64_Sym*) data->d_buf;
+ Elf64_Sym *lastsym = (Elf64_Sym*) ((char*) data->d_buf + data->d_size);
+
+ /* Look through all symbols */
+ for (; esym < lastsym; esym++) {
+ if ((esym->st_value == 0) ||
+ (ELF64_ST_BIND(esym->st_info)== STB_WEAK) ||
+ (ELF64_ST_BIND(esym->st_info)== STB_NUM) ||
+ (ELF64_ST_TYPE(esym->st_info)!= STT_FUNC))
+ continue;
+
+ name = elf_strptr(elf,shdr->sh_link , (size_t)esym->st_name);
+
+ if(!name){
+ fprintf(stderr,"%s\n",elf_errmsg(elf_errno()));
+ //exit(-1);
+ } else if(strcmp(fname, name) == 0 ) {
+ fp = (void(*)(void)) esym->st_value;
+ }
+ }
+
+ /* Call and hope we don't segfault!*/
+ if (fp != NULL) {
+ fp();
+ return;
+ }
+ }
+ }
+
+ elf_end(elf);
+
+ fprintf(stderr, "done, nothing found\n");
+}
+
diff --git a/cleanc.dcl b/cleanc.dcl
new file mode 100644
index 0000000..df97ffe
--- /dev/null
+++ b/cleanc.dcl
@@ -0,0 +1,10 @@
+definition module cleanc
+
+:: State :== Int
+
+puti :: !Int !*State -> *State
+
+call :: !String !*State -> *State
+
+geti :: !*State -> (!Int, !*State)
+
diff --git a/cleanc.h b/cleanc.h
new file mode 100644
index 0000000..9c3e043
--- /dev/null
+++ b/cleanc.h
@@ -0,0 +1,10 @@
+void hello(void);
+
+void init(void);
+
+void puti(long);
+
+void call(char*);
+
+long geti(void);
+
diff --git a/cleanc.icl b/cleanc.icl
new file mode 100644
index 0000000..b3f037c
--- /dev/null
+++ b/cleanc.icl
@@ -0,0 +1,17 @@
+implementation module cleanc
+
+puti :: !Int !*State -> *State
+puti i s = code inline {
+ ccall puti "I:V:I"
+}
+
+call :: !String !*State -> *State
+call f s = code inline {
+ ccall call "S:V:I"
+}
+
+geti :: !*State -> (!Int, !*State)
+geti s = code inline {
+ ccall geti ":I:I"
+}
+
diff --git a/test.icl b/test.icl
new file mode 100644
index 0000000..e154d5c
--- /dev/null
+++ b/test.icl
@@ -0,0 +1,12 @@
+module test
+
+import StdEnv
+import cleanc
+
+Start
+# s = 10
+# s = puti 50 s
+# s = call "hello" s
+# (i, s) = geti s
+= i
+