Compare commits

35 Commits

Author SHA1 Message Date
Dennis Boekholtz
34f830bd1d Merge branch 'Dennis_buffer' 2024-04-14 23:36:12 +02:00
Dennis Boekholtz
7eab42c3b9 Merge branch 'master' into Dennis_buffer 2024-04-14 23:35:52 +02:00
522c14710e Merge branch 'finley' 2024-04-14 23:32:36 +02:00
3ed2ab432b update 2024-04-14 23:30:44 +02:00
8ddf982e78 Merge branch 'finley' 2024-04-14 22:50:57 +02:00
Dennis Boekholtz
91f3c8461e Merge remote-tracking branch 'origin/HEAD' into Dennis_buffer 2024-04-14 22:50:55 +02:00
9c30ea4ef1 Merge branch 'master' 2024-04-14 22:50:18 +02:00
62f45f7256 fix memory leaks 2024-04-14 22:47:18 +02:00
Dennis Boekholtz
92eb70f4b5 Merge branch 'Dennis_CCS' 2024-04-14 21:10:48 +02:00
Dennis Boekholtz
cb7b573eed Merge branch 'master' into Dennis_CCS 2024-04-14 21:10:15 +02:00
Dennis Boekholtz
04eebfc3fc CLI & History features aan gezet en werkende gekregen op CC3220 2024-04-14 21:09:20 +02:00
Dennis Boekholtz
5ed7154183 Merge branch 'master' into Dennis_buffer 2024-04-14 16:37:50 +02:00
Dennis Boekholtz
51c1c28756 Merge branch 'Dennis_CCS' 2024-04-14 15:00:33 +02:00
Dennis Boekholtz
cd72e519a1 Merge branch 'master' into Dennis_CCS 2024-04-14 14:57:10 +02:00
df2129a1bb history: fix memory leak 2024-04-14 12:28:27 +02:00
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
ee501b17ce Merge branch 'Dennis_CCS' into Dennis_buffer 2024-04-13 23:19:12 +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
64a72b70ef CMDList: separate command name from comand object for alias 2024-04-12 18:32:39 +02:00
8 changed files with 521 additions and 91 deletions

320
CLI/CLI.c
View File

@@ -3,12 +3,45 @@
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <limits.h>
// #include <config.h>
#define HISTORY
#include "../FIFOBuff/FIFOBuffChar.h" #include "../FIFOBuff/FIFOBuffChar.h"
#ifdef HISTORY
#include "../History/history.h"
#endif
CLI_charOutFn CLI_charOut; CLI_charOutFn CLI_charOut;
CMDList_t* CMDList; CMDList_t* CMDList;
FIFOBuffChar_t* FIFO; 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 // initilize and register the lineout print function
bool CLI_init(CLI_charOutFn lineOut, CMDList_t* cmdList) bool CLI_init(CLI_charOutFn lineOut, CMDList_t* cmdList)
@@ -17,11 +50,13 @@ bool CLI_init(CLI_charOutFn lineOut, CMDList_t* cmdList)
CMDList = cmdList; CMDList = cmdList;
FIFO = FIFOBuffChar_create(); FIFO = FIFOBuffChar_create();
#ifdef HISTORY
History = History_init();
#endif
if (CLI_charOut != NULL) if (CLI_charOut != NULL)
{ {
(*CLI_charOut)(">"); CLI_stringOut((char*)"> ");
(*CLI_charOut)(" ");
} }
return true; return true;
@@ -33,6 +68,9 @@ bool CLI_deinit()
CMDList = NULL; CMDList = NULL;
FIFOBuffChar_delete(FIFO); FIFOBuffChar_delete(FIFO);
#ifdef HISTORY
History_deinit(History, true);
#endif
return true; return true;
} }
@@ -41,7 +79,8 @@ char* fifoToString(FIFOBuffChar_t* fifo)
char* out = malloc(fifo->size + 1); char* out = malloc(fifo->size + 1);
char* write_p = out; 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); FIFOBuffChar_get(fifo, write_p);
write_p++; write_p++;
@@ -52,109 +91,240 @@ char* fifoToString(FIFOBuffChar_t* fifo)
return out; return out;
} }
#ifdef HISTORY
void CLI_PrintHistory()
{
char** historyList;
int ret = History_getFullHistory(History, &historyList);
int i;
if (ret >= 0)
{
for (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 tryExecute(FIFOBuffChar_t* fifo)
{ {
int ret = 0;
CMD_t* cmd = NULL;
char* line = fifoToString(fifo); 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) 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_stringOut((char*)"> ");
(*CLI_charOut)(" ");
} }
return true; ret = 0;
} }
else else if (ret == 0)
{ {
if (CLI_charOut != NULL) if (CLI_charOut != NULL)
{ {
char err[100]; char err[100];
sprintf(&err[0], "command not found: %s\n> ", line); sprintf(&err[0], "command not found: %s\n> ", line);
for (int i=0; err[i] != 0; i++) CLI_stringOut(&err[0]);
{
char c[2] = {err[i], 0};
(*CLI_charOut)(&c[0]);
}
} }
return false; ret = -1;
#ifdef HISTORY
free(line);
#endif
} }
#ifndef HISTORY
free(line);
#endif
return ret;
} }
// to recive a single caracter // to recive a single caracter
bool CLI_charIn(char c) bool CLI_charIn(char c)
{ {
bool ok = true; 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 switch (CLI_State)
((c >= 'A') && (c <= 'Z'))
|| ((c >= '0') && (c <= '9'))
|| (c == ' ')
|| (c == '-')
|| (c == '_')
)
{ {
FIFOBuffChar_put(FIFO, c); // save char in buffer case CLI_State_Default:
if (CLI_charOut != NULL) if ( //TODO: update list of accepted characters
{ // echo to terminal ((C >= 'A') && (C <= 'Z'))
(*CLI_charOut)(&c); || ((c >= '0') && (c <= '9'))
} || (c == ' ')
} || (c == '-')
else || (c == '_')
{ )
char str[100]; {
switch (c) FIFOBuffChar_put(FIFO, C); // save char in buffer
{ CLI_charOut_save(c);
case '\n': }
case '\r': else
if (CLI_charOut != NULL) {
{ // echo to terminal switch (c)
(*CLI_charOut)(&c);
}
FIFOBuffChar_t* fifo = FIFO;
FIFO = FIFOBuffChar_create();
ok = tryExecute(fifo);
FIFOBuffChar_delete(fifo);
break;
case 127: // backspace
if (FIFOBuffChar_pop(FIFO))
{ {
(*CLI_charOut)("\x1b"); case '\n':
(*CLI_charOut)("["); case '\r':
(*CLI_charOut)("D"); if (CLI_charOut != NULL)
(*CLI_charOut)(" "); { // echo to terminal
(*CLI_charOut)("\x1b"); char ch[2] = {c, 0};
(*CLI_charOut)("["); (*CLI_charOut)(&ch[0]);
(*CLI_charOut)("D"); }
} FIFOBuffChar_t* fifo = FIFO;
break; FIFO = FIFOBuffChar_create();
ok = (tryExecute(fifo) == 0);
FIFOBuffChar_delete(fifo);
break;
case 8:
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) case 27: // escape (start for arrow keys)
sprintf(&str[0], "\ninvlid char: ESC - (%i)\n", c); CLI_State = CLI_State_Esc;
for (int i=0; str[i] != 0; i++) break;
{
char ch[2] = {str[i], 0};
(*CLI_charOut)(&ch[0]);
}
break;
default: default:
sprintf(&str[0], "\ninvlid char: '%c' - (%i)\n", c, c); sprintf(&str[0], "\ninvlid char: '%c' - (%i)\n", c, c);
for (int i=0; str[i] != 0; i++) CLI_stringOut(&str[0]);
{ break;
char ch[2] = {str[i], 0};
(*CLI_charOut)(&ch[0]);
} }
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; 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_init(CLI_charOutFn lineOut, CMDList_t* cmdList);
bool CLI_deinit(); bool CLI_deinit();
#ifdef HISTORY
extern void CLI_PrintHistory();
#endif
// to recive a single caracter // to recive a single caracter
bool CLI_charIn(char c); bool CLI_charIn(char c);

View File

@@ -8,46 +8,43 @@
// initilises a CMDList_t with all NULL pointers // initilises a CMDList_t with all NULL pointers
CMDList_t* CMDList_init() CMDList_t* CMDList_init()
{ {
CMDList_t *list = malloc(sizeof(CMDList_t)); CMDList_t* list = malloc(sizeof(CMDList_t));
memset(list, 0, sizeof(CMDList_t)); memset(list, 0, sizeof(CMDList_t));
return list; return list;
} }
// free up the full tree from memory // free up the full tree from memory
// does not free up the commands // does not free up the commands
int CMDList_deinit(CMDList_t *list) int CMDList_deinit(CMDList_t* list)
{ {
CMDList_t** list_p = (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) if (*(list_p + i) != NULL)
{ {
// printf("deinit %i\n", i);
CMDList_deinit(*(list_p + i)); CMDList_deinit(*(list_p + i));
} }
} }
//TODO: fix "free(): invalid pointer" free(list);
// free(list);
return 0; return 0;
} }
// add a command in the command tree // add a command in the command tree
int CMDList_add(CMDList_t *list, CMD_t* cmd) int CMDList_add(CMDList_t *list, CMD_t* cmd, char* cmdName)
{ {
int returnCode = 0; int returnCode = 0;
char* read_p = cmd->cmd; char* read_p = cmdName;
CMDList_t** list_p = (CMDList_t**)list; CMDList_t** list_p = (CMDList_t**)list;
if (read_p == NULL) if (read_p == NULL)
{ // cmd is missing a string for the commnad name {
returnCode = -1; read_p = cmd->cmd;
} }
while (returnCode == 0) while (returnCode >= 0)
{ {
char c = *read_p & (~0x20); // convert to uppercase char c = *read_p & (~0x20); // convert to uppercase
if ((c >= 'A') && (c <= 'Z')) if ((c >= 'A') && (c <= 'Z'))

View File

@@ -3,7 +3,7 @@
typedef struct CMD_t { typedef struct CMD_t {
char* cmd; char* cmd;
void (*fn)(char* line); int (*fn)(char* line);
} CMD_t; } CMD_t;
typedef struct CMDList_s { typedef struct CMDList_s {
@@ -46,7 +46,7 @@ extern CMDList_t* CMDList_init();
extern int CMDList_deinit(CMDList_t *list); extern int CMDList_deinit(CMDList_t *list);
// add a command in the command tree // add a command in the command tree
extern int CMDList_add(CMDList_t *list, CMD_t* cmd); extern int CMDList_add(CMDList_t *list, CMD_t* cmd, char* cmdName);
// search command in the tree // search command in the tree
extern CMD_t* CMDList_get(CMDList_t *list, char* cmd); extern CMD_t* CMDList_get(CMDList_t *list, char* cmd);

View File

@@ -6,6 +6,13 @@ add_library(FIFOBuffChar FIFOBuff/FIFOBuffChar.c)
add_library(CMDList CMDList/CMDList.c) add_library(CMDList CMDList/CMDList.c)
add_library(CMDListPrint CMDList/printList.c) add_library(CMDListPrint CMDList/printList.c)
# History
add_library(history History/History.c)
# CLI # CLI
add_library(CLI CLI/CLI.c) add_library(CLI CLI/CLI.c)
target_link_libraries(CLI CMDList FIFOBuffChar) target_link_libraries(CLI CMDList FIFOBuffChar history)
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 default: // buffer is at least 2 element big
// find the second last element // find the second last element
{
FIFOBuffChar_element_t* secondLastEl = fifo->FirstEl_p; FIFOBuffChar_element_t* secondLastEl = fifo->FirstEl_p;
while ( while (
secondLastEl->nextElement != fifo->LastEl_p secondLastEl->nextElement != fifo->LastEl_p
@@ -158,6 +159,7 @@ bool FIFOBuffChar_pop(FIFOBuffChar_t *fifo)
fifo->size--; fifo->size--;
ok = true; ok = true;
break; break;
}
} }
return ok; return ok;

210
History/History.c Normal file
View File

@@ -0,0 +1,210 @@
#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, bool freeLines)
{
// 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;
if (freeLines)
{
free(el->line);
}
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;
int i;
for (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;
int i;
for (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, bool freeLines);
// 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