From 4930c9c0ddeaa5c9421d36396fd74d22db1385c6 Mon Sep 17 00:00:00 2001 From: Mart Lubbers Date: Wed, 27 Jan 2016 18:21:24 +0100 Subject: [PATCH] fixed issue 1, changed function type of readline --- Clean System Files/readLine.c | 151 ++++++++++++++++++++++++++++------ Makefile | 17 +++- ReadLine.dcl | 22 ++++- ReadLine.icl | 123 ++++++++++++++++++++++----- test.icl | 19 ++++- 5 files changed, 275 insertions(+), 57 deletions(-) diff --git a/Clean System Files/readLine.c b/Clean System Files/readLine.c index bea7de6..c73bc06 100644 --- a/Clean System Files/readLine.c +++ b/Clean System Files/readLine.c @@ -9,7 +9,9 @@ static char *cs_answer = (char *)NULL; HISTORY_STATE *history_state = NULL; -char *cleanStringToCString(CleanString s){ +//Helper functions +char *cleanStringToCString(CleanString s) +{ unsigned long len = CleanStringLength(s); char *cs = (char *)malloc(len+1); if(cs == NULL){ @@ -21,7 +23,13 @@ char *cleanStringToCString(CleanString s){ return cs; } -void cleanReadLine(CleanString prompt, int history, CleanString *result) +void cleanSetReadLineName(CleanString name) +{ + rl_readline_name = cleanStringToCString(name); +} + +//Readline functions +void cleanReadLine(CleanString prompt, int history, CleanString *result, int *eof) { char *cs_prompt = cleanStringToCString(prompt); @@ -35,35 +43,35 @@ void cleanReadLine(CleanString prompt, int history, CleanString *result) if(cs_answer && *cs_answer && history){ add_history(cs_answer); } - + + *eof = 0; if(!cs_answer){ //In case of an EOF - CleanStringVariable(answer, 1); - *result = (CleanString) answer; - memcpy(CleanStringCharacters(answer), "", 1); - CleanStringLength(answer) = 1; - } else { //In case of a proper response - CleanStringVariable(answer, strlen(cs_answer)); - *result = (CleanString) answer; - memcpy(CleanStringCharacters(answer), cs_answer, strlen(cs_answer)); - CleanStringLength(answer) = strlen(cs_answer); + cs_answer = (char *)malloc(1); + cs_answer[0] = '\0'; + *eof = 1; } + CleanStringVariable(answer, strlen(cs_answer)); + *result = (CleanString) answer; + memcpy(CleanStringCharacters(answer), cs_answer, strlen(cs_answer)); + CleanStringLength(answer) = strlen(cs_answer); } -void cleanSetReadLineName(CleanString name){ - rl_readline_name = cleanStringToCString(name); -} - -void cleanUsingHistory(){ +//History Functions +//Initializing History and State Management +void cleanUsingHistory() +{ using_history(); } -void cleanGetState(int *offset, int *num, int *flags){ +void cleanGetState(int *offset, int *num, int *flags) +{ *offset = history_get_history_state()->offset; *num = history_get_history_state()->length; *flags = history_get_history_state()->flags; } -void cleanGetHistoryItem(int num, CleanString *line, CleanString *timestamp){ +void cleanGetHistoryItem(int num, CleanString *line, CleanString *timestamp) +{ char *cs_line = history_get_history_state()->entries[num]->line; char *cs_stamp = history_get_history_state()->entries[num]->timestamp; @@ -78,7 +86,8 @@ void cleanGetHistoryItem(int num, CleanString *line, CleanString *timestamp){ CleanStringLength(cleanTimestamp) = strlen(cs_stamp); } -void cleanInitNewHistoryState(int offset, int flags, int num){ +void cleanInitNewHistoryState(int offset, int flags, int num) +{ if(history_state != NULL){ //we should test if we can recursively free the object free(history_state); @@ -103,48 +112,136 @@ void cleanInitNewHistoryState(int offset, int flags, int num){ history_state->flags = 0; } -void cleanSetNewHistoryEntry(int i, CleanString line, CleanString timestamp){ +void cleanSetNewHistoryEntry(int i, CleanString line, CleanString timestamp) +{ char *cs_line = cleanStringToCString(line); char *cs_timestamp = cleanStringToCString(timestamp); history_state->entries[i]->line = cs_line; history_state->entries[i]->timestamp = cs_timestamp; } -void cleanCommitSetHistory(void){ +void cleanCommitSetHistory(void) +{ history_set_history_state(history_state); } -void cleanAddHistory(CleanString entry){ +//History List Management +void cleanAddHistoryTime(CleanString timestamp) +{ + char *cs_timestamp = cleanStringToCString(timestamp); + add_history_time(cs_timestamp); + free(cs_timestamp); +} + +void cleanAddHistory(CleanString entry) +{ char *cs_entry = cleanStringToCString(entry); add_history(cs_entry); free(cs_entry); } -void cleanClearHistory(){ +void cleanRemoveHistory(int which, CleanString *line, CleanString *timestamp) +{ + HIST_ENTRY *entry = remove_history(which); + char *cs_line = entry->line; + char *cs_stamp = entry->timestamp; + + CleanStringVariable(cleanLine, strlen(cs_line)); + *line = (CleanString) cleanLine; + memcpy(CleanStringCharacters(cleanLine), cs_line, strlen(cs_line)); + CleanStringLength(cleanLine) = strlen(cs_line); + + CleanStringVariable(cleanTimestamp, strlen(cs_stamp)); + *timestamp = (CleanString) cleanTimestamp; + memcpy(CleanStringCharacters(cleanTimestamp), cs_stamp, strlen(cs_stamp)); + CleanStringLength(cleanTimestamp) = strlen(cs_stamp); + + histdata_t tofree = free_history_entry(entry); + free(tofree); +} + +void cleanReplaceHistoryEntry( + int which, CleanString l, CleanString *line, CleanString *timestamp) +{ + char *cs_l = cleanStringToCString(l); + HIST_ENTRY *entry = replace_history_entry(which, cs_l, NULL); + free(cs_l); + if(entry == NULL){ + printf("invalid which\n"); + } + + char *cs_line = entry->line; + char *cs_stamp = entry->timestamp; + + CleanStringVariable(cleanLine, strlen(cs_line)); + *line = (CleanString) cleanLine; + memcpy(CleanStringCharacters(cleanLine), cs_line, strlen(cs_line)); + CleanStringLength(cleanLine) = strlen(cs_line); + + CleanStringVariable(cleanTimestamp, strlen(cs_stamp)); + *timestamp = (CleanString) cleanTimestamp; + memcpy(CleanStringCharacters(cleanTimestamp), cs_stamp, strlen(cs_stamp)); + CleanStringLength(cleanTimestamp) = strlen(cs_stamp); + + histdata_t tofree = free_history_entry(entry); + free(tofree); +} + + +void cleanClearHistory() +{ clear_history(); } -int cleanHistorySearch(CleanString s, int dir){ +void cleanStifleHistory(int max) +{ + stifle_history(max); +} + +int cleanUnstifleHistory() +{ + return unstifle_history(); +} + +int cleanHistoryIsStifled() +{ + return history_is_stifled(); +} + +//Information About the History List +int cleanHistoryTotalBytes() +{ + return history_total_bytes(); +} + +//Moving Around the History List + +//Searching the History List +int cleanHistorySearch(CleanString s, int dir) +{ char *cs_s = cleanStringToCString(s); int ret = history_search(cs_s, dir); free(cs_s); return ret; } -int cleanHistorySearchPrefix(CleanString s, int dir){ +int cleanHistorySearchPrefix(CleanString s, int dir) +{ char *cs_s = cleanStringToCString(s); int ret = history_search_prefix(cs_s, dir); free(cs_s); return ret; } -int cleanHistorySearchPos(CleanString s, int dir, int pos){ +int cleanHistorySearchPos(CleanString s, int dir, int pos) +{ char *cs_s = cleanStringToCString(s); int ret = history_search_pos(cs_s, dir, pos); free(cs_s); return ret; } +//Managing the History File int cleanReadHistory(CleanString path) { char *cs_path = cleanStringToCString(path); diff --git a/Makefile b/Makefile index ae01361..48a27cc 100644 --- a/Makefile +++ b/Makefile @@ -1,11 +1,20 @@ SHELL:=/bin/bash -CLM=clm -CLMFLAGS=-nt -l /usr/lib/libreadline.so +CLM:=clm +CLMFLAGS:=-nt -l /usr/lib/libreadline.so +LIBRARYDIR:=Clean\ System\ Files +BINARIES:=test testscripts/issue1 -all: test +.PHONY: readline clean + +all: readline $(BINARIES) + +readline: + $(MAKE) -C $(LIBRARYDIR) %: %.icl $(CLM) $(CLMFLAGS) $(basename $<) -o $@ clean: - $(RM) -v test Clean\ System\ Files/{ReadLine,test}.* + $(MAKE) -C $(LIBRARYDIR) clean + $(RM) -v $(BINARIES) + $(RM) -v $(addprefix $(LIBRARYDIR)/,$(addsuffix .*,$(BINARIES))) diff --git a/ReadLine.dcl b/ReadLine.dcl index d66e37e..f859e32 100644 --- a/ReadLine.dcl +++ b/ReadLine.dcl @@ -1,13 +1,19 @@ definition module ReadLine +import StdEnv + +:: Maybe a = Nothing | Just a :: HistoryItem = {line :: String, timestamp :: String} :: HistoryState = {entries :: [HistoryItem], offset :: Int, flags :: Int} +instance toString HistoryItem +instance toString HistoryState + //Non-library functions setReadLineName :: !String !*env -> !*env //Readline -readLine :: !String !Bool !*env -> (!String, !*env) +readLine :: !String !Bool !*env -> (!Maybe String, !*env) //Initializing History and State Management //Note that this HAS to be executed when you want to add entries when the @@ -18,11 +24,21 @@ historySetHistoryState :: !HistoryState !*env -> !*env //History List Management addHistory :: !String !*env -> !*env +addHistoryTime :: !String !*env -> !*env +removeHistory :: !Int !*env -> (!HistoryItem, !*env) +replaceHistoryEntry :: !Int !String !*env -> (!HistoryItem, !*env) clearHistory :: !*env -> !*env -//TODO some more functions +stifleHistory :: !Int !*env -> !*env +unstifleHistory :: !*env -> !*env +historyIsStifled :: !*env -> (!Int, !*env) //Information About the History List -//TODO +historyList :: !*env -> (![HistoryItem], !*env) +whereHistory :: !*env -> (!Int, !*env) +currentHistory :: !*env -> (!Maybe HistoryItem, !*env) +historyGet :: !Int !*env -> (!Maybe HistoryItem, !*env) +historyGetTime :: HistoryItem -> String +historyTotalBytes :: !*env -> (!Int, !*env) //Moving Around the History List //TODO diff --git a/ReadLine.icl b/ReadLine.icl index 07b90ac..6320117 100644 --- a/ReadLine.icl +++ b/ReadLine.icl @@ -4,21 +4,37 @@ import StdEnv import code from "readLine.o" +instance toString HistoryItem where + toString {line,timestamp} = line +++ " (" +++ timestamp +++ ")" +instance toString HistoryState where + toString {entries,offset,flags} = "[" +++ toS entries +++ "]\n" +++ + "offset: " +++ toString offset +++ "\nflags: " +++ toString flags + where + toS :: [HistoryItem] -> String + toS [] = "--empty--" + toS [x] = toString x + toS [x:xs] = toString x +++ "," + //Readline -readLine :: !String !Bool !*env -> (!String, !*env) -readLine s h e = code { - ccall cleanReadLine "SI:S:A" - } +readLine :: !String !Bool !*env -> (!Maybe String, !*env) +readLine s h e +# (s, eof, e) = readLineEof s h e += (if eof Nothing (Just s), e) + where + readLineEof :: !String !Bool !*env -> (!String, !Bool, !*env) + readLineEof s h e = code { + ccall cleanReadLine "SI:VSI:A" + } setReadLineName :: !String !*env -> !*env setReadLineName s e = code { - ccall cleanSetReadLineName "S:V:A" + ccall cleanSetReadLineName "S:V:A" } //Initializing History and State Management usingHistory :: !*env -> !*env usingHistory e = code { - ccall cleanUsingHistory ":V:A" + ccall cleanUsingHistory ":V:A" } historyGetHistoryState :: !*env -> (!HistoryState, !*env) @@ -29,8 +45,8 @@ historyGetHistoryState e where getState :: !*env -> (!Int, !Int, !Int, !*env) getState e= code { - ccall cleanGetState ":VIII:A" - } + ccall cleanGetState ":VIII:A" + } getItems :: !Int !*env -> (![HistoryItem], !*env) getItems 0 e = ([], e) getItems i e @@ -40,8 +56,8 @@ historyGetHistoryState e getItem :: !Int !*env -> (!String, !String, !*env) getItem i e = code { - ccall cleanGetHistoryItem "I:VSS:A" - } + ccall cleanGetHistoryItem "I:VSS:A" + } historySetHistoryState :: !HistoryState !*env -> !*env @@ -73,57 +89,124 @@ historySetHistoryState {entries,offset,flags} e //History List Management addHistory :: !String !*env -> !*env addHistory s e = code { - ccall cleanAddHistory "S:V:A" + ccall cleanAddHistory "S:V:A" } +addHistoryTime :: !String !*env -> !*env +addHistoryTime s e = code { + ccall cleanAddHistoryTime "S:V:A" + } + +removeHistory :: !Int !*env -> (!HistoryItem, !*env) +removeHistory i e +# (line, timestamp, e) = removeHistoryItem i e += ({HistoryItem | line=line, timestamp=timestamp}, e) + where + removeHistoryItem :: !Int !*env -> (!String, !String, !*env) + removeHistoryItem i e = code { + ccall cleanRemoveHistory "I:VSS:A" + } + +replaceHistoryEntry :: !Int !String !*env -> (!HistoryItem, !*env) +replaceHistoryEntry i s e +# (line, timestamp, e) = replaceItem i s e += ({HistoryItem | line=line, timestamp=timestamp}, e) + where + replaceItem :: !Int !String !*env -> (!String, !String, !*env) + replaceItem i s e = code { + ccall cleanReplaceHistoryEntry "IS:VSS:A" + } + clearHistory :: !*env -> !*env clearHistory e = code { - ccall cleanClearHistory ":V:A" + ccall cleanClearHistory ":V:A" + } + +stifleHistory :: !Int !*env -> !*env +stifleHistory i e = code { + ccall cleanStifleHistory "I:V:A" + } + +unstifleHistory :: !*env -> !*env +unstifleHistory e = code { + ccall cleanUnstifleHistory ":V:A" + } + +historyIsStifled :: !*env -> (!Int, !*env) +historyIsStifled e = code { + ccall cleanHistoryIsStifled ":I:A" } //Information About the History List +historyList :: !*env -> (![HistoryItem], !*env) +historyList e +# ({entries,offset,flags}, e) = historyGetHistoryState e += (entries, e) + +whereHistory :: !*env -> (!Int, !*env) +whereHistory e +# ({entries,offset,flags}, e) = historyGetHistoryState e += (offset, e) + +currentHistory :: !*env -> (!Maybe HistoryItem, !*env) +currentHistory e +# ({entries,offset,flags}, e) = historyGetHistoryState e += (if (isEmpty entries) Nothing (Just (entries!!offset)), e) + +historyGet :: !Int !*env -> (!Maybe HistoryItem, !*env) +historyGet i e +# ({entries,offset,flags}, e) = historyGetHistoryState e += (if (isEmpty entries) Nothing (Just (entries!!i)), e) + +historyGetTime :: HistoryItem -> String +historyGetTime {line,timestamp} = timestamp + +historyTotalBytes :: !*env -> (!Int, !*env) +historyTotalBytes e = code { + ccall cleanHistoryTotalBytes ":I:A" + } //Moving Around the History List //Searching the History List historySearch :: !String !Int !*env-> (!Int, !*env) historySearch s i e = code { - ccall cleanHistorySearch "SI:I:A" + ccall cleanHistorySearch "SI:I:A" } historySearchPrefix :: !String !Int !*env-> (!Int, !*env) historySearchPrefix s i e = code { - ccall cleanHistorySearchPrefix "SI:I:A" + ccall cleanHistorySearchPrefix "SI:I:A" } historySearchPos :: !String !Int !Int !*env-> (!Int, !*env) historySearchPos s i1 i2 e = code { - ccall cleanHistorySearchPos "SI:I:A" + ccall cleanHistorySearchPos "SI:I:A" } //Managing the History File readHistory :: !String !*env -> (!Bool, !*env) readHistory s e = code { - ccall cleanReadHistory "S:I:A" + ccall cleanReadHistory "S:I:A" } readHistoryRange :: !String !Int !Int !*env -> (!Bool, !*env) readHistoryRange s i1 i2 e = code { - ccall cleanReadHistoryRange "SII:I:A" + ccall cleanReadHistoryRange "SII:I:A" } writeHistory :: !String !*env -> (!Bool, !*env) writeHistory s e = code { - ccall cleanWriteHistory "S:I:A" + ccall cleanWriteHistory "S:I:A" } appendHistory :: !Int !String !*env -> (!Bool, !*env) appendHistory i s e = code { - ccall cleanWriteHistory "IS:I:A" + ccall cleanWriteHistory "IS:I:A" } historyTruncateFile :: !String !Int !*env -> (!Bool, !*env) historyTruncateFile i s e = code { - ccall cleanWriteHistory "SI:I:A" + ccall cleanWriteHistory "SI:I:A" } diff --git a/test.icl b/test.icl index 7612e6a..18e1292 100644 --- a/test.icl +++ b/test.icl @@ -8,19 +8,32 @@ testHistory = {HistoryState | entries=[{HistoryItem | line="custom", timestamp=""}], offset=1, flags=0} -Start :: *World -> (Int, String, HistoryState, HistoryState, *World) +Start :: *World -> (String, *World) Start w -# (f, w) = stdio w #! w = setReadLineName "Test program" w #! w = usingHistory w #! (_, w) = readHistory "readline.history" w #! w = addHistory "testentry" w +#! w = addHistoryTime "time" w +#! (hi, w) = removeHistory 1 w +#! (hy, w) = replaceHistoryEntry 1 "replacement" w #! (s, w) = readLine "first prompt: " True w #! (s, w) = readLine "uparrow should word with history: " False w #! (_, w) = writeHistory "readline.history" w #! (i, w) = historySearch "testentry" -1 w +#! (_, w) = historyList w +#! (_, w) = whereHistory w +#! (_, w) = currentHistory w +#! (_, w) = historyGet 1 w +#! (_, w) = historyTotalBytes w +#! w = stifleHistory 2 w +#! (i, w) = historyIsStifled w +#! w = unstifleHistory w +#! (i, w) = historyIsStifled w #! (oh, w) = historyGetHistoryState w #! w = historySetHistoryState testHistory w #! (h, w) = historyGetHistoryState w #! w = clearHistory w -= (i, s, oh, h, w) += ( + toString h, + w) -- 2.20.1