diff options
-rw-r--r-- | ChangeLog | 34 | ||||
-rw-r--r-- | src/datconv.c | 9 | ||||
-rw-r--r-- | src/gdbmload.c | 9 | ||||
-rw-r--r-- | src/gdbmtool.c | 255 | ||||
-rw-r--r-- | src/gdbmtool.h | 12 | ||||
-rw-r--r-- | src/gram.y | 16 | ||||
-rw-r--r-- | src/lex.l | 5 | ||||
-rw-r--r-- | src/var.c | 199 |
8 files changed, 430 insertions, 109 deletions
@@ -1,5 +1,39 @@ 2013-05-14 Sergey Poznyakoff <gray@gnu.org.ua> + Provide "open" and "close" commands; implement new variables. + + * src/datconv.c (datum_format): Don't print field delimiter + after the last field. + (dsprint): Bugfix. + * src/gdbmload.c (gdbm_load_from_file): Return GDBM_NO_DBNAME + when loading from bdb dump and the database pointer is NULL. + * src/gdbmtool.c (opendb, checkdb): New auxiliary functions. + (begin handlers): call checkdb. + (import_handler): Special handling for GDBM_NO_DBNAME. + (status_handler): Print more info. + (command_tab): Call checkdb prior to handlers that expect an + open database. + New commands: open, close + (gdbmarg_string, gdbmarg_datum) + (gdbmarg_kvpair): Take pointer to locus as the 2nd argument. + All uses changed. + (coerce): Include locus info in the diagnostic message. + (main): Don't open database right away. + * src/gdbmtool.h (GDBMTOOL_DEFFILE): New define. + (gdbmarg) <loc>: New member. + (VART_INT): New variable typ.e + (VAR_ERR_FAILURE): New error code. + (variable_is_set, varible_mode_name): New protos. + * src/gram.y: Provide printable token names for error messages. + Pass locus to gdbmarg initialization functions. + * src/lex.l (vparse_error): Fix output. + * src/var.c (variable) <v.num, hook, hook_data>: New members. + (vartab): Define more variables. + (variable_set): Accept value of any valid datatype. + (variable_mode_name, variable_is_set): New functions. + +2013-05-14 Sergey Poznyakoff <gray@gnu.org.ua> + Cleanup. * src/datconv.c (s_float): Use strtod. diff --git a/src/datconv.c b/src/datconv.c index cf17011..0178f41 100644 --- a/src/datconv.c +++ b/src/datconv.c @@ -211,7 +211,8 @@ datum_format (FILE *fp, datum const *dat, struct dsegm *ds) { int off = 0; char *delim[2]; - + int first_field = 1; + if (!ds) { fprintf (fp, "%.*s\n", dat->dsize, dat->dptr); @@ -228,6 +229,8 @@ datum_format (FILE *fp, datum const *dat, struct dsegm *ds) switch (ds->type) { case FDEF_FLD: + if (!first_field) + fwrite (delim[1], strlen (delim[1]), 1, fp); if (ds->v.field.name) fprintf (fp, "%s=", ds->v.field.name); if (ds->v.field.dim > 1) @@ -259,7 +262,7 @@ datum_format (FILE *fp, datum const *dat, struct dsegm *ds) } if (ds->v.field.dim > 1) fprintf (fp, " }"); - fwrite (delim[1], strlen (delim[1]), 1, fp); + first_field = 0; break; case FDEF_OFF: @@ -403,7 +406,7 @@ dsprint (FILE *fp, int what, struct dsegm *ds) case FDEF_FLD: fprintf (fp, "\t%s", ds->v.field.type->name); if (ds->v.field.name) - fprintf (fp, " %s", ds->v.field.type->name); + fprintf (fp, " %s", ds->v.field.name); if (ds->v.field.dim > 1) fprintf (fp, "[%d]", ds->v.field.dim); fprintf (fp, ",\n"); diff --git a/src/gdbmload.c b/src/gdbmload.c index 4a0c2de..7c5fb01 100644 --- a/src/gdbmload.c +++ b/src/gdbmload.c @@ -593,7 +593,14 @@ gdbm_load_from_file (GDBM_FILE *pdbf, FILE *fp, int replace, df.fp = fp; if (rc == 'V') - rc = gdbm_load_bdb_dump (&df, *pdbf, replace); + { + if (!*pdbf) + { + gdbm_errno = GDBM_NO_DBNAME; + return -1; + } + rc = gdbm_load_bdb_dump (&df, *pdbf, replace); + } else rc = _gdbm_load_file (&df, *pdbf, pdbf, replace, meta_mask); dump_file_free (&df); diff --git a/src/gdbmtool.c b/src/gdbmtool.c index b9d771b..20c60d8 100644 --- a/src/gdbmtool.c +++ b/src/gdbmtool.c @@ -106,7 +106,70 @@ tildexpand (char *s) } return estrdup (s); } - + +static int +opendb (char *dbname) +{ + int cache_size; + int block_size; + int flags = 0; + GDBM_FILE db; + + if (variable_get ("cachesize", VART_INT, (void**) &cache_size)) + abort (); + if (variable_get ("blocksize", VART_INT, (void**) &block_size)) + abort (); + + if (!variable_is_set ("lock")) + flags |= GDBM_NOLOCK; + if (!variable_is_set ("mmap")) + flags |= GDBM_NOMMAP; + if (variable_is_set ("sync")) + flags |= GDBM_SYNC; + + if (variable_is_set ("readonly")) + flags = GDBM_READER; + else if (variable_is_set ("newdb")) + flags |= GDBM_NEWDB; + else + flags |= GDBM_WRCREAT; + + db = gdbm_open (dbname, block_size, flags, 00664, NULL); + + if (db == NULL) + { + syntax_error (_("cannot open database %s: %s"), dbname, + gdbm_strerror (gdbm_errno)); + return 1; + } + + if (gdbm_setopt (db, GDBM_CACHESIZE, &cache_size, sizeof (int)) == + -1) + syntax_error (_("gdbm_setopt failed: %s"), + gdbm_strerror (gdbm_errno)); + + if (gdbm_file) + gdbm_close (gdbm_file); + + gdbm_file = db; + return 0; +} + +static int +checkdb () +{ + if (!gdbm_file) + { + if (!file_name) + { + file_name = estrdup (GDBMTOOL_DEFFILE); + syntax_error (_("warning: using default database file %s"), + file_name); + } + return opendb (file_name); + } + return 0; +} size_t bucket_print_lines (hash_bucket *bucket) @@ -336,6 +399,26 @@ struct handler_param }; +void +open_handler (struct handler_param *param) +{ + if (opendb (param->argv[0]->v.string) == 0) + { + free (file_name); + file_name = estrdup (param->argv[0]->v.string); + } +} + +void +close_handler (struct handler_param *param) +{ + if (!gdbm_file) + syntax_error (_("nothing to close")); + gdbm_close (gdbm_file); + gdbm_file = NULL; +} + + /* c - count */ void count_handler (struct handler_param *param) @@ -453,7 +536,9 @@ reorganize_handler (struct handler_param *param ARG_UNUSED) /* A - print available list */ int avail_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count) -{ +{ + if (checkdb ()) + return 1; if (exp_count) *exp_count = _gdbm_avail_list_size (gdbm_file, SIZE_T_MAX); return 0; @@ -470,6 +555,9 @@ int print_current_bucket_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count) { + if (checkdb ()) + return 1; + if (exp_count) *exp_count = bucket_print_lines (gdbm_file->bucket) + 3; return 0; @@ -515,6 +603,9 @@ print_bucket_begin (struct handler_param *param, size_t *exp_count) { int temp; + if (checkdb ()) + return 1; + if (getnum (&temp, param->argv[0]->v.string, NULL)) return 1; @@ -534,6 +625,8 @@ print_bucket_begin (struct handler_param *param, size_t *exp_count) int print_dir_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count) { + if (checkdb ()) + return 1; if (exp_count) *exp_count = gdbm_file->header->dir_size / 4 + 3; return 0; @@ -557,6 +650,8 @@ print_dir_handler (struct handler_param *param) int print_header_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count) { + if (checkdb ()) + return 1; if (exp_count) *exp_count = 14; return 0; @@ -596,6 +691,8 @@ hash_handler (struct handler_param *param) int print_cache_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count) { + if (checkdb ()) + return 1; if (exp_count) *exp_count = gdbm_file->bucket_cache ? gdbm_file->cache_size + 1 : 1; return 0; @@ -618,6 +715,8 @@ print_version_handler (struct handler_param *param) int list_begin (struct handler_param *param ARG_UNUSED, size_t *exp_count) { + if (checkdb ()) + return 1; if (exp_count) *exp_count = get_record_count (); return 0; @@ -698,6 +797,7 @@ import_handler (struct handler_param *param) unsigned long err_line; int meta_mask = 0; int i; + int rc; for (i = 1; i < param->argc; i++) { @@ -713,8 +813,25 @@ import_handler (struct handler_param *param) } } - if (gdbm_load (&gdbm_file, param->argv[0]->v.string, flag, - meta_mask, &err_line)) + rc = gdbm_load (&gdbm_file, param->argv[0]->v.string, flag, + meta_mask, &err_line); + if (rc && gdbm_errno == GDBM_NO_DBNAME) + { + const char *varname = variable_mode_name (); + int t = 1; + + variable_set ("newdb", VART_BOOL, &t); + rc = checkdb (); + if (varname) + variable_set (varname, VART_BOOL, &t); + + if (rc) + return; + + rc = gdbm_load (&gdbm_file, param->argv[0]->v.string, flag, + meta_mask, &err_line); + } + if (rc) { switch (gdbm_errno) { @@ -732,14 +849,26 @@ import_handler (struct handler_param *param) terror (0, _("cannot load from %s: %s"), param->argv[0], gdbm_strerror (gdbm_errno)); } + return; } + + free (file_name); + if (gdbm_setopt (gdbm_file, GDBM_GETDBNAME, &file_name, sizeof (file_name))) + syntax_error (_("gdbm_setopt failed: %s"), gdbm_strerror (gdbm_errno)); } /* S - print current program status */ void status_handler (struct handler_param *param) { - fprintf (param->fp, _("Database file: %s\n"), file_name); + if (file_name) + fprintf (param->fp, _("Database file: %s\n"), file_name); + else + fprintf (param->fp, "%s\n", _("No database name")); + if (gdbm_file) + fprintf (param->fp, "%s\n", _("Database is open")); + else + fprintf (param->fp, "%s\n", _("Database is not open")); dsprint (param->fp, DS_KEY, dsdef[DS_KEY]); dsprint (param->fp, DS_CONTENT, dsdef[DS_CONTENT]); } @@ -780,20 +909,20 @@ struct command struct command command_tab[] = { #define S(s) #s, sizeof (#s) - 1 { S(count), T_CMD, - NULL, count_handler, NULL, + checkdb, count_handler, NULL, { { NULL } }, N_("count (number of entries)") }, { S(delete), T_CMD, - NULL, delete_handler, NULL, + checkdb, delete_handler, NULL, { { N_("key"), ARG_DATUM, DS_KEY }, { NULL } }, N_("delete") }, { S(export), T_CMD, - NULL, export_handler, NULL, + checkdb, export_handler, NULL, { { N_("file"), ARG_STRING }, { "[truncate]", ARG_STRING }, { "[binary|ascii]", ARG_STRING }, { NULL } }, N_("export") }, { S(fetch), T_CMD, - NULL, fetch_handler, NULL, + checkdb, fetch_handler, NULL, { { N_("key"), ARG_DATUM, DS_KEY }, { NULL } }, N_("fetch") }, { S(import), T_CMD, NULL, import_handler, NULL, @@ -806,21 +935,21 @@ struct command command_tab[] = { list_begin, list_handler, NULL, { { NULL } }, N_("list") }, { S(next), T_CMD, - NULL, nextkey_handler, NULL, + checkdb, nextkey_handler, NULL, { { N_("[key]"), ARG_STRING }, { NULL } }, N_("nextkey") }, { S(store), T_CMD, - NULL, store_handler, NULL, + checkdb, store_handler, NULL, { { N_("key"), ARG_DATUM, DS_KEY }, { N_("data"), ARG_DATUM, DS_CONTENT }, { NULL } }, N_("store") }, { S(first), T_CMD, - NULL, firstkey_handler, NULL, + checkdb, firstkey_handler, NULL, { { NULL } }, N_("firstkey") }, { S(reorganize), T_CMD, - NULL, reorganize_handler, NULL, + checkdb, reorganize_handler, NULL, { { NULL } }, N_("reorganize") }, { S(avail), T_CMD, avail_begin, avail_handler, NULL, @@ -840,7 +969,7 @@ struct command command_tab[] = { print_header_begin , print_header_handler, NULL, { { NULL } }, N_("print file header") }, { S(hash), T_CMD, - NULL, hash_handler, NULL, + checkdb, hash_handler, NULL, { { N_("key"), ARG_DATUM, DS_KEY }, { NULL } }, N_("hash value of key") }, { S(cache), T_CMD, @@ -870,6 +999,13 @@ struct command command_tab[] = { NULL, source_handler, NULL, { { "file", ARG_STRING }, { NULL } }, N_("source command script") }, + { S(close), T_CMD, + NULL, close_handler, NULL, + { { NULL } }, N_("close the database") }, + { S(open), T_CMD, + NULL, open_handler, NULL, + { { "file", ARG_STRING }, { NULL } }, + N_("open new database") }, #undef S { 0 } }; @@ -996,34 +1132,40 @@ struct gdbm_option optab[] = { struct gdbmarg * -gdbmarg_string (char *string) +gdbmarg_string (char *string, struct locus *loc) { - struct gdbmarg *arg = emalloc (sizeof (*arg)); + struct gdbmarg *arg = ecalloc (1, sizeof (*arg)); arg->next = NULL; arg->type = ARG_STRING; arg->ref = 1; + if (loc) + arg->loc = *loc; arg->v.string = string; return arg; } struct gdbmarg * -gdbmarg_datum (datum *dat) +gdbmarg_datum (datum *dat, struct locus *loc) { - struct gdbmarg *arg = emalloc (sizeof (*arg)); + struct gdbmarg *arg = ecalloc (1, sizeof (*arg)); arg->next = NULL; arg->type = ARG_DATUM; arg->ref = 1; + if (loc) + arg->loc = *loc; arg->v.dat = *dat; return arg; } struct gdbmarg * -gdbmarg_kvpair (struct kvpair *kvp) +gdbmarg_kvpair (struct kvpair *kvp, struct locus *loc) { - struct gdbmarg *arg = emalloc (sizeof (*arg)); + struct gdbmarg *arg = ecalloc (1, sizeof (*arg)); arg->next = NULL; arg->type = ARG_KVPAIR; arg->ref = 1; + if (loc) + arg->loc = *loc; arg->v.kvpair = kvp; return arg; } @@ -1188,7 +1330,7 @@ coerce_k2d (struct gdbmarg *arg, struct argdef *def) if (datum_scan (&d, dsdef[def->ds], arg->v.kvpair)) return NULL; - return gdbmarg_datum (&d); + return gdbmarg_datum (&d, &arg->loc); } struct gdbmarg * @@ -1203,7 +1345,7 @@ coerce_s2d (struct gdbmarg *arg, struct argdef *def) if (datum_scan (&d, dsdef[def->ds], &kvp)) return NULL; - return gdbmarg_datum (&d); + return gdbmarg_datum (&d, &arg->loc); } #define coerce_fail NULL @@ -1222,8 +1364,7 @@ coerce (struct gdbmarg *arg, struct argdef *def) { if (!coerce_tab[def->type][arg->type]) { - //FIXME: locus - syntax_error (_("cannot coerce %s to %s"), + parse_error (&arg->loc, _("cannot coerce %s to %s"), argtypestr[arg->type], argtypestr[def->type]); return NULL; } @@ -1284,7 +1425,7 @@ run_command (struct command *cmd, struct gdbmarglist *arglist) sizeof (param.argv[0]) * argmax); } - t = gdbmarg_string (estrdup (argbuf)); + t = gdbmarg_string (estrdup (argbuf), &yylloc); if ((param.argv[i] = coerce (t, &cmd->args[i])) == NULL) { gdbmarg_free (t); @@ -1381,16 +1522,10 @@ source_rcfile () int main (int argc, char *argv[]) { - int intr; - - int cache_size = DEFAULT_CACHESIZE; - int block_size = 0; - + int intr; int opt; - char reader = FALSE; - char newdb = FALSE; - int flags = 0; - + int bv; + set_progname (argv[0]); #ifdef HAVE_SETLOCALE @@ -1407,40 +1542,36 @@ main (int argc, char *argv[]) switch (opt) { case 'l': - flags = flags | GDBM_NOLOCK; + bv = 0; + variable_set ("lock", VART_BOOL, &bv); break; case 'm': - flags = flags | GDBM_NOMMAP; + bv = 0; + variable_set ("mmap", VART_BOOL, &bv); break; case 's': - if (reader) - terror (EXIT_USAGE, _("-s is incompatible with -r")); - - flags = flags | GDBM_SYNC; + bv = 1; + variable_set ("sync", VART_BOOL, &bv); break; case 'r': - if (newdb) - terror (EXIT_USAGE, _("-r is incompatible with -n")); - - reader = TRUE; + bv = 1; + variable_set ("readonly", VART_BOOL, &bv); break; case 'n': - if (reader) - terror (EXIT_USAGE, _("-n is incompatible with -r")); - - newdb = TRUE; + bv = 1; + variable_set ("newdb", VART_BOOL, &bv); break; case 'c': - cache_size = atoi (optarg); + variable_set ("cachesize", VART_STRING, optarg); break; case 'b': - block_size = atoi (optarg); + variable_set ("blocksize", VART_STRING, optarg); break; case 'g': @@ -1463,36 +1594,12 @@ main (int argc, char *argv[]) terror (EXIT_USAGE, _("too many arguments")); if (argc == 1) file_name = argv[0]; - else - file_name = "junk.gdbm"; /* Initialize variables. */ intr = isatty (0); dsdef[DS_KEY] = dsegm_new_field (datadef_lookup ("string"), NULL, 1); dsdef[DS_CONTENT] = dsegm_new_field (datadef_lookup ("string"), NULL, 1); - if (reader) - { - gdbm_file = gdbm_open (file_name, block_size, GDBM_READER, 00664, NULL); - } - else if (newdb) - { - gdbm_file = - gdbm_open (file_name, block_size, GDBM_NEWDB | flags, 00664, NULL); - } - else - { - gdbm_file = - gdbm_open (file_name, block_size, GDBM_WRCREAT | flags, 00664, NULL); - } - if (gdbm_file == NULL) - terror (EXIT_FATAL, _("gdbm_open failed: %s"), gdbm_strerror (gdbm_errno)); - - if (gdbm_setopt (gdbm_file, GDBM_CACHESIZE, &cache_size, sizeof (int)) == - -1) - terror (EXIT_FATAL, _("gdbm_setopt failed: %s"), - gdbm_strerror (gdbm_errno)); - signal (SIGPIPE, SIG_IGN); memset (¶m, 0, sizeof (param)); diff --git a/src/gdbmtool.h b/src/gdbmtool.h index 3887338..8c585f0 100644 --- a/src/gdbmtool.h +++ b/src/gdbmtool.h @@ -102,6 +102,7 @@ extern char *file_name; extern int interactive; #define GDBMTOOLRC ".gdbmtoolrc" +#define GDBMTOOL_DEFFILE "junk.gdbm" struct slist @@ -144,6 +145,7 @@ struct gdbmarg struct gdbmarg *next; int type; int ref; + struct locus loc; union { char *string; @@ -162,9 +164,9 @@ void gdbmarglist_init (struct gdbmarglist *, struct gdbmarg *); void gdbmarglist_add (struct gdbmarglist *, struct gdbmarg *); void gdbmarglist_free (struct gdbmarglist *lst); -struct gdbmarg *gdbmarg_string (char *); -struct gdbmarg *gdbmarg_datum (datum *); -struct gdbmarg *gdbmarg_kvpair (struct kvpair *kvl); +struct gdbmarg *gdbmarg_string (char *, struct locus *); +struct gdbmarg *gdbmarg_datum (datum *, struct locus *); +struct gdbmarg *gdbmarg_kvpair (struct kvpair *kvl, struct locus *); int gdbmarg_free (struct gdbmarg *arg); void gdbmarg_destroy (struct gdbmarg **parg); @@ -223,14 +225,18 @@ extern struct dsegm *dsdef[]; #define VART_STRING 0 #define VART_BOOL 1 +#define VART_INT 2 #define VAR_OK 0 #define VAR_ERR_NOTDEF 1 #define VAR_ERR_BADTYPE 2 +#define VAR_ERR_FAILURE 3 int variable_set (const char *name, int type, void *val); int variable_get (const char *name, int type, void **val); +int variable_is_set (const char *name); void variable_print_all (FILE *fp); +const char *variable_mode_name (); int unescape (int c); @@ -27,10 +27,14 @@ struct dsegm *dsdef[DS_MAX]; %locations %token <type> T_TYPE -%token T_OFF T_PAD T_DEF T_SET T_BOGUS -%token <cmd> T_CMD -%token <num> T_NUM -%token <string> T_IDENT T_WORD +%token T_OFF "off" + T_PAD "pad" + T_DEF "define" + T_SET "set" + T_BOGUS +%token <cmd> T_CMD "command verb" +%token <num> T_NUM "number" +%token <string> T_IDENT "identifier" T_WORD "word" %type <string> string %type <arg> arg %type <arglist> arglist arg1list @@ -116,11 +120,11 @@ arg1list : arg arg : string { - $$ = gdbmarg_string ($1); + $$ = gdbmarg_string ($1, &@1); } | compound { - $$ = gdbmarg_kvpair ($1); + $$ = gdbmarg_kvpair ($1, &@1); } ; @@ -422,13 +422,12 @@ void vparse_error (struct locus *loc, const char *fmt, va_list ap) { if (!interactive) - fprintf (stderr, "%s", progname); + fprintf (stderr, "%s: ", progname); if (loc) { - fprintf (stderr, ": "); YY_LOCATION_PRINT (stderr, *loc); + fprintf (stderr, ": "); } - fprintf (stderr, ": "); vfprintf (stderr, fmt, ap); fputc ('\n', stderr); } @@ -29,9 +29,14 @@ struct variable { char *string; int bool; + int num; } v; + int (*hook) (struct variable *, int); + void *hook_data; }; +static int mode_toggle (struct variable *var, int after); + static struct variable vartab[] = { /* Top-level prompt */ { "ps1", VART_STRING, VARF_DFL, { "%p>%_" } }, @@ -41,9 +46,50 @@ static struct variable vartab[] = { { "delim1", VART_STRING, VARF_DFL, { "," } }, /* This delimits structure members */ { "delim2", VART_STRING, VARF_DFL, { "," } }, + { "cachesize", VART_INT, VARF_DFL, { num: DEFAULT_CACHESIZE } }, + { "blocksize", VART_INT, VARF_DFL, { num: 0 } }, + { "readonly", VART_BOOL, VARF_DFL, { num: 0 }, mode_toggle }, + { "newdb", VART_BOOL, VARF_DFL, { 0 }, mode_toggle }, + { "lock", VART_BOOL, VARF_DFL, { num: 1 } }, + { "mmap", VART_BOOL, VARF_DFL, { num: 1 } }, + { "sync", VART_BOOL, VARF_DFL, { num: 0 } }, { NULL } }; +static int +mode_toggle (struct variable *var, int after) +{ + if (after) + { + struct variable *vp; + int newval = !var->v.bool; + + for (vp = vartab; vp->name; vp++) + { + if (vp == var) + continue; + else if (vp->hook == mode_toggle) + { + vp->v.bool = newval; + newval = 0; + } + } + } + return 0; +} + +const char * +variable_mode_name () +{ + struct variable *vp; + + for (vp = vartab; vp->name; vp++) + if (vp->hook == mode_toggle && vp->v.bool) + return vp->name; + + return NULL; +} + static struct variable * varfind (const char *name) { @@ -56,35 +102,133 @@ varfind (const char *name) return NULL; } +typedef int (*setvar_t) (struct variable *, void *); + +static int +s2s (struct variable *vp, void *val) +{ + vp->v.string = estrdup (val); + return 0; +} + +static int +b2s (struct variable *vp, void *val) +{ + vp->v.string = estrdup (*(int*)val ? "true" : "false"); + return 0; +} + +static int +i2s (struct variable *vp, void *val) +{ + char buf[128]; + snprintf (buf, sizeof buf, "%d", *(int*)val); + vp->v.string = estrdup (buf); + return 0; +} + +static int +s2b (struct variable *vp, void *val) +{ + static char *trueval[] = { "on", "true", "yes", NULL }; + static char *falseval[] = { "off", "false", "no", NULL }; + int i; + unsigned long n; + char *p; + + for (i = 0; trueval[i]; i++) + if (strcasecmp (trueval[i], val) == 0) + { + vp->v.bool = 1; + return 0; + } + + for (i = 0; falseval[i]; i++) + if (strcasecmp (falseval[i], val) == 0) + { + vp->v.bool = 0; + return 1; + } + + n = strtoul (val, &p, 0); + if (*p) + return VAR_ERR_BADTYPE; + vp->v.bool = !!n; + return VAR_OK; +} + +static int +s2i (struct variable *vp, void *val) +{ + char *p; + int n = strtoul (val, &p, 0); + + if (*p) + return VAR_ERR_BADTYPE; + + vp->v.num = n; + return VAR_OK; +} + +static int +b2b (struct variable *vp, void *val) +{ + vp->v.bool = !!*(int*)val; + return VAR_OK; +} + +static int +b2i (struct variable *vp, void *val) +{ + vp->v.num = *(int*)val; + return VAR_OK; +} + +static int +i2i (struct variable *vp, void *val) +{ + vp->v.num = *(int*)val; + return VAR_OK; +} + +static int +i2b (struct variable *vp, void *val) +{ + vp->v.bool = *(int*)val; + return VAR_OK; +} + +static setvar_t setvar[3][3] = { + /* s b i */ + /* s */ { s2s, b2s, i2s }, + /* b */ { s2b, b2b, i2b }, + /* i */ { s2i, b2i, i2i } +}; + int variable_set (const char *name, int type, void *val) { struct variable *vp = varfind (name); - + int rc; + if (!vp) return VAR_ERR_NOTDEF; + + if (vp->hook && vp->hook (vp, 0)) + return VAR_ERR_FAILURE; - if (type != vp->type) - return VAR_ERR_BADTYPE; - - switch (vp->type) - { - case VART_STRING: - if (vp->flags && VARF_SET) - free (vp->v.string); - vp->v.string = estrdup (val); - break; - - case VART_BOOL: - if (val == NULL) - vp->v.bool = 0; - else - vp->v.bool = *(int*)val; - break; - } + if (vp->type == VART_STRING && (vp->flags && VARF_SET)) + free (vp->v.string); + rc = setvar[vp->type][type] (vp, val); + + if (rc) + return rc; vp->flags |= VARF_SET; + if (vp->hook) + vp->hook (vp, 1); + return VAR_OK; } @@ -108,6 +252,10 @@ variable_get (const char *name, int type, void **val) case VART_BOOL: *(int*)val = vp->v.bool; break; + + case VART_INT: + *(int*)val = vp->v.num; + break; } return VAR_OK; @@ -123,6 +271,10 @@ variable_print_all (FILE *fp) { switch (vp->type) { + case VART_INT: + fprintf (fp, "%s=%d", vp->name, vp->v.num); + break; + case VART_BOOL: fprintf (fp, "%s%s", vp->v.bool ? "no" : "", vp->name); break; @@ -146,3 +298,12 @@ variable_print_all (FILE *fp) } } +int +variable_is_set (const char *name) +{ + int n; + + if (variable_get (name, VART_BOOL, (void **) &n)) + return 1; + return n; +} |