Compare commits

...

20 Commits

Author SHA1 Message Date
e7ea706157 Merge branch 'finley' 2024-04-14 00:33:05 +02:00
3b3761faa9 Merge branch 'master' 2024-04-13 23:53:29 +02:00
Dennis Boekholtz
edc09d505b Merge branch 'Dennis_CCS' 2024-04-13 23:43:03 +02:00
Dennis Boekholtz
bb79053b1e merge conf reslove 2024-04-13 23:17:47 +02:00
Dennis Boekholtz
2495ac6ee6 Veranderingen om CCS blij te maken 2024-04-13 23:16:24 +02:00
Dennis Boekholtz
1d033c88fb CCS tevreden maken 2024-04-13 22:53:55 +02:00
0eed939e87 CLI: add history next 2024-04-13 22:19:32 +02:00
73c0013ee9 CLI: update historyPrevius() 2024-04-13 21:19:06 +02:00
8f8000d9ca inital draft for history previus handeling 2024-04-13 20:52:05 +02:00
d4edc2cd8f CLI: ignore ANSI/VT100 arrow keys on default 2024-04-13 20:28:39 +02:00
c8854931b5 history: add getFullHistory
CLI: detect arrow keys
2024-04-13 20:20:44 +02:00
e34fe9f213 History: add to cmake and fix errors 2024-04-13 18:03:13 +02:00
a1fef05168 create inital version of history 2024-04-13 17:37:49 +02:00
c49ed49a0b CLI: fix return value for CLI_charIn 2024-04-13 16:52:52 +02:00
bbbc0c4683 fix memory leaks 2024-04-13 16:13:59 +02:00
dea1c8ae52 CLI: don't print an arrow on exit 2024-04-13 15:43:42 +02:00
e267e6f907 simplify some code and fix tiny bugs 2024-04-13 15:21:43 +02:00
9a437218a2 Merge branch 'master' into finley 2024-04-12 18:38:14 +02:00
Dennis Boekholtz
58d08e2951 Merge branch 'master' into Dennis_buffer 2024-04-12 17:48:47 +02:00
Dennis Boekholtz
36a442b42b Merge branch 'master' into Dennis_buffer 2024-04-10 16:17:36 +02:00
8 changed files with 503 additions and 82 deletions

317
CLI/CLI.c
View File

