#include <string.h>
#include <stdlib.h>
static int cmdc;
static char **cmdv;
static int cmdv_max;
static int reserve_cmdv(int cmdc)
{
int cmd_max = cmdv_max;
char **tmp;
if (cmdc < cmd_max)
return 0;
do
cmd_max += 10;
while (cmdc >= cmd_max);
tmp = realloc(cmdv, cmd_max * sizeof(*tmp));
if (!tmp)
return -1;
cmdv = tmp;
cmdv_max = cmd_max;
return 0;
}
static int split_cmd(char *cmd)
{
char *out = cmd;
int arg;
cmdc = 0;
for (;;) {
char ch;
arg = 0;
while (*cmd == ' ')
++cmd;
next_char:
ch = *cmd++;
if (ch == '"' || ch == '\'') {
char end = ch;
if (!arg) {
if (reserve_cmdv(cmdc + 1))
return -1;
cmdv[cmdc++] = out;
arg = 1;
}
while (*cmd && *cmd != end)
*out++ = *cmd++;
if (!*cmd++)
return -1;
goto next_char;
}
if (ch && ch != ' ') {
if (!arg) {
if (reserve_cmdv(cmdc + 1))
return -1;
cmdv[cmdc++] = out;
arg = 1;
}
*out++ = ch;
goto next_char;
}
*out++ = 0;
if (!ch)
break;
}
return cmdc;
}
static char *input_cmd(void)
{
int ch;
char *cmd = malloc(128);
int len = 128;
int pos = 0;
if (!cmd)
return NULL;
for (;;) {
ch = fgetc(stdin);
if (ch < 0)
break;
switch (ch) {
case '\r':
case '\n':
ch = 0;
default:
if (pos == len) {
char *tmp = realloc(cmd, len * 2);
if (!tmp)
goto cleanup;
cmd = tmp;
len *= 2;
}
cmd[pos++] = ch;
if (!ch)
return cmd;
}
}
cleanup:
free(cmd);
return NULL;
}
static const char *help(int argc, char *argv[])
{
return "Available commands:\n"
"\n"
"help\n"
"set <option> <value> ...\n"
"subset <section> <option> <value>\n"
"create <section>\n"
"destroy <section>\n"
"dump [mod|modified]\n"
"quit\n"
"\n"
"<option> is one of 'bool', 'int' 'string' and 'float'.\n";
}
static const char *set(int argc, char *argv[])
{
if (argc < 3)
return "Need more args\n";
if (!cfg_getopt(cfg, argv[1]))
return "Unknown option\n";
if (cfg_setmulti(cfg, argv[1], argc - 2, &argv[2]))
return "Failure\n";
return "OK\n";
}
static const char *subset(int argc, char *argv[])
{
if (argc < 4)
return "Need more args\n";
if (argc > 4)
return "Too many args\n";
sub = cfg_gettsec(cfg, "sub", argv[1]);
if (!sub)
return "No such section\n";
if (!cfg_getopt(sub, argv[2]))
return "Unknown option\n";
if (cfg_setmulti(sub, argv[2], argc - 3, &argv[3]))
return "Failure\n";
return "OK\n";
}
static const char *create(int argc, char *argv[])
{
if (argc != 2)
return "Need one arg\n";
if (cfg_gettsec(cfg, "sub", argv[1]))
return "Section exists already\n";
opt = cfg_getopt(cfg, "sub");
if (!opt || !cfg_setopt(cfg, opt, argv[1]))
return "Failure\n";
return "OK\n";
}
static const char *destroy(int argc, char *argv[])
{
if (argc < 2)
return "Need one arg\n";
if (!cfg_gettsec(cfg, "sub", argv[1]))
return "No such section\n";
cfg_rmtsec(cfg, "sub", argv[1]);
return "OK\n";
}
{
int i;
return 0;
sec = cfg_opt_getnsec(opt, 0);
if (!sec)
return 1;
if (!print_modified(sec, &sec->
opts[i]))
return 0;
}
return 1;
}
static const char *dump(int argc, char *argv[])
{
if (argc > 2)
return "Too many args\n";
if (argc == 2) {
if (!strcmp(argv[1], "mod") || !strcmp(argv[1], "modified"))
cfg_set_print_filter_func(cfg, print_modified);
else
return "Invalid arg\n";
}
else
cfg_set_print_filter_func(cfg, NULL);
cfg_print(cfg, stdout);
return "";
}
static const char *quit(int argc, char *argv[])
{
return NULL;
}
struct cmd_handler {
const char *cmd;
const char *(*handler)(int argc, char *argv[]);
};
static const struct cmd_handler cmds[] = {
{ "help", help },
{ "set", set },
{ "subset", subset },
{ "create", create },
{ "destroy", destroy },
{ "dump", dump },
{ "quit", quit },
{ "exit", quit },
{ NULL, NULL }
};
int main(void)
{
};
};
char *cmd = NULL;
const char *reply;
int res;
int i;
for (;;) {
printf("cli> ");
fflush(stdout);
if (cmd)
free(cmd);
cmd = input_cmd();
if (!cmd)
exit(0);
res = split_cmd(cmd);
if (res < 0) {
printf("Parse error\n");
continue;
}
if (cmdc == 0)
continue;
for (i = 0; cmds[i].cmd; ++i) {
if (strcmp(cmdv[0], cmds[i].cmd))
continue;
reply = cmds[i].handler(cmdc, cmdv);
if (!reply)
exit(0);
printf("%s", reply);
break;
}
if (!cmds[i].cmd)
printf("Unknown command\n");
}
cfg_free(cfg);
return 0;
}
A configuration file parser library.
#define CFG_FLOAT_LIST(name, def, flags)
Initialize a floating point list option.
Definition confuse.h:713
#define CFGF_NO_TITLE_DUPES
multiple section titles must be unique (duplicates raises an error, only applies to sections)
Definition confuse.h:88
#define CFG_SEC(_name, _opts, _flags)
Initialize a section.
Definition confuse.h:790
#define CFG_BOOL(name, def, flags)
Initialize a boolean option.
Definition confuse.h:753
#define CFGF_TITLE
option has a title (only applies to sections)
Definition confuse.h:86
#define CFGF_NONE
Flags.
Definition confuse.h:82
#define CFG_END()
Terminate list of options.
Definition confuse.h:858
#define CFG_INT_LIST(name, def, flags)
Initialize an integer list option.
Definition confuse.h:478
#define CFGF_MODIFIED
option has been changed from its default value
Definition confuse.h:97
#define CFGF_MULTI
option may be specified multiple times (only applies to sections)
Definition confuse.h:83
#define CFG_STR(name, def, flags)
Initialize a string option.
Definition confuse.h:367
#define CFG_FLOAT(name, def, flags)
Initialize a floating point option.
Definition confuse.h:708
@ CFGT_SEC
section
Definition confuse.h:65
#define CFG_INT(name, def, flags)
Initialize an integer option.
Definition confuse.h:473
#define CFG_BOOL_LIST(name, def, flags)
Initialize a boolean list option.
Definition confuse.h:758
#define CFG_STR_LIST(name, def, flags)
Initialize a string list option.
Definition confuse.h:381
Data structure holding information about an option.
Definition confuse.h:324
const char * name
The name of the option.
Definition confuse.h:325
cfg_type_t type
Type of option.
Definition confuse.h:327
cfg_flag_t flags
Flags.
Definition confuse.h:330
Data structure holding information about a "section".
Definition confuse.h:250
cfg_opt_t * opts
Array of options.
Definition confuse.h:256