Prepare shell environment implmentation

This commit is contained in:
Yann Weber 2023-03-07 11:49:11 +01:00
commit 9b325d5c36
5 changed files with 290 additions and 3 deletions

View file

@ -1,7 +1,7 @@
bin_PROGRAMS = asmsh child
libcheck_asmsh_a_SOURCES = mmap_parse.c asm_env.c compile.c logger.c \
completion.c shell.c shell_cmds.c
completion.c shell.c shell_cmds.c shell_env.c
asmsh_SOURCES = asmsh.c $(libcheck_asmsh_a_SOURCES)
child_SOURCES = child.s
@ -21,7 +21,7 @@ noinst_LIBRARIES = libcheck_asmsh.a
if HAVE_GCOV
libcheck_asmsh_a_CFLAGS = @CFLAGS@ -fprofile-arcs -ftest-coverage
gcov:
gcov: tests/test-suite.log
$(GCOV) -j *.gcno
TO_LOCAL_CLEAN=*.gcov *.gcda *.gcno
@ -34,7 +34,7 @@ LCOV_HTML=lcov_html
TO_LOCAL_CLEAN += $(LCOV_INFO) $(LCOV_HTML)
$(LCOV_INFO): gcov
$(LCOV) --capture --directory . --output-file $@
$(LCOV) --capture --no-recursion --directory . --output-file $@
$(LCOV_HTML): $(LCOV_INFO)
genhtml $< --output-directory $@

View file