@ -3,12 +3,44 @@
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
// #include <config.h>
#include "../FIFOBuff/FIFOBuffChar.h"
#ifdef HISTORY
#include "../History/history.h"
#endif
CLI_charOutFn CLI_charOut;
CMDList_t* CMDList;
FIFOBuffChar_t* FIFO;
enum {
CLI_State_Default,
CLI_State_Esc,
CLI_State_ANSIVT100
} CLI_State = CLI_State_Default;
#ifdef HISTORY
History_t* History;
#endif
void CLI_charOut_save(char ch)
{
if (CLI_charOut != NULL)
{
// create string of size one to be compatable with string print function
char c[2] = {ch, 0};
(*CLI_charOut)(&c[0]);
}
}
void CLI_stringOut(char* str)
{
for (; *str != 0; str++)
{
CLI_charOut_save(*str);
}
}
// initilize and register the lineout print function
bool CLI_init(CLI_charOutFn lineOut, CMDList_t* cmdList)
@ -17,11 +49,13 @@ bool CLI_init(CLI_charOutFn lineOut, CMDList_t* cmdList)
CMDList = cmdList;
FIFO = FIFOBuffChar_create();
#ifdef HISTORY
History = History_init();
#endif
if (CLI_charOut != NULL)
{
(*CLI_charOut)(">");
(*CLI_charOut)(" ");
CLI_stringOut((char*)"> ");
}
return true;
@ -33,6 +67,9 @@ bool CLI_deinit()
CMDList = NULL;
FIFOBuffChar_delete(FIFO);
#ifdef HISTORY
History_deinit(History);
#endif
return true;
}
@ -41,7 +78,8 @@ char* fifoToString(FIFOBuffChar_t* fifo)
char* out = malloc(fifo->size + 1);
char* write_p = out;
for (int i = fifo->size; i > 0; i--)
int i;
for (i = fifo->size; i > 0; i--)
{
FIFOBuffChar_get(fifo, write_p);
write_p++;
@ -52,109 +90,238 @@ char* fifoToString(FIFOBuffChar_t* fifo)
return out;
}
#ifdef HISTORY
void CLI_PrintHistory()
{
char** historyList;
int ret = History_getFullHistory(History, &historyList);
if (ret >= 0)
{
for (int i=0; *(historyList + i) != NULL; i++)
{
printf("%03i: %s\n", i, *(historyList + i));
}
}
else
{
printf("ERROR: get history returnd: %i\n", ret);
}
free(historyList);
}
void historyPrevius()
{
char* line;
int i;
if (
(History_getCurrPos(History) == History_getSize(History))
&& (FIFOBuffChar_getSize(FIFO) > 0)
)
{
// add current text to end of history
line = fifoToString(FIFO);
History_put(History, line);
for (i=0; *(line + i) != '\0'; i++)
{
CLI_stringOut((char*)"\x1b[D \x1b[D");
}
History_getPrev(History, &line);
}
// empty current line
while (FIFOBuffChar_getSize(FIFO) > 0)
{
CLI_stringOut((char*)"\x1b[D \x1b[D");
FIFOBuffChar_pop(FIFO);
}
// get previus command
int ret = History_getPrev(History, &line);
// write line
if ((ret >= 0) && (line != NULL))
{
for (i=0; *(line + i) != '\0'; i++)
{
CLI_charIn(*(line + i));
}
}
}
void historyNext()
{
char* line;
// empty current line
while (FIFOBuffChar_getSize(FIFO) > 0)
{
CLI_stringOut((char*)"\x1b[D \x1b[D");
FIFOBuffChar_pop(FIFO);
}
// get next command
int ret = History_getNext(History, &line);
// write line
if ((ret >= 0) && (line != NULL))
{
int i;
for (i=0; *(line + i) != '\0'; i++)
{
CLI_charIn(*(line + i));
}
}
}
#endif
int tryExecute(FIFOBuffChar_t* fifo)
{
int ret = 0;
CMD_t* cmd = NULL;
char* line = fifoToString(fifo);
CMD_t* cmd = CMDList_get(CMDList, line);
if (*line == '\0')
{ // empty line
ret = 1;
CLI_stringOut((char*)"> ");
}
else
{
cmd = CMDList_get(CMDList, line);
}
if (cmd != NULL)
{
(*(cmd->fn))(line);
#ifdef HISTORY
History_put(History, line);
#endif
int ret = (*(cmd->fn))(line);
if (CLI_charOut != NULL)
if (ret != INT_MIN)
{
(*CLI_charOut)(">");
(*CLI_charOut)(" ");
CLI_stringOut((char*)"> ");
}
return true;
ret = 0;
}
else
else if (ret == 0)
{
if (CLI_charOut != NULL)
{
char err[100];
sprintf(&err[0], "command not found: %s\n> ", line);
for (int i=0; err[i] != 0; i++)
{
char c[2] = {err[i], 0};
(*CLI_charOut)(&c[0]);
}
CLI_stringOut(&err[0]);
}
return false;
ret = -1;
#ifdef HISTORY
free(line);
#endif
}
#ifndef HISTORY
free(line);
#endif
return ret;
}
// to recive a single caracter
bool CLI_charIn(char c)
{
bool ok = true;
if ((c >= 'a') && (c <= 'z'))
char str[100];
char C = c;
if ((C >= 'a') && (C <= 'z'))
{
c &= (~0x20); // convert to uppercase
C &= (~0x20); // convert to uppercase
}
if ( //TODO: update list of accepted characters
((c >= 'A') && (c <= 'Z'))
|| ((c >= '0') && (c <= '9'))
|| (c == ' ')
|| (c == '-')
|| (c == '_')
)
switch (CLI_State)
{
FIFOBuffChar_put(FIFO, c); // save char in buffer
if (CLI_charOut != NULL)
{ // echo to terminal
(*CLI_charOut)(&c);
}
}
else
{
char str[100];
switch (c)
{
case '\n':
case '\r':
if (CLI_charOut != NULL)
{ // echo to terminal
(*CLI_charOut)(&c);
}
FIFOBuffChar_t* fifo = FIFO;
FIFO = FIFOBuffChar_create();
ok = tryExecute(fifo);
FIFOBuffChar_delete(fifo);
break;
case 127: // backspace
if (FIFOBuffChar_pop(FIFO))
case CLI_State_Default:
if ( //TODO: update list of accepted characters
((C >= 'A') && (C <= 'Z'))
|| ((c >= '0') && (c <= '9'))
|| (c == ' ')
|| (c == '-')
|| (c == '_')
)
{
FIFOBuffChar_put(FIFO, C); // save char in buffer
CLI_charOut_save(c);
}
else
{
switch (c)
{
(*CLI_charOut)("\x1b");
(*CLI_charOut)("[");
(*CLI_charOut)("D");
(*CLI_charOut)(" ");
(*CLI_charOut)("\x1b");
(*CLI_charOut)("[");
(*CLI_charOut)("D");
}
break;
case '\n':
case '\r':
if (CLI_charOut != NULL)
{ // echo to terminal
char ch[2] = {c, 0};
(*CLI_charOut)(&ch[0]);
}
FIFOBuffChar_t* fifo = FIFO;
FIFO = FIFOBuffChar_create();
ok = (tryExecute(fifo) == 0);
FIFOBuffChar_delete(fifo);
break;
case 127: // backspace
if (FIFOBuffChar_pop(FIFO))
{ // pop something of the buffer
CLI_stringOut((char*)"\x1b[D \x1b[D"); // "<left arrow><space><left arrow>"
}
break;
case 27: // escape (start for arrow keys)
sprintf(&str[0], "\ninvlid char: ESC - (%i)\n", c);
for (int i=0; str[i] != 0; i++)
{
char ch[2] = {str[i], 0};
(*CLI_charOut)(&ch[0]);
}
break;
case 27: // escape (start for arrow keys)
CLI_State = CLI_State_Esc;
break;
default:
sprintf(&str[0], "\ninvlid char: '%c' - (%i)\n", c, c);
for (int i=0; str[i] != 0; i++)
{
char ch[2] = {str[i], 0};
(*CLI_charOut)(&ch[0]);
default:
sprintf(&str[0], "\ninvlid char: '%c' - (%i)\n", c, c);
CLI_stringOut(&str[0]);
break;
}
break;
}
}
break;
case CLI_State_Esc:
if (c == '[')
{
CLI_State = CLI_State_ANSIVT100;
}
else
{
CLI_State = CLI_State_Default;
}
break;
case CLI_State_ANSIVT100:
switch (c)
{
#ifdef HISTORY
case 'A': // arrow up
CLI_State = CLI_State_Default;
historyPrevius();
break;
case 'B': // arrow down
CLI_State = CLI_State_Default;
historyNext();
break;
case 'C': // arrow right
CLI_stringOut((char*)"(key: arrow right)");
CLI_State = CLI_State_Default;
break;
case 'D': // arrow left
CLI_stringOut((char*)"(key: arrow left)");
CLI_State = CLI_State_Default;
break;
#endif
default:
// only to back on on alpha char. seems to be the with all '\x1d[' commands
if ((C >= 'A') && (C <= 'Z'))
{
CLI_State = CLI_State_Default;
}
}
break;
}
return ok;

View File

@ -11,6 +11,10 @@ typedef int (*CLI_charOutFn)(const char* line);
bool CLI_init(CLI_charOutFn lineOut, CMDList_t* cmdList);
bool CLI_deinit();
#ifdef HISTORY
extern void CLI_PrintHistory();
#endif
// to recive a single caracter
bool CLI_charIn(char c);

View File

@ -18,20 +18,17 @@ CMDList_t* CMDList_init()
int CMDList_deinit(CMDList_t *list)
{
CMDList_t** list_p = (CMDList_t**)list;
// printf("deinit %p\n", (void*)list);
// printf("deinit e %p\n", list->e);
for (int i = 0; i < 26; i++)
int i;
for (i = 0; i < 26; i++)
{
if (*(list_p + i) != NULL)
{
// printf("deinit %i\n", i);
CMDList_deinit(*(list_p + i));
}
}
//TODO: fix "free(): invalid pointer"
// free(list);
free(*list_p);
return 0;
}

View File

@ -3,7 +3,7 @@
typedef struct CMD_t {
char* cmd;
void (*fn)(char* line);
int (*fn)(char* line);
} CMD_t;
typedef struct CMDList_s {

View File

@ -6,6 +6,13 @@ add_library(FIFOBuffChar FIFOBuff/FIFOBuffChar.c)
add_library(CMDList CMDList/CMDList.c)
add_library(CMDListPrint CMDList/printList.c)
# History
add_library(history History/History.c)
# CLI
add_library(CLI CLI/CLI.c)
target_link_libraries(CLI CMDList FIFOBuffChar)
add_library(CLI_History CLI/CLI.c)
target_link_libraries(CLI_History CMDList FIFOBuffChar history)
target_compile_definitions(CLI_History PRIVATE HISTORY)

View File

@ -141,6 +141,7 @@ bool FIFOBuffChar_pop(FIFOBuffChar_t *fifo)
default: // buffer is at least 2 element big
// find the second last element
{
FIFOBuffChar_element_t* secondLastEl = fifo->FirstEl_p;
while (
secondLastEl->nextElement != fifo->LastEl_p
@ -158,6 +159,7 @@ bool FIFOBuffChar_pop(FIFOBuffChar_t *fifo)
fifo->size--;
ok = true;
break;
}
}
return ok;

204
History/History.c Normal file
View File

@ -0,0 +1,204 @@
#include "history.h"
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
History_t* History_init()
{
History_t* history = malloc(sizeof(History_t));
if (history != NULL) {
history->FirstEl_p = NULL;
history->LastEl_p = NULL;
history->CurrEl_p = NULL;
history->size = 0;
}
return history;
}
int History_deinit(History_t* history)
{
// Check if the buffer there is something in the buffer
if (history->FirstEl_p == NULL)
{
// Delete all elements in the buffer
History_element_t* el = history->FirstEl_p;
while (el != NULL)
{
History_element_t* nextEl = el->nextEl_p;
free(el);
el = nextEl;
}
}
free(history);
return 0;
}
int History_put(History_t *history, char* line)
{
int retCode;
if ((history->LastEl_p == NULL) && (history->FirstEl_p == NULL))
{
// buffer is empty. add first element
history->FirstEl_p = malloc(sizeof(History_element_t));
if (history->FirstEl_p != NULL)
{
history->FirstEl_p->line = line;
history->FirstEl_p->prevEl_p = NULL;
history->FirstEl_p->nextEl_p = NULL;
history->LastEl_p = history->FirstEl_p;
history->size = 1;
retCode = 0;
}
else
{ // failt to allocate memory
retCode = -1;
}
}
else if ((history->LastEl_p != NULL) && (history->FirstEl_p != NULL))
{
// add element to exsiting buffer
History_element_t* el = malloc(sizeof(History_element_t));
if (el != NULL)
{
el->line = line;
el->prevEl_p = history->LastEl_p;
el->nextEl_p = NULL;
history->LastEl_p->nextEl_p = el;
history->LastEl_p = el;
history->size++;
retCode = 0;
}
else
{ // failt to allocate memory
retCode = -2;
}
}
else
{
retCode = -3;
}
if (retCode >= 0)
{
// reset current pointer
history->CurrEl_p = NULL;
}
return retCode;
}
int History_getPrev(History_t* history, char** line)
{
int retCode;
if (history->CurrEl_p == NULL)
{
history->CurrEl_p = history->LastEl_p;
}
else if (history->CurrEl_p->prevEl_p != NULL)
{
history->CurrEl_p = history->CurrEl_p->prevEl_p;
}
else
{ // no previus line
retCode = -2;
}
if (history->CurrEl_p != NULL)
{
*line = history->CurrEl_p->line;
retCode = 0;
}
else
{ // no items in history?
*line = NULL;
retCode = -1;
}
return 0;
}
int History_getNext(History_t* history, char** line)
{
int retCode;
if (history->CurrEl_p != NULL)
{
history->CurrEl_p = history->CurrEl_p->nextEl_p;
}
if (history->CurrEl_p != NULL)
{
*line = history->CurrEl_p->line;
retCode = 0;
}
else
{
*line = NULL;
retCode = -1;
}
return 0;
}
int History_getFullHistory(History_t* history, char*** list)
{
int retCode = 0;
*list = malloc(sizeof(char**) * (History_getSize(history) + 1));
History_element_t* el = history->FirstEl_p;
for (int i = 0; (i < History_getSize(history)-1) && (retCode >= 0); i++)
{
*((*list) + i) = el->line;
if (el->nextEl_p == NULL)
{
retCode = -1;
}
else
{
el = (History_element_t*)el->nextEl_p;
}
}
if (retCode >= 0)
{
// indicate end of list
*((*list) + History_getSize(history)) = NULL;
}
return retCode;
}
int History_getCurrPos(History_t* history)
{
int retCode = 0;
if (history->CurrEl_p != NULL)
{
History_element_t* el = history->FirstEl_p;
for (int i = 0; (el != history->CurrEl_p) && (retCode >= 0); i++)
{
if (el->nextEl_p == NULL)
{
retCode = 2;
}
else
{
el = (History_element_t*)el->nextEl_p;
}
}
}
else
{
retCode = History_getSize(history);
}
return retCode;
}
unsigned int History_getSize(History_t *history)
{
return history->size;
}

40
History/history.h Normal file
View File

@ -0,0 +1,40 @@
#ifndef HISTORY_H
#define HISTORY_H
#include <stdbool.h>
// one element in the buffer
typedef struct History_element_s {
void* prevEl_p;
char* line;
void* nextEl_p;
} History_element_t;
// defines all vars for the buffer to operate
typedef struct History_s {
History_element_t* FirstEl_p;
History_element_t* LastEl_p;
History_element_t* CurrEl_p;
unsigned char size;
} History_t;
// create a fifo buffer and initilizes it with zeros
extern History_t* History_init();
// destroy a fifo buffer (free up its space)
extern int History_deinit(History_t* history);
// put value i in buffer if there is still memory avaliable
extern int History_put(History_t *history, char* line);
// get value from buffer and writes it to *line
extern int History_getPrev(History_t* history, char** line);
extern int History_getNext(History_t* history, char** line);
extern int History_getCurrPos(History_t* history);
extern int History_getFullHistory(History_t* history, char*** list);
extern unsigned int History_getSize(History_t *history);
#endif