#include <stdio.h>
#include <stdarg.h>
+#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#if defined(__FreeBSD__)
-#include <stdlib.h>
-#elif defined(_WIN32)
+#ifdef _WIN32
#include <malloc.h>
-#else
+#endif
+#ifdef HAVE_ALLOCA_H
#include <alloca.h>
#endif
#include "lc_parser_t.h"
#include "hashptr.h"
#include "lc_printf.h"
+#include "xmalloc.h"
#define ERR_STRING "In argument \"%s\": "
#define OPT_DELIM '-'
-#define HELP_TEMPL "%-15s %-10s %-45s"
-#define HELP_TEMPL_VALS HELP_TEMPL " [%s] (%s)"
+#define HELP_TEMPL "%-15s %-10s %-45s"
+#define HELP_TEMPL_VALS HELP_TEMPL " [%s] (%s)"
static struct obstack obst;
static lc_opt_err_info_t *set_error(lc_opt_err_info_t *err, int error, const char *arg)
{
- if(err) {
+ if (err) {
err->error = error;
err->msg = "";
err->arg = arg;
int res = 0;
va_start(args, fmt);
- if(err && lc_opt_is_error(err)) {
+ if (err && lc_opt_is_error(err)) {
res = 1;
- if(handler) {
+ if (handler) {
char buf[256];
vsnprintf(buf, sizeof(buf), fmt, args);
handler(buf, err);
const char *copied_desc;
obstack_grow0(&obst, name, strlen(name));
- copied_name = obstack_finish(&obst);
+ copied_name = (char*)obstack_finish(&obst);
obstack_grow0(&obst, desc, strlen(desc));
- copied_desc = obstack_finish(&obst);
+ copied_desc = (char*)obstack_finish(&obst);
memset(ent, 0, sizeof(*ent));
set_name(ent, copied_name);
INIT_LIST_HEAD(&ent->v.grp.opts);
set_error(err, lc_opt_err_none, "");
- if(ent->parent) {
- if(ent->parent->is_grp)
- list_add(&ent->list, &lc_get_grp_special(ent->parent)->grps);
+ if (ent->parent) {
+ if (ent->parent->is_grp)
+ list_add_tail(&ent->list, &lc_get_grp_special(ent->parent)->grps);
else
set_error(err, lc_opt_err_grp_expected, ent->parent->name);
}
ent->is_grp = 0;
set_error(err, lc_opt_err_none, "");
- list_add(&ent->list, &lc_get_grp_special(ent->parent)->opts);
+ list_add_tail(&ent->list, &lc_get_grp_special(ent->parent)->opts);
- s->type = type;
- s->value = val;
- s->cb = cb;
+ s->type = type;
+ s->value = val;
+ s->cb = cb;
s->dump = dump;
s->dump_vals = dump_vals;
- s->length = length;
+ s->length = length;
return ent;
}
static lc_opt_entry_t root_group;
static int inited = 0;
- if(!inited) {
+ if (!inited) {
obstack_init(&obst);
inited = 1;
const char *res;
#define XXX(t) case lc_opt_type_ ## t: res = #t; break
- switch(type) {
+ switch (type) {
XXX(enum);
XXX(bit);
XXX(int);
return get_type_name(lc_get_opt_special(ent)->type);
}
-
-lc_opt_entry_t *lc_opt_find_grp(const lc_opt_entry_t *grp, const char *name, lc_opt_err_info_t *err);
-lc_opt_entry_t *lc_opt_find_opt(const lc_opt_entry_t *grp, const char *name, lc_opt_err_info_t *err);
-
lc_opt_entry_t *lc_opt_get_grp(lc_opt_entry_t *parent, const char *name)
{
lc_opt_entry_t *ent = lc_opt_find_grp(parent, name, NULL);
- if(!ent) {
- ent = obstack_alloc(&obst, sizeof(*ent));
+ if (!ent) {
+ ent = OALLOC(&obst, lc_opt_entry_t);
init_entry(ent, parent, name, "");
init_grp(ent, NULL);
}
{
lc_opt_entry_t *res = NULL;
- if(parent->is_grp) {
+ if (parent->is_grp) {
lc_opt_entry_t *ent = lc_opt_find_opt(parent, name, NULL);
- if(!ent) {
- res = obstack_alloc(&obst, sizeof(*ent));
+ if (!ent) {
+ res = OALLOC(&obst, lc_opt_entry_t);
init_entry(res, parent, name, desc);
init_opt(res, type, value, length, cb, dump, dump_vals, err);
} else
int error = error_to_use;
unsigned hash = HASH_STR(name, strlen(name));
- if(!list_empty(head)) {
+ if (!list_empty(head)) {
list_for_each_entry(lc_opt_entry_t, ent, head, list) {
- if(entry_matches(ent, hash, name)) {
+ if (entry_matches(ent, hash, name)) {
error = lc_opt_err_none;
found = ent;
break;
{
lc_opt_entry_t *ent;
- if(pos == n)
+ if (pos == n)
return root;
ent = lc_opt_find_grp(root, names[pos], err);
lc_opt_entry_t *res = from;
size_t end = strcspn(path, path_delim);
- if(path[end] != '\0') {
+ if (path[end] != '\0') {
/* skip all delimiters */
size_t next = strspn(path + end, path_delim);
/* copy the part of the path into a buffer */
- char *buf = malloc((end+1) * sizeof(buf[0]));
+ char *buf = (char*)malloc((end+1) * sizeof(buf[0]));
strncpy(buf, path, end);
buf[end] = '\0';
res = resolve_up_to_last_str_rec(from, path + end + next, last_name);
}
- else if(last_name != NULL) {
+ else if (last_name != NULL) {
*last_name = path;
}
size_t next = strspn(path, path_delim);
/* if l != 0 we saw deliminators, so we resolve from the root */
- if(next > 0)
+ if (next > 0)
root = lc_opt_root_grp();
return resolve_up_to_last_str_rec(root, path + next, last_name);
static char *strtolower(char *buf, size_t n, const char *str)
{
unsigned i;
- for(i = 0; i < n; ++i)
+ for (i = 0; i < n; ++i)
buf[i] = tolower(str[i]);
return buf;
}
va_start(args, length);
- if(data) {
+ if (data) {
res = 1;
- switch(type) {
+ switch (type) {
case lc_opt_type_bit:
integer = va_arg(args, int);
- if(integer)
+ if (integer)
*((int *) data) |= length;
else
*((int *) data) &= ~length;
case lc_opt_type_negbit:
integer = va_arg(args, int);
- if(integer)
+ if (integer)
*((int *) data) &= ~length;
else
*((int *) data) |= length;
break;
case lc_opt_type_string:
- strncpy(data, va_arg(args, const char *), length);
+ strncpy((char*)data, va_arg(args, const char *), length);
break;
case lc_opt_type_int:
{
int res;
- if(data) {
- switch(type) {
+ if (data) {
+ switch (type) {
case lc_opt_type_bit:
case lc_opt_type_negbit:
- res = snprintf(buf, n, "%x", *((int *) data));
+ res = snprintf(buf, n, "%x", *((unsigned *) data));
break;
case lc_opt_type_boolean:
case lc_opt_type_negboolean:
res = snprintf(buf, n, "%s", *((int *) data) ? "true" : "false");
break;
case lc_opt_type_string:
- strncpy(buf, data, n);
+ strncpy(buf, (const char*)data, n);
res = n;
break;
case lc_opt_type_int:
double dbl;
} val_storage, *val = &val_storage;
- if(!opt) {
+ if (!opt) {
set_error(err, lc_opt_err_opt_not_found, "");
return 0;
}
- if(!s->cb) {
+ if (!s->cb) {
set_error(err, lc_opt_err_no_callback, "");
return 0;
}
s->is_set = 1;
- switch(s->type) {
+ switch (s->type) {
case lc_opt_type_int:
- if(sscanf(value, "%i", (int *) val)) {
+ if (sscanf(value, "%i", (int *) val)) {
error = lc_opt_err_unknown_value;
if (s->cb(opt->name, s->type, s->value, s->length, val->integer))
error = lc_opt_err_none;
break;
case lc_opt_type_double:
- if(sscanf(value, "%lf", (double *) val)) {
+ if (sscanf(value, "%lf", (double *) val)) {
error = lc_opt_err_unknown_value;
if (s->cb(opt->name, s->type, s->value, s->length, val->dbl))
error = lc_opt_err_none;
case lc_opt_type_bit:
case lc_opt_type_negbit:
strtolower(buf, sizeof(buf), value);
- for(i = 0; i < LC_ARRSIZE(bool_strings); ++i) {
- if(strcmp(buf, bool_strings[i].str) == 0) {
+ for (i = 0; i < LC_ARRSIZE(bool_strings); ++i) {
+ if (strcmp(buf, bool_strings[i].str) == 0) {
val->integer = bool_strings[i].val;
error = lc_opt_err_none;
break;
if (s->cb(opt->name, s->type, s->value, s->length, value))
error = lc_opt_err_none;
break;
+ case lc_opt_type_invalid:
+ abort();
}
set_error(err, error, value);
char *lc_opt_value_to_string(char *buf, size_t len, const lc_opt_entry_t *ent)
{
const lc_opt_special_t *s = lc_get_opt_special(ent);
- if(s->dump)
+ if (s->dump)
s->dump(buf, len, ent->name, s->type, s->value, s->length);
else
strncpy(buf, "<n/a>", len);
return buf;
}
-char *lc_opt_values_to_string(char *buf, size_t len, const lc_opt_entry_t *ent)
+static char *lc_opt_values_to_string(char *buf, size_t len, const lc_opt_entry_t *ent)
{
const lc_opt_special_t *s = lc_get_opt_special(ent);
- if(s->dump_vals)
+ if (s->dump_vals)
s->dump_vals(buf, len, ent->name, s->type, s->value, s->length);
return buf;
}
-static lc_opt_entry_t *resolve_up_to_last_str(lc_opt_entry_t *root, const char *path, const char **last_name);
-
int lc_opt_add_table(lc_opt_entry_t *root, const lc_opt_table_entry_t *table)
{
int i, res = 0;
lc_opt_err_info_t err;
- for(i = 0; table[i].name != NULL; ++i) {
+ for (i = 0; table[i].name != NULL; ++i) {
const char *name;
const lc_opt_table_entry_t *tab = &table[i];
lc_opt_entry_t *grp = resolve_up_to_last_str(root, tab->name, &name);
lc_opt_add_opt(grp, name, tab->desc, tab->type, tab->value, tab->len, tab->cb, tab->dump, tab->dump_vals, &err);
- if(err.error != lc_opt_err_none)
+ if (err.error != lc_opt_err_none)
res = 1;
}
}
}
- strncat(buf, ent->name, len);
+ strncat(buf, ent->name, len-1);
}
static char *lc_opt_print_grp_path(char *buf, size_t len, const lc_opt_entry_t *ent, char separator, lc_opt_entry_t *stop_ent)
char values[512];
lc_opt_entry_t *e;
- if(!list_empty(&s->opts)) {
+ if (!list_empty(&s->opts)) {
lc_opt_print_grp_path(grp_name, sizeof(grp_name), ent, separator, stop_ent);
fputc('\n', f);
if (grp_name[0])
static void indent(FILE *f, int n)
{
int i;
- for(i = 0; i < n; ++i)
+ for (i = 0; i < n; ++i)
fputc(' ', f);
}
{
lc_grp_special_t *s;
- if(ent->is_grp) {
+ if (ent->is_grp) {
lc_opt_entry_t *e;
s = lc_get_grp_special(ent);
lc_opt_print_tree_grp_indent(ent, f, 0);
}
+static int lc_opts_default_error_handler(const char *prefix, const lc_opt_err_info_t *err)
+{
+ fprintf(stderr, "%s: %s; %s\n", prefix, err->msg, err->arg);
+ return 0;
+}
void lc_opt_from_file(const char *filename, FILE *f, lc_opt_error_handler_t *handler)
{
+ if (handler == NULL)
+ handler = lc_opts_default_error_handler;
PMANGLE(in) = f;
lc_opt_init_parser(filename, handler);
PMANGLE(parse)();
int ret = 0;
lc_opt_err_info_t err;
- char *end, *buf, *eqsign;
+ const char *end, *eqsign;
- if(n >= n_prefix && strncmp(opt_prefix, arg, n_prefix) == 0) {
+ if (n >= n_prefix && strncmp(opt_prefix, arg, n_prefix) == 0) {
arg = arg + n_prefix;
/*
* This means, that we want to read options
* from a file.
*/
- if(arg[0] == '@') {
- size_t n = strcspn(&arg[1], " \t\n");
- char *fname = alloca(n + 1);
+ if (arg[0] == '@') {
+ size_t n = strcspn(&arg[1], " \t\n");
+ char *fname = (char*)alloca(n + 1);
FILE *f;
strncpy(fname, &arg[1], n);
- if((f = fopen(fname, "rt")) != NULL) {
+ if ((f = fopen(fname, "rt")) != NULL) {
lc_opt_from_file(fname, f, handler);
fclose(f);
set_error(&err, lc_opt_err_none, NULL);
eqsign = strchr(arg, '=');
if (eqsign && eqsign < end)
end = NULL;
- while(end != NULL) {
+ while (end != NULL) {
/*
* Copy the part of the option into the buffer and add the
* finalizing zero.
*/
- buf = obstack_copy0(&obst, arg, end - arg);
+ char *buf = (char*)obstack_copy0(&obst, arg, end - arg);
/* Resolve the group inside the group */
grp = lc_opt_find_grp(grp, buf, &err);
error = lc_opt_raise_error(&err, handler, ERR_STRING, arg);
- if(error)
+ if (error)
break;
/* Find the next option part delimiter. */
obstack_free(&obst, buf);
}
- if(!error) {
+ if (!error) {
lc_opt_entry_t *opt;
+ char *buf;
/*
* Now, we are at the last option part:
* later.
*/
end = strchr(arg, '=');
- buf = obstack_copy0(&obst, arg, end ? end - arg : (int) strlen(arg));
+ buf = (char*)obstack_copy0(&obst, arg, end ? end - arg : (int) strlen(arg));
opt = lc_opt_find_opt(grp, buf, &err);
error = lc_opt_raise_error(&err, handler, ERR_STRING, arg);
- if(!error) {
+ if (!error) {
/*
* Now evaluate the parameter of the option (the part after
* the =) if it was given.
int i;
int options_set = 0;
- for(i = 0; i < argc; ++i) {
+ if (handler == NULL)
+ handler = lc_opts_default_error_handler;
+
+ for (i = 0; i < argc; ++i) {
options_set |= lc_opt_from_single_arg(root, opt_prefix, argv[i], handler);
}
{
char buf[256];
- lc_opt_entry_t *opt = arg->v_ptr;
- const char *s = buf;
- size_t res = 0;
+ lc_opt_entry_t *opt = (lc_opt_entry_t*)arg->v_ptr;
+ const char *s = buf;
+ size_t res = 0;
- switch(occ->conversion) {
+ switch (occ->conversion) {
case 'V':
lc_opt_value_to_string(buf, sizeof(buf), opt);
break;
s = NULL;
}
- if(s)
+ if (s)
res = lc_appendable_snadd(app, s, strlen(s));
return res;
{
static lc_arg_env_t *env = NULL;
- if(!env) {
+ if (!env) {
env = lc_arg_new_env();
lc_arg_register(env, "opt:value", 'V', &lc_opt_arg_handler);
return env;
}
-static int lc_opts_default_error_handler(const char *prefix, const lc_opt_err_info_t *err)
-{
- fprintf(stderr, "%s: %s; %s\n", prefix, err->msg, err->arg);
- return 0;
-}
-
-void lc_opts_init(const char *ini_name, lc_opt_entry_t *root, const char *arg_prefix, int argc, const char **argv)
+void lc_opt_default_configs(const char *ini_name)
{
FILE *f;
char path[MAX_PATH];
/* <cmnt>.ini */
strncpy(local_ini_file, ini_name, sizeof(local_ini_file));
- strncat(local_ini_file, ".ini", sizeof(local_ini_file));
+ strncat(local_ini_file, ".ini", sizeof(local_ini_file)-1);
local_ini_file[sizeof(local_ini_file) - 1] = '\0';
path[0] = '\0';
#if _MSC_VER > 1200
/* ARG: need newer SDK to compile this */
SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, 0, path);
- strncat(path, "\\", sizeof(path));
+ strncat(path, "\\", sizeof(path)-1);
#endif
strncpy(home_dir_ini_file, local_ini_file, sizeof(home_dir_ini_file));
home_dir_ini_file[sizeof(home_dir_ini_file) - 1] = '\0';
struct passwd *entry = getpwuid(getuid());
if (entry != NULL) {
strcpy(path, entry->pw_dir);
- strncat(path, "/", sizeof(path));
+ strncat(path, "/", sizeof(path)-1);
/* .<cmnt>rc */
snprintf(home_dir_ini_file, sizeof(home_dir_ini_file), ".%src", ini_name);
home_dir_ini_file[sizeof(home_dir_ini_file) - 1] = '\0';
} else {
- /* FIXME: some error occured */
+ /* FIXME: some error occurred */
home_dir_ini_file[0] = '\0';
}
}
#endif
- strncat(path, home_dir_ini_file, sizeof(path));
+ strncat(path, home_dir_ini_file, sizeof(path)-1);
path[sizeof(path) - 1] = '\0';
/* Process ini file in user's home. */
lc_opt_from_file(local_ini_file, f, lc_opts_default_error_handler);
fclose(f);
}
-
- /* process arguments from the command line */
- lc_opt_from_argv(root, arg_prefix, argc, argv, lc_opts_default_error_handler);
}