#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int (*cmd_func)(int argc, char* argv[]);
typedef struct {
char* name;
int parc;
char** parv;
int argc;
char** argv;
cmd_func func;
} cmd_desc;
bool exfree(void* p)
{
if (p != NULL) {
free(p);
return true;
}
return false;
}
void clear_cmd_desc(cmd_desc* to_clear)
{
int i;
exfree(to_clear->name);
for (i = 0; i < to_clear->parc; i++)
{
exfree(to_clear->parv[i]);
}
for (i = 0; i < to_clear->argc; i++)
{
exfree(to_clear->argv[i]);
}
memset(to_clear, 0, sizeof(cmd_desc));
}
cmd_desc* create_cmd_desc(const char* name, int parc, const char** parv, cmd_func func)
{
cmd_desc* ptr = NULL;
if (parc < 0)
{
return NULL;
}
ptr = (cmd_desc*)calloc(1, sizeof(cmd_desc));
if (ptr == NULL)
{
return NULL;
}
ptr->name = (char*)malloc(strlen(name) + 1);
strcpy(ptr->name, name);
int i;
if (parc > 0)
{
ptr->parc = parc;
ptr->parv = (char**)malloc(sizeof(char*)*parc);
for (i = 0; i < parc; i++)
{
ptr->parv[i] = (char*)malloc(strlen(parv[i]) + 1);
strcpy(ptr->parv[i], parv[i]);
}
}
ptr->func = func;
return ptr;
}
bool push_input(cmd_desc* d, const char* input)
{
char** tmp = NULL;
tmp = (char**)realloc(d->argv, sizeof(char*) * (d->argc + 1));
if (tmp == NULL)
{
return false;
}
else
{
d->argv = tmp;
}
d->argv[d->argc] = (char*)malloc(strlen(input) + 1);
strcpy(d->argv[d->argc], input);
d->argc++;
return true;
}
void clear_input(cmd_desc* d)
{
int i;
for (i = 0; i < d->argc; i++)
{
exfree(d->argv[i]);
}
exfree(d->argv);
d->argv = NULL;
d->argc = 0;
}
bool add_cmd_desc(cmd_desc** arr, size_t* index, size_t* arrsize, cmd_desc* desc)
{
cmd_desc* tmp = NULL;
if (*index >= *arrsize)
{
tmp = (cmd_desc*)realloc(*arr, sizeof(cmd_desc) * *arrsize * 2);
if (tmp == NULL)
{
return false;
}
else
{
*arrsize *= 2;
*arr = tmp;
}
}
(*arr)[(*index)++] = *desc;
free(desc);
return true;
}
int adder(int argc, char* argv[])
{
if (argc <= 0)
{
printf("Invalid parameters\n");
return 0;
}
int sum = 0;
int i;
for (i = 0; i < argc; i++)
{
sum += atoi(argv[i]);
}
printf("Sum is %d, Average is %d and median is %d\n", sum, sum / argc, atoi(argv[argc / 2]));
return sum;
}
int main(int argc, char* argv[])
{
cmd_desc* cmd_desc_arr = NULL;
size_t arr_ind = 0;
size_t arr_size = 4;
char* buf = NULL;
char* bufbase = NULL;
cmd_desc_arr = (cmd_desc*)calloc(arr_size, sizeof(cmd_desc));
if (cmd_desc_arr == NULL)
{
return -1;
}
size_t bufstep = 256;
size_t bufsize = 256;
buf = (char*)calloc(bufsize, sizeof(char));
bufbase = buf;
if (buf == NULL)
{
free(cmd_desc_arr);
return -1;
}
cmd_desc* d = create_cmd_desc("adder", 0, NULL, &adder);
if (d == NULL)
{
printf("Something really bad happened. And the programmer was too lazy to clean up... Take cover.\n");
}
add_cmd_desc(&cmd_desc_arr, &arr_ind, &arr_size, d);
printf("This is a little command line interface (cli) demo.\nEnter 'quit' to quit.\n");
size_t i = 0;
char* tmp = NULL;
int diff;
while (scanf("%255s", bufbase) > 0)
{
if (strcmp(bufbase, "quit") == 0)
{
break;
}
for (; i < arr_ind; i++)
{
cmd_desc* d = &cmd_desc_arr[i];
if (d->name == NULL)
{
continue;
}
if (strcmp(d->name, buf) == 0)
{
while (scanf("%255s", buf) > 0)
{
if (buf[0] == '<') break;
if (buf[bufstep-2] != 0)
{
buf += bufstep-1;
}
if (bufbase[bufsize - 2] != 0) {
tmp = (char*)realloc(bufbase, bufsize * 2);
if (tmp == NULL)
{
printf("Failed to realloc.\n");
goto end;
}
diff = (buf - bufbase);
bufbase = tmp;
buf = buf + diff;
bufsize *= 2;
bufbase[bufsize - 2] = 0;
bufbase[bufsize - 1] = 0;
}
push_input(d, bufbase);
}
d->func(d->argc, d->argv);
clear_input(d);
break;
}
}
printf("Ladies and gentlemen, next round, your input please...\n");
}
end:
free(bufbase);
for (; i < arr_size; i++)
{
clear_cmd_desc(&cmd_desc_arr[i]);
}
exfree(cmd_desc_arr);
getchar();
return 0;
}