initial commit, working readline function
authorMart Lubbers <mart@martlubbers.net>
Mon, 25 Jan 2016 09:16:28 +0000 (10:16 +0100)
committerMart Lubbers <mart@martlubbers.net>
Mon, 25 Jan 2016 09:16:28 +0000 (10:16 +0100)
.gitignore [new file with mode: 0644]
Clean System Files/Clean.h [new file with mode: 0644]
Clean System Files/Makefile [new file with mode: 0644]
Clean System Files/readLine.c [new file with mode: 0644]
Makefile [new file with mode: 0644]
README.md [new file with mode: 0644]
ReadLine.dcl [new file with mode: 0644]
ReadLine.icl [new file with mode: 0644]
test.icl [new file with mode: 0644]

diff --git a/.gitignore b/.gitignore
new file mode 100644 (file)
index 0000000..f7c3c6c
--- /dev/null
@@ -0,0 +1,3 @@
+test
+*.abc
+*.o
diff --git a/Clean System Files/Clean.h b/Clean System Files/Clean.h
new file mode 100644 (file)
index 0000000..bf22e6e
--- /dev/null
@@ -0,0 +1,76 @@
+
+#define Clean(a)
+
+typedef struct clean_string *CleanString;
+
+/*     a string in Clean is:
+       struct clean_string {
+               size_t clean_string_length;
+               char clean_string_characters[clean_string_length];
+       };
+       The string does not end with a '\0' !
+*/
+
+#ifndef _WIN64
+
+/* 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 long)(string_length)+(sizeof(unsigned long)-1))>>(1+(sizeof(unsigned long)>>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 long clean_string[CleanStringSizeInts(string_length)]
+
+/* CleanStringSizeBytes(string_length) return size of *CleanString in bytes */
+#define CleanStringSizeBytes(string_length) ((sizeof(unsigned long)<<1)+(((unsigned long)(string_length)+(sizeof(unsigned long)-1)) & -(sizeof(unsigned long))))
+
+typedef long *CleanIntArray;
+
+/* CleanIntArraySize(clean_array) returns the size (number of elements) of the clean_int_array */
+#define CleanIntArraySize(clean_int_array) (((unsigned long *)(clean_int_array))[-2])
+
+/* CleanRealArraySize(clean_real_array) returns the size (number of elements) of the clean_real_array */
+#define CleanRealArraySize(clean_real_array) (((unsigned long *)(clean_real_array))[-2])
+
+/* CleanCharArraySize(clean_char_array) returns the size (number of elements) of the clean_char_array */
+#define CleanCharArraySize(clean_char_array) (((unsigned long *)(clean_char_array))[-1])
+
+#else
+
+/* CleanStringLength(clean_string) returns length of the clean_string in characters */
+#define CleanStringLength(clean_string) (*(unsigned __int64 *)(clean_string))
+
+/* CleanStringCharacters(clean_string) returns a pointer to the characters of the clean_string */
+#define CleanStringCharacters(clean_string) ((char*)(1+(unsigned __int64 *)(clean_string)))
+
+/* CleanStringSizeInts(string_length) return size of *CleanString in integers */
+#define CleanStringSizeInts(string_length) (1+(((unsigned __int64)(string_length)+7)>>3))
+
+/* 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 __int64 clean_string[CleanStringSizeInts(string_length)]
+
+/* CleanStringSizeBytes(string_length) return size of *CleanString in bytes */
+#define CleanStringSizeBytes(string_length) (8+(((unsigned __int64)(string_length)+7) & -8))
+
+typedef __int64 *CleanIntArray;
+
+/* CleanIntArraySize(clean_array) returns the size (number of elements) of the clean_int_array */
+#define CleanIntArraySize(clean_int_array) (((unsigned __int64 *)(clean_int_array))[-2])
+
+/* CleanRealArraySize(clean_real_array) returns the size (number of elements) of the clean_real_array */
+#define CleanRealArraySize(clean_real_array) (((unsigned __int64 *)(clean_real_array))[-2])
+
+/* CleanCharArraySize(clean_char_array) returns the size (number of elements) of the clean_char_array */
+#define CleanCharArraySize(clean_char_array) (((unsigned __int64 *)(clean_char_array))[-1])
+
+#endif
+
+typedef double *CleanRealArray;
+
+typedef unsigned char *CleanCharArray;
diff --git a/Clean System Files/Makefile b/Clean System Files/Makefile
new file mode 100644 (file)
index 0000000..154cf00
--- /dev/null
@@ -0,0 +1,7 @@
+CFLAGS=-Wall -pedantic
+LDFLAGS=-lreadline
+
+all: readLine.o
+
+clean:
+       $(RM) -v readLine.o
diff --git a/Clean System Files/readLine.c b/Clean System Files/readLine.c
new file mode 100644 (file)
index 0000000..b39be2e
--- /dev/null
@@ -0,0 +1,39 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "Clean.h"
+
+static char *cs_answer = (char *)NULL;
+
+void cleanReadLine(CleanString prompt, int history, CleanString *result)
+{
+       //Initialize
+       unsigned long promptlen = CleanStringLength(prompt);
+       char *cs_prompt = (char *)malloc(promptlen+1);
+       if(cs_prompt == NULL){
+               printf("malloc failed...\n");
+               exit(1);
+       }
+       memcpy(cs_prompt, CleanStringCharacters(prompt), promptlen);
+       cs_prompt[promptlen] = '\0';
+
+       //Get the answer and add to history if not empty
+       if(cs_answer){
+               free(cs_answer);
+               cs_answer = (char *)NULL;
+       }
+       cs_answer = readline(cs_prompt);
+       free(cs_prompt);
+       if(cs_answer && *cs_answer && history){
+               add_history(cs_answer);
+       }
+
+       //Transfor answer into cstring
+       CleanStringVariable(answer, strlen(cs_answer));
+       *result = (CleanString) answer;
+       memcpy(CleanStringCharacters(answer), cs_answer, strlen(cs_answer));
+       CleanStringLength(answer) = strlen(cs_answer);
+}
diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..6dd1a70
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+SHELL:=/bin/bash
+CLM=clm
+CLMFLAGS=-nt -l /usr/lib/libreadline.so
+
+all: test
+
+%: %.icl
+       $(CLM) $(CLMFLAGS) $(basename $<) -o $@
+
+clean:
+       $(RM) -v test Clean\ System\ Files/test.*
diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..c50a825
--- /dev/null
+++ b/README.md
@@ -0,0 +1,35 @@
+Clean readline Version 0.1
+==========================
+
+ReadLine is a Clean library that allows interactive console programs to use the
+GNU readline libraries. At the moment this is only tested on Linux.
+
+###Usage
+To setup the library you can simply run
+```
+make -C Clean\ System\ Files
+```
+
+To compile and test the test program you can run
+```
+make
+./test
+```
+
+When you want to use the library in your program you should compile with the
+`-l /usr/lib/libreadline.so` linker flag
+
+###Todo
+
+- Test how the library reacts on non terminal stdin and EOF
+- Embed the readline library in the object files in such a way that no special
+  compiler flag is needed.
+- Control over history, right now entries are added automatically to the
+  history when the boolean flag is on. It would be nice to be able to add
+  custom entries.
+- Control over tabcompletion, right now it completes on filenames.
+- Check possibilities for Windows/Mac
+
+###Author
+
+Mart Lubbers (mart at martlubbers.net)
diff --git a/ReadLine.dcl b/ReadLine.dcl
new file mode 100644 (file)
index 0000000..da953d7
--- /dev/null
@@ -0,0 +1,8 @@
+definition module ReadLine
+
+/*
+       Reads a line from stdin with the readline library
+       The value in the String argument will be used as a prompt
+       To enable history the Boolean variable has to be set to True
+*/
+readLine :: !String !Bool !*env -> (!String, !*env)
diff --git a/ReadLine.icl b/ReadLine.icl
new file mode 100644 (file)
index 0000000..b8c3053
--- /dev/null
@@ -0,0 +1,11 @@
+implementation module ReadLine
+
+import StdEnv
+
+import code from "readLine.o"
+
+readLine :: !String !Bool !*env -> (!String, !*env)
+readLine s h e = code {
+                       ccall cleanReadLine "SI:S:A"
+       }
+
diff --git a/test.icl b/test.icl
new file mode 100644 (file)
index 0000000..0919253
--- /dev/null
+++ b/test.icl
@@ -0,0 +1,11 @@
+module test
+
+import StdEnv
+import ReadLine
+
+Start :: *World -> (String, *World)
+Start w
+# (f, w) = stdio w
+#! (s, w) = readLine "first prompt: " True w
+#! (s, w) = readLine "uparrow should word with history: " False w
+= (s, w)