aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-05-14 13:16:37 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2013-05-14 13:16:37 +0000
commitc3df0bf5f64241cb7ea00c1894da7f81e055a2aa (patch)
tree2a698dae997c076077b1ad7476d6576c0f89db12 /src
parent60f99611aee975bcd0710c59e32e8c2a13154603 (diff)
downloadgdbm-c3df0bf5f64241cb7ea00c1894da7f81e055a2aa.tar.gz
gdbm-c3df0bf5f64241cb7ea00c1894da7f81e055a2aa.tar.bz2
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.
Diffstat (limited to 'src')
-rw-r--r--src/datconv.c9
-rw-r--r--src/gdbmload.c9
-rw-r--r--src/gdbmtool.c255
-rw-r--r--src/gdbmtool.h12
-rw-r--r--src/gram.y16
-rw-r--r--src/lex.l5
-rw-r--r--src/var.c199
7 files changed, 396 insertions, 109 deletions
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 (&param, 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);
diff --git a/src/gram.y b/src/gram.y
index af0093e..75c7e86 100644
--- a/src/gram.y
+++ b/src/gram.y
@@ -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);
}
;
diff --git a/src/lex.l b/src/lex.l
index 8596365..dcd9af3 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -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);
}
diff --git a/src/var.c b/src/var.c
index 4a0ea60..ffa7297 100644
--- a/src/var.c
+++ b/src/var.c
@@ -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;
+}

Return to:

Send suggestions and report system problems to the System administrator.