@ -10,6 +10,7 @@
#include "compile.h"
typedef struct asmsh_s asmsh_t;
#include "shell_sym.h"
struct asmsh_s
{

144
shell_sym.c Normal file
View file

@ -0,0 +1,144 @@
#include "shell_env.h"
int asmsh_symtable_init(asmsh_symtable_t *table, short freeval)
{
int err;
table->freeval = freeval?1:0;
table->alloc = ASMSH_SYMALLOC;
table->syms = malloc(table->alloc*sizeof(*table->syms));
if(!table->syms)
{
err = errno;
goto err;
}
bzero(table->syms, table->alloc*sizeof(*table->syms));
table->syms_sz = 0;
return 0;
err:
bzero(table, sizeof(*table));
errno=err;
return -1;
}
void asmsh_symtable_clean(asmsh_symtable_t *table)
{
if(table->freeval)
{
for(int i=0; i<table->syms_sz; i++)
{
free(table->syms[i].val);
}
}
free(table->syms);
bzero(table, sizeof(*table));
}
int asmsh_symtable_add(asmsh_symtable_t *table, const char *name, void *val)
{
int i;
if(strlen(name)>ASMSH_VARNAME_MAX)
{
errno=EINVAL;
return -1;
}
if(table->syms_sz >= table->alloc-1)
{
table->alloc += ASMSH_SYMALLOC;
void *tmp = realloc(table->syms, sizeof(*table->syms)*table->alloc);
if(!tmp)
{
return -1;
}
table->syms = tmp;
}
for(i=0; i<table->syms_sz; i++)
{
int cmp = strcmp(name, table->syms[i].name);
if(cmp == 0)
{
//update value
if(table->freeval)
{
free(table->syms[i].val);
}
table->syms[i].val = val;
return 0;
}
else if(cmp > 0)
{
break;
}
}
if(i<table->syms_sz)
{
memmove(&table->syms[i+1], &table->syms[i],
sizeof(*table->syms)*(table->syms_sz - i));
}
strncpy(table->syms[i].name, name, ASMSH_VARNAME_MAX);
table->syms[i].name[ASMSH_VARNAME_MAX] = '\0';
table->syms[i].val = val;
table->syms_sz++;
return 0;
}
int asmsh_symtable_del(asmsh_symtable_t *table, const char *name)
{
if(strlen(name) > ASMSH_VARNAME_MAX)
{
return 0;
}
int i=0;
for(i=0; i<table->syms_sz; i++)
{
int cmp = strncmp(name, table->syms[i].name, ASMSH_VARNAME_MAX);
if(!cmp) { break; }
}
if(i==table->syms_sz)
{
return 0; // not found
}
if(table->freeval) { free(table->syms[i].val); }
if(table->syms_sz > i+1)
{
memmove(&table->syms[i], &table->syms[i+1],
sizeof(*table->syms)*(table->syms_sz - (i+1)));
if((table->alloc - table->syms_sz) > ASMSH_SYMALLOC*2)
{
table->alloc -= ASMSH_SYMALLOC;
void *tmp = realloc(table->syms,
sizeof(*table->syms)*table->alloc);
if(!tmp)
{
return 0; // :/
}
table->syms = tmp;
}
}
table->syms_sz--;
return 1; // 1 deleted
}
const asmsh_sym_t *asmsh_symtable_get(asmsh_symtable_t *table, const char *name)
{
if(strlen(name) > ASMSH_VARNAME_MAX)
{
return NULL;
}
for(int i=0; i<table->syms_sz; i++)
{
int cmp = strcmp(name, table->syms[i].name);
if(!cmp)
{
return &(table->syms[i]);
}
if(cmp > 0) { break; }
}
return NULL;
}

40
shell_sym.h Normal file
View file

@ -0,0 +1,40 @@
#ifndef ASMSH_SHELL_ENV_H
#define ASMSH_SHELL_ENV_H
#include "config.h"
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#define ASMSH_VARNAME_MAX 31
#define ASMSH_SYMALLOC 64
typedef struct asmsh_sym_s asmsh_sym_t;
typedef struct asmsh_symtable_s asmsh_symtable_t;
struct asmsh_sym_s
{
char name[ASMSH_VARNAME_MAX + 1];
void *val;
};
struct asmsh_symtable_s
{
short freeval;
asmsh_sym_t *syms;
size_t syms_sz;
size_t alloc;
};
/** if freeval value given to add are freed on clean */
int asmsh_symtable_init(asmsh_symtable_t *table, short freeval);
void asmsh_symtable_clean(asmsh_symtable_t *table);
int asmsh_symtable_add(asmsh_symtable_t *table, const char *name, void *val);
int asmsh_symtable_del(asmsh_symtable_t *table, const char *name);
const asmsh_sym_t *asmsh_symtable_get(asmsh_symtable_t *table, const char *name);
#include "shell.h"
#endif

102
tests/tests_shell_env.c Normal file
View file

@ -0,0 +1,102 @@
#include "config.h"
#include <check.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include "asmsh_check.h"
#include "shell_env.h"
START_TEST(init)
{
asmsh_symtable_t st;
ck_assert_int_eq(asmsh_symtable_init(&st,0), 0);
asmsh_symtable_clean(&st);
}
END_TEST
START_TEST(add)
{
asmsh_symtable_t st;
ck_assert_int_eq(asmsh_symtable_init(&st,0), 0);
ck_assert_int_eq(asmsh_symtable_add(&st, "b", NULL), 0);
ck_assert_int_eq(st.syms_sz, 1);
ck_assert_int_eq(asmsh_symtable_add(&st, "a", NULL), 0);
ck_assert_int_eq(st.syms_sz, 2);
ck_assert_int_eq(asmsh_symtable_add(&st, "a", NULL), 0);
ck_assert_int_eq(st.syms_sz, 2);
ck_assert_int_eq(asmsh_symtable_add(&st, "ab", NULL), 0);
ck_assert_int_eq(st.syms_sz, 3);
asmsh_symtable_clean(&st);
}
END_TEST
START_TEST(del)
{
asmsh_symtable_t st;
ck_assert_int_eq(asmsh_symtable_init(&st,0), 0);
ck_assert_int_eq(asmsh_symtable_del(&st, "a"), 0);
ck_assert_int_eq(asmsh_symtable_add(&st, "a", NULL), 0);
ck_assert_int_eq(asmsh_symtable_del(&st, "a"), 1);
ck_assert_int_eq(asmsh_symtable_del(&st, "a"), 0);
ck_assert_int_eq(asmsh_symtable_add(&st, "a", NULL), 0);
ck_assert_int_eq(asmsh_symtable_add(&st, "b", NULL), 0);
ck_assert_int_eq(asmsh_symtable_add(&st, "c", NULL), 0);
ck_assert_int_eq(asmsh_symtable_del(&st, "d"), 0);
ck_assert_int_eq(asmsh_symtable_del(&st, "b"), 1);
ck_assert_int_eq(asmsh_symtable_del(&st, "b"), 0);
ck_assert_int_eq(asmsh_symtable_add(&st, "b", NULL), 0);
ck_assert_int_eq(asmsh_symtable_del(&st, "a"), 1);
ck_assert_int_eq(asmsh_symtable_del(&st, "a"), 0);
asmsh_symtable_clean(&st);
}
END_TEST
START_TEST(get)
{
asmsh_symtable_t st;
const asmsh_sym_t *s;
ck_assert_int_eq(asmsh_symtable_init(&st,0), 0);
ck_assert_ptr_null(asmsh_symtable_get(&st, "a"));
ck_assert_int_eq(asmsh_symtable_add(&st, "a", NULL), 0);
s = asmsh_symtable_get(&st, "a");
ck_assert_ptr_nonnull(s);
ck_assert_ptr_null(s->val);
ck_assert_int_eq(asmsh_symtable_add(&st, "a", (void*)42), 0);
s = asmsh_symtable_get(&st, "a");
ck_assert_ptr_nonnull(s);
ck_assert_ptr_eq(s->val, (void*)42);
asmsh_symtable_clean(&st);
}
END_TEST
START_TEST(_realloc)
{
asmsh_symtable_t st;
ck_assert_int_eq(asmsh_symtable_init(&st,0), 0);
for(int i=0; i<ASMSH_SYMALLOC*3; i++)
{
char buf[16];
snprintf(buf, 15, "a%d", i);
ck_assert_int_eq(asmsh_symtable_add(&st, buf, NULL), 0);
}
for(int i=0; i<ASMSH_SYMALLOC*3; i++)
{
char buf[16];
snprintf(buf, 15, "a%d", i);
ck_assert_int_eq(asmsh_symtable_del(&st, buf), 1);
}
asmsh_symtable_clean(&st);
}
END_TEST
ASMSH_CHECK_START("testing completion", "Testing completion features")
ASMSH_ADD_TEST(init);
ASMSH_ADD_TEST(add);
ASMSH_ADD_TEST(del);
ASMSH_ADD_TEST(get);
ASMSH_ADD_TEST(_realloc);
ASMSH_CHECK_END