Browse Source

Basic support for variables set drop listvars

master
alistair 4 years ago
parent
commit
a167dfecc9
  1. 1
      error.h
  2. 228
      main.c
  3. 24
      main.h
  4. 14
      util.c
  5. 2
      util.h

1
error.h

@ -6,6 +6,7 @@ enum ExitCodes { @@ -6,6 +6,7 @@ enum ExitCodes {
ER_SUCCESS,
ER_FAILURE,
ER_FAIL_TO_FORK,
ER_NOT_EXISTS,
ER_ALLOC
};

228
main.c

@ -3,6 +3,21 @@ @@ -3,6 +3,21 @@
#include "main.h"
#include "util.h"
#include <dirent.h>
int get_alias(Alias *alias, State *state, char *name);
int add_alias(State* state, char *name, char *substitution);
int del_alias(State *state, char *name);
int repl(State* state, FILE *input);
GrowingArray get_growing_array(size_t num_elements, size_t size_elem) {
GrowingArray arr;
arr.inner = calloc(num_elements, size_elem);
arr.space = num_elements;
arr.elements = 0;
return arr;
}
int get_alias(Alias *alias, State *state, char *name) {
for (int i = 0; i < state->num_aliases; i++) {
if (!strcmp(name, state->aliases[i].name)) {
@ -13,9 +28,100 @@ int get_alias(Alias *alias, State *state, char *name) { @@ -13,9 +28,100 @@ int get_alias(Alias *alias, State *state, char *name) {
return ER_FAILURE;
}
int del_alias(State *state, char *name);
int get_array_element(ArrayElement **ret, GrowingArray* array, char* key) {
for (int i = 0; i < array->elements; i++) {
if (!strcmp(key, array->inner[i].key)) {
*ret = array->inner + i;
return ER_SUCCESS;
}
}
return ER_NOT_EXISTS;
}
int check_array_space(GrowingArray* array) {
int resize = 0;
if (array->elements > MIN_ARRAY_SIZE) {
if (array->elements >= array->space - 2) {
resize = 2 * array->space;
} else if (array->elements < (array->space / 3)) {
resize = array->space / 2;
}
}
if (resize) {
void *new = reallocarray(array->inner, resize,
sizeof(ArrayElement));
if (new) {
array->space = resize;
array->inner = new;
return ER_SUCCESS;
} else {
return ER_FAILURE;
}
} else {
return ER_SUCCESS;
}
}
int add_alias(State* state, char *name, char *substitution) {
int set_array_element(GrowingArray* array, char* key, void* value,
size_t valsize) {
ArrayElement *arr;
if (!get_array_element(&arr, array, key)) {
free(arr->value);
arr->value = dualloc(value, valsize);
return ER_SUCCESS;
} else {
check_array_space(array);
void *val = dualloc(value, valsize);
void *nkey = dualloc(key, (strlen(key) + 1) * sizeof(char));
if (value && key) {
array->inner[array->elements].value = val;
array->inner[array->elements].key = nkey;
array->elements++;
return ER_SUCCESS;
}
}
return ER_FAILURE;
}
int del_array_element(GrowingArray* array, char* key) {
ArrayElement *elem;
int err = get_array_element(&elem, array, key);
if (err) {
return err;
} else {
bool move = false;
for (int i = 0; i < array->elements; i++) {
if (move) {
if (i == array->elements - 1) {
memset(&array->inner[i], 0, sizeof(ArrayElement));
} else {
array->inner[i] = array->inner[i+1];
}
}
if (!strcmp(array->inner[i].key, key)) {
if (!move) {
free(array->inner[i].key);
free(array->inner[i].value);
move = true;
// move
if (i == array->elements - 1) {
memset(&array->inner[i], 0, sizeof(ArrayElement));
} else {
array->inner[i] = array->inner[i+1];
}
}
}
}
array->elements--;
return ER_SUCCESS;
}
return ER_FAILURE;
}
int add_alias(State* state, char* name, char* substitution) {
Alias alias;
strip_char(name, ' ');
alias.name = calloc(strlen(name) + 1, sizeof(char));
@ -23,9 +129,9 @@ int add_alias(State* state, char *name, char *substitution) { @@ -23,9 +129,9 @@ int add_alias(State* state, char *name, char *substitution) {
strcpy(alias.name, name);
strcpy(alias.substitution, substitution);
Alias throw;
Alias existing;
if (get_alias(&throw, state, name)) {
if (get_alias(&existing, state, name)) {
// add it if it doesnt exist
state->aliases[state->num_aliases] = alias;
@ -74,6 +180,25 @@ int list_aliases(State *state) { @@ -74,6 +180,25 @@ int list_aliases(State *state) {
return ER_SUCCESS;
}
int list_variables(State *state) {
for (int i = 0; i < state->variables.elements; i++) {
char *key = state->variables.inner[i].key;
char *value = state->variables.inner[i].value;
fprintf(state->output, "%s=%s\n", key, value);
}
return ER_SUCCESS;
}
void shutdown(State *state) {
for (int i = 0; i < state->num_aliases; i++) {
free(state->aliases[i].name);
free(state->aliases[i].substitution);
}
free(state->ps1);
free(state);
exit(0);
}
int check_builtins(State *state, int num_args, char *args[]) {
char *builtins[NUM_BUILTINS] = {
"cd",
@ -82,19 +207,54 @@ int check_builtins(State *state, int num_args, char *args[]) { @@ -82,19 +207,54 @@ int check_builtins(State *state, int num_args, char *args[]) {
};
if (!strcmp(args[0], "cd")) {
if (num_args == 1) {
chdir(getenv("HOME"));
return ER_SUCCESS;
}
if (num_args != 2) {
return ER_FAILURE;
}
chdir(args[1]);
}
if (!strcmp(args[0], "set")) {
if (num_args >= 2) {
char *joined;
int err = join_string(&joined, num_args -1, args + 1, " ");
char **split;
int num;
err = split_string(&split, &num, joined, '=');
if (num == 2) {
char * key = split[0];
char * value = split[1];
set_array_element(&state->variables, key, value,
(strlen(value) + 1) * sizeof(char));
return ER_SUCCESS;
} else {
return ER_FAILURE;
}
}
}
if (!strcmp(args[0], "listvars")) {
list_variables(state);
return ER_SUCCESS;
}
if (!strcmp(args[0], "drop")) {
if (num_args == 2) {
char *key = args[1];
int err = del_array_element(&state->variables, key);
if (err) {
return ER_FAILURE;
} else {
return ER_SUCCESS;
}
}
return ER_FAILURE;
}
if (!strcmp(args[0], "alias")) {
Alias alias;
// list aliases
@ -106,14 +266,16 @@ int check_builtins(State *state, int num_args, char *args[]) { @@ -106,14 +266,16 @@ int check_builtins(State *state, int num_args, char *args[]) {
if (num_args >= 2) {
if (num_args == 2) {
if (!get_alias(&alias, state, args[1])) {
fprintf(state->output, "alias %s=%s\n", alias.name, alias.substitution);
fprintf(state->output, "alias %s=%s\n", alias.name,
alias.substitution);
return ER_SUCCESS;
}
}
if (num_args >= 2) {
char *substitution;
char **new_split;
int err = join_string(&substitution, num_args - 1, args + 1, " ");
int err = join_string(&substitution, num_args - 1,
args + 1, " ");
if (err) {
return err;
}
@ -141,7 +303,33 @@ int check_builtins(State *state, int num_args, char *args[]) { @@ -141,7 +303,33 @@ int check_builtins(State *state, int num_args, char *args[]) {
}
}
return ER_FAILURE;
if (!strcmp(args[0], "run")) {
if (num_args == 2) {
FILE *file = fopen(args[1], "r");
if (!file) {
return ER_FAILURE;
}
bool temp_repl_state = state->interactive;
state->interactive = false;
int err;
if ((err = repl(state, file))) {
perror("Config file error");
return err;
}
state->interactive = temp_repl_state;
fclose(file);
return ER_SUCCESS;
}
}
if (!strcmp(args[0], "exit")) {
if (num_args == 1) {
shutdown(state);
return ER_FAILURE;
}
}
return ER_NOT_EXISTS;
}
int check_aliases(State *state, char **substitution, char *name) {
@ -155,6 +343,7 @@ int check_aliases(State *state, char **substitution, char *name) { @@ -155,6 +343,7 @@ int check_aliases(State *state, char **substitution, char *name) {
return ER_FAILURE;
}
int run_command(State *state, int argc, char *argv[]) {
pid_t child;
@ -184,7 +373,7 @@ int run_command(State *state, int argc, char *argv[]) { @@ -184,7 +373,7 @@ int run_command(State *state, int argc, char *argv[]) {
free(new_argv);
}
if (check_builtins(state, argc, argv)) {
if (check_builtins(state, argc, argv) == ER_NOT_EXISTS) {
execute(stdin, stdout, argv, &child);
waitpid(child, NULL, 0);
}
@ -196,8 +385,8 @@ int repl(State* state, FILE *input) { @@ -196,8 +385,8 @@ int repl(State* state, FILE *input) {
while (true) {
char *line;
if (state->repl) {
fprintf(state->output, "$ ");
if (state->interactive) {
fprintf(state->output, "%s", state->ps1);
}
if (readline(input, &line)) {
@ -223,6 +412,11 @@ int repl(State* state, FILE *input) { @@ -223,6 +412,11 @@ int repl(State* state, FILE *input) {
int startup(State *state, int argc, char **argv) {
state->output = stdout;
state->ps1 = calloc(3, sizeof(char));
strcpy(state->ps1, "$ ");
state->variables = get_growing_array(INITIAL_NUM_VARIABLES, sizeof(char*));
char *config_home;
char *config = calloc(500, sizeof(char));
if ((config_home = getenv("XDG_CONFIG_HOME"))) {
@ -240,13 +434,14 @@ int startup(State *state, int argc, char **argv) { @@ -240,13 +434,14 @@ int startup(State *state, int argc, char **argv) {
int err;
FILE* rc = fopen(config, "r");
if (rc) {
state->repl = false;
state->interactive = false;
state->input = rc;
if ((err = repl(state, rc))) {
perror("Config file error");
return err;
}
}
fclose(rc);
if (argc == 2) {
FILE *script_text = fopen(argv[1], "r");
@ -262,7 +457,6 @@ int startup(State *state, int argc, char **argv) { @@ -262,7 +457,6 @@ int startup(State *state, int argc, char **argv) {
}
int main(int argc, char** argv) {
State *state = calloc(1, sizeof(State));
state->aliases = calloc(INITIAL_NUM_ALIASES, sizeof(struct Alias));
state->num_aliases = 0;
@ -273,10 +467,10 @@ int main(int argc, char** argv) { @@ -273,10 +467,10 @@ int main(int argc, char** argv) {
}
if (state->code) {
state->repl = false;
state->interactive = false;
repl(state, state->code);
} else {
state->repl = true;
state->interactive = true;
print_chicken(state);
repl(state, stdin);
}

24
main.h

@ -13,6 +13,11 @@ @@ -13,6 +13,11 @@
#define INITIAL_LINE_BUFFER 80
#define INITIAL_WORD_SIZE 80
#define INITIAL_NUM_ALIASES 50
#define INITIAL_NUM_VARIABLES 200
// the minimum size of an array, the automaic array allocator will not make
// arrays smaller than this
#define MIN_ARRAY_SIZE 50
#define NUM_BUILTINS 3
@ -21,13 +26,30 @@ struct Alias { @@ -21,13 +26,30 @@ struct Alias {
char *substitution;
};
struct ArrayElement {
void *value;
char *key;
};
typedef struct ArrayElement ArrayElement;
struct GrowingArray {
struct ArrayElement *inner;
int elements;
int space;
};
typedef struct GrowingArray GrowingArray;
struct State {
struct Alias* aliases;
struct GrowingArray variables;
int num_aliases;
FILE* code;
FILE *input;
FILE *output;
bool repl;
bool interactive;
char *ps1;
};
typedef struct State State;

14
util.c

@ -1,5 +1,15 @@ @@ -1,5 +1,15 @@
#include "util.h"
void *dualloc(void *thing, size_t size) {
void *dupl = malloc(size);
memset(dupl, 0, size);
memcpy(dupl, thing, size);
return dupl;
}
/* Read a line into a newly created buffer */
int readline(FILE* in, char **out) {
int size_of_buffer = INITIAL_LINE_BUFFER;
char *buffer = calloc(size_of_buffer, sizeof(char));
@ -44,7 +54,8 @@ int join_string(char **joined, int arr_len, char *sep_stirng[], char *delim) { @@ -44,7 +54,8 @@ int join_string(char **joined, int arr_len, char *sep_stirng[], char *delim) {
for (int i = 0; i < arr_len; i++) {
if (length == stringsize - 2) {
new_string = reallocarray(new_string, stringsize *= 2, sizeof(char));
new_string = reallocarray(new_string, stringsize *= 2,
sizeof(char));
}
int len = strlen(sep_stirng[i]);
@ -68,6 +79,7 @@ int join_string(char **joined, int arr_len, char *sep_stirng[], char *delim) { @@ -68,6 +79,7 @@ int join_string(char **joined, int arr_len, char *sep_stirng[], char *delim) {
return ER_FAILURE;
}
/* Remove all instances of char del from the given string (in place). */
int strip_char(char *string, char del) {
int len = strlen(string);
bool move = false;

2
util.h

@ -4,6 +4,8 @@ @@ -4,6 +4,8 @@
#ifndef UTILH
#define UTILH
void *dualloc(void *thing, size_t size);
int readline(FILE* in, char **out);
int split_string(char **sep_string[], int *num, char *string, char delim);

Loading…
Cancel
Save