aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-05-13 06:27:44 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2013-05-13 06:27:44 +0000
commit1638ed6202b77b521214128189dc4aacdb5fe098 (patch)
tree2e82fd4a16bef6f4d29bf11b4b4b62e7fa9de28f
parent4785154fda6411a384a4ead5abb18c22bb77a8f0 (diff)
downloadgdbm-1638ed6202b77b521214128189dc4aacdb5fe098.tar.gz
gdbm-1638ed6202b77b521214128189dc4aacdb5fe098.tar.bz2
Handle structured key and content data in gdbmtool.
* src/datconv.c: New file. * src/Makefile.am (gdbmtool_SOURCES): Add datconv.c. * src/gdbmtool.h (slist, kvpair): New structures. (gdbmarg): Keep various types of data depending on the value of the type member. (slist_new, slist_free) (kvpair_string, kvpair_list): New protos. (gdbmarg_new): Remove. (gdbmarg_string, gdbmarg_datum) (gdbmarg_kvpair, gdbmarg_free) (gdbmarg_destroy): New protos. (xd_expand, xd_store, datadef_locate): New protos. (field, dsegm): New structs. (dsegm_new, dsegm_new_field, dsegm_free_list): New protos. * src/gdbmtool.c: Rewrite. * src/gram.y: Change grammar to allow for defining key and content structure and for supplying structured data as arguments to fetch, store and similar functions. * src/lex.l: Handle new token types. * tests/dtload.c (main): Fix parser. * tests/gtload.c: Likewise.
-rw-r--r--ChangeLog27
-rw-r--r--src/Makefile.am1
-rw-r--r--src/datconv.c385
-rw-r--r--src/gdbmtool.c448
-rw-r--r--src/gdbmtool.h97
-rw-r--r--src/gram.y154
-rw-r--r--src/lex.l73
-rw-r--r--tests/dtload.c7
-rw-r--r--tests/gtload.c7
9 files changed, 1057 insertions, 142 deletions
diff --git a/ChangeLog b/ChangeLog
index 1fb7809..42a7a71 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2013-05-13 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ Handle structured key and content data in gdbmtool.
+
+ * src/datconv.c: New file.
+ * src/Makefile.am (gdbmtool_SOURCES): Add datconv.c.
+ * src/gdbmtool.h (slist, kvpair): New structures.
+ (gdbmarg): Keep various types of data depending on the
+ value of the type member.
+ (slist_new, slist_free)
+ (kvpair_string, kvpair_list): New protos.
+ (gdbmarg_new): Remove.
+ (gdbmarg_string, gdbmarg_datum)
+ (gdbmarg_kvpair, gdbmarg_free)
+ (gdbmarg_destroy): New protos.
+ (xd_expand, xd_store, datadef_locate): New protos.
+ (field, dsegm): New structs.
+ (dsegm_new, dsegm_new_field, dsegm_free_list): New protos.
+ * src/gdbmtool.c: Rewrite.
+ * src/gram.y: Change grammar to allow for defining key and
+ content structure and for supplying structured data as arguments
+ to fetch, store and similar functions.
+ * src/lex.l: Handle new token types.
+
+ * tests/dtload.c (main): Fix parser.
+ * tests/gtload.c: Likewise.
+
2013-05-11 Sergey Poznyakoff <gray@gnu.org.ua>
Rewrite gdbmtool parser.
diff --git a/src/Makefile.am b/src/Makefile.am
index d5561ea..795832d 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -80,6 +80,7 @@ bin_PROGRAMS = gdbmtool gdbm_load gdbm_dump
gdbmtool_LDADD = ./libgdbmapp.a ./libgdbm.la
gdbmtool_SOURCES = \
+ datconv.c\
gram.y\
lex.l\
gdbmtool.h\
diff --git a/src/datconv.c b/src/datconv.c
new file mode 100644
index 0000000..2ef64a6
--- /dev/null
+++ b/src/datconv.c
@@ -0,0 +1,385 @@
+/* This file is part of GDBM, the GNU data base manager.
+ Copyright (C) 1990, 1991, 1993, 2007, 2011, 2013 Free Software Foundation,
+ Inc.
+
+ GDBM is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GDBM is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with GDBM. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "gdbmtool.h"
+
+#define DEFFMT(name, type, fmt) \
+static int \
+name (FILE *fp, void *ptr, int size) \
+{ \
+ fprintf (fp, fmt, *(type*) ptr); \
+ return size; \
+}
+
+DEFFMT (f_char, char, "%c")
+DEFFMT (f_int, int, "%d")
+DEFFMT (f_uint, unsigned, "%u")
+DEFFMT (f_long, long, "%ld")
+DEFFMT (f_ulong, unsigned long, "%lu")
+DEFFMT (f_llong, long long, "%lld")
+DEFFMT (f_ullong, unsigned long long, "%llu")
+DEFFMT (f_float, float, "%f")
+DEFFMT (f_double, double, "%e")
+
+static int
+f_string (FILE *fp, void *ptr, int size)
+{
+ int sz;
+ char *s;
+
+ for (sz = 1, s = ptr; *s; s++, sz++)
+ {
+ int c;
+
+ if (isprint (*s))
+ fputc (*s, fp);
+ else if ((c = escape (*s)))
+ fprintf (fp, "\\%c", c);
+ else
+ fprintf (fp, "\\%03o", *s);
+ }
+ return sz;
+}
+
+static int
+f_zstring (FILE *fp, void *ptr, int size)
+{
+ int sz;
+ char *s;
+
+ for (sz = 0, s = ptr; sz < size; s++, sz++)
+ {
+ int c;
+
+ if (isprint (*s))
+ fputc (*s, fp);
+ else if ((c = escape (*s)))
+ fprintf (fp, "\\%c", c);
+ else
+ fprintf (fp, "\\%03o", *s);
+ }
+ return sz;
+}
+
+int
+s_char (struct xdatum *xd, char *str)
+{
+ xd_store (xd, str, 1);
+ return 0;
+}
+
+#define DEFNSCAN(name, type, temptype, strto) \
+int \
+name (struct xdatum *xd, char *str) \
+{ \
+ temptype n; \
+ type t; \
+ char *p; \
+ \
+ errno = 0; \
+ n = strto (str, &p, 0); \
+ if (*p) \
+ return 1; \
+ if (errno == ERANGE || (t = n) != n) \
+ return 1; \
+ xd_store (xd, &n, sizeof (n)); \
+ return 0; \
+}
+
+DEFNSCAN(s_int, int, long, strtol)
+DEFNSCAN(s_uint, unsigned, unsigned long, strtol)
+DEFNSCAN(s_long, long, long, strtoul)
+DEFNSCAN(s_ulong, unsigned long, unsigned long, strtoul)
+DEFNSCAN(s_llong, long long, long long, strtoll)
+DEFNSCAN(s_ullong, unsigned long long, unsigned long long, strtoull)
+
+int
+s_double (struct xdatum *xd, char *str)
+{
+ double d;
+ char *p;
+
+ errno = 0;
+ d = strtod (str, &p);
+ if (errno || *p)
+ return 1;
+ xd_store (xd, &d, sizeof (d));
+ return 0;
+}
+
+int
+s_float (struct xdatum *xd, char *str)
+{
+ float d;
+ char *p;
+
+ errno = 0;
+ d = strtof (str, &p);
+ if (errno || *p)
+ return 1;
+ xd_store (xd, &d, sizeof (d));
+ return 0;
+}
+
+int
+s_string (struct xdatum *xd, char *str)
+{
+ xd_store (xd, str, strlen (str) + 1);
+ return 0;
+}
+
+int
+s_zstring (struct xdatum *xd, char *str)
+{
+ xd_store (xd, str, strlen (str));
+ return 0;
+}
+
+static struct datadef datatab[] = {
+ { "char", sizeof(char), f_char, s_char },
+ { "int", sizeof(int), f_int, s_int },
+ { "unsigned", sizeof(unsigned), f_uint, s_uint },
+ { "uint", sizeof(unsigned), f_uint, s_uint },
+ { "long", sizeof(long), f_long, s_long },
+ { "ulong", sizeof(unsigned long), f_ulong, s_ulong },
+ { "llong", sizeof(long long), f_llong, s_llong },
+ { "ullong", sizeof(unsigned long long), f_ullong, s_ullong },
+ { "float", sizeof(float), f_float, s_float },
+ { "double", sizeof(double), f_double, s_double },
+ { "string", 0, f_string, s_string },
+ { "zstring", 0, f_zstring, s_zstring },
+ { NULL }
+};
+
+struct datadef *
+datadef_locate (const char *name)
+{
+ struct datadef *p;
+
+ for (p = datatab; p->name; p++)
+ if (strcmp (p->name, name) == 0)
+ return p;
+ return NULL;
+}
+
+struct dsegm *
+dsegm_new (int type)
+{
+ struct dsegm *p = emalloc (sizeof (*p));
+ p->next = NULL;
+ p->type = type;
+ return p;
+}
+
+struct dsegm *
+dsegm_new_field (struct datadef *type, char *id, int dim)
+{
+ struct dsegm *p = dsegm_new (FDEF_FLD);
+ p->v.field.type = type;
+ p->v.field.name = id;
+ p->v.field.dim = dim;
+ return p;
+}
+
+void
+dsegm_free_list (struct dsegm *dp)
+{
+ while (dp)
+ {
+ struct dsegm *next = dp->next;
+ free (dp);
+ dp = next;
+ }
+}
+
+void
+datum_format (FILE *fp, datum const *dat, struct dsegm *ds, char *delim)
+{
+ int off = 0;
+
+ if (!ds)
+ {
+ fprintf (fp, "%.*s\n", dat->dsize, dat->dptr);
+ return;
+ }
+
+ for (; ds && off <= dat->dsize; ds = ds->next)
+ {
+ switch (ds->type)
+ {
+ case FDEF_FLD:
+ if (ds->v.field.name)
+ fprintf (fp, "%s=", ds->v.field.name);
+ if (ds->v.field.dim > 1)
+ fprintf (fp, "{ ");
+ if (ds->v.field.type->format)
+ {
+ int i, n;
+
+ for (i = 0; i < ds->v.field.dim; i++)
+ {
+ if (i)
+ fwrite (delim, strlen (delim), 1, fp);
+ if (off + ds->v.field.type->size > dat->dsize)
+ {
+ fprintf (fp, _("(not enough data)"));
+ off += dat->dsize;
+ break;
+ }
+ else
+ {
+ n = ds->v.field.type->format (fp,
+ (char*) dat->dptr + off,
+ ds->v.field.type->size ?
+ ds->v.field.type->size :
+ dat->dsize - off);
+ off += n;
+ }
+ }
+ }
+ if (ds->v.field.dim > 1)
+ fprintf (fp, " }");
+ fwrite (delim, strlen (delim), 1, fp);
+ break;
+
+ case FDEF_OFF:
+ off = ds->v.n;
+ break;
+
+ case FDEF_PAD:
+ off += ds->v.n;
+ break;
+ }
+ }
+}
+
+struct xdatum
+{
+ char *dptr;
+ size_t dsize;
+ size_t dmax;
+ int off;
+};
+
+void
+xd_expand (struct xdatum *xd, size_t size)
+{
+ if (xd->dmax < size)
+ {
+ xd->dptr = erealloc (xd->dptr, size);
+ memset (xd->dptr + xd->dmax, 0, size - xd->dmax);
+ xd->dmax = size;
+ }
+}
+
+void
+xd_store (struct xdatum *xd, void *val, size_t size)
+{
+ xd_expand (xd, xd->off + size);
+ memcpy (xd->dptr + xd->off, val, size);
+ xd->off += size;
+ if (xd->off > xd->dsize)
+ xd->dsize = xd->off;
+}
+
+int
+datum_scan_notag (datum *dat, struct dsegm *ds, struct kvpair *kv)
+{
+ struct xdatum xd;
+ int i, n;
+ struct slist *s;
+ int err = 0;
+
+ memset (&xd, 0, sizeof (xd));
+
+ for (; err == 0 && ds && kv; ds = ds->next, kv = kv->next)
+ {
+ if (kv->key)
+ {
+ parse_error (&kv->loc,
+ _("mixing tagged and untagged values is not allowed"));
+ err = 1;
+ break;
+ }
+
+ switch (ds->type)
+ {
+ case FDEF_FLD:
+ if (!ds->v.field.type->scan)
+ abort ();
+
+ switch (kv->type)
+ {
+ case KV_STRING:
+ err = ds->v.field.type->scan (&xd, kv->val.s);
+ if (err)
+ parse_error (&kv->loc, _("cannot convert"));
+ break;
+
+ case KV_LIST:
+ for (i = 0, s = kv->val.l; i < ds->v.field.dim && s;
+ i++, s = s->next)
+ {
+ err = ds->v.field.type->scan (&xd, s->str);
+ if (err)
+ {
+ parse_error (&kv->loc,
+ _("cannot convert value #%d: %s"),
+ i, s->str);
+ break;
+ }
+ }
+ /* FIXME: Warn if (s) -> "extra data" */
+ }
+ break;
+
+ case FDEF_OFF:
+ xd_expand (&xd, ds->v.n);
+ xd.off = ds->v.n;
+ break;
+
+ case FDEF_PAD:
+ xd_expand (&xd, xd.off + ds->v.n);
+ xd.off += ds->v.n;
+ break;
+ }
+ }
+
+ if (err)
+ {
+ free (xd.dptr);
+ return 1;
+ }
+
+ dat->dptr = xd.dptr;
+ dat->dsize = xd.dsize;
+
+ return 0;
+}
+
+int
+datum_scan_tag (datum *dat, struct dsegm *ds, struct kvpair *kv)
+{
+ parse_error (&kv->loc, "tagged values are not yet supported");
+ return 1;
+}
+
+int
+datum_scan (datum *dat, struct dsegm *ds, struct kvpair *kv)
+{
+ return (kv->key ? datum_scan_tag : datum_scan_notag) (dat, ds, kv);
+}
diff --git a/src/gdbmtool.c b/src/gdbmtool.c
index 82da808..78ffb6e 100644
--- a/src/gdbmtool.c
+++ b/src/gdbmtool.c
@@ -38,8 +38,6 @@ GDBM_FILE gdbm_file = NULL; /* Database to operate upon */
int interactive; /* Are we running in interactive mode? */
datum key_data; /* Current key */
datum return_data; /* Current data */
-int key_z = 1; /* Keys are nul-terminated strings */
-int data_z = 1; /* Data are nul-terminated strings */
int quiet_option = 0; /* Omit usual welcome banner at startup */
#define SIZE_T_MAX ((size_t)-1)
@@ -235,6 +233,7 @@ trimnl (char *str)
return 0;
}
+#if 0
void
read_from_file (const char *name, int replace)
{
@@ -273,6 +272,8 @@ read_from_file (const char *name, int replace)
for (*p++ = 0; *p && isspace (*p); p++)
;
+
+ FIXME
key.dptr = buf;
key.dsize = strlen (buf) + key_z;
data.dptr = p;
@@ -283,6 +284,7 @@ read_from_file (const char *name, int replace)
}
fclose (fp);
}
+#endif
int
get_screen_lines ()
@@ -333,7 +335,7 @@ get_record_count ()
struct handler_param
{
int argc;
- char **argv;
+ struct gdbmarg **argv;
FILE *fp;
void *data;
};
@@ -353,11 +355,7 @@ count_handler (struct handler_param *param)
void
delete_handler (struct handler_param *param)
{
- if (key_data.dptr != NULL)
- free (key_data.dptr);
- key_data.dptr = strdup (param->argv[0]);
- key_data.dsize = strlen (param->argv[0]) + key_z;
- if (gdbm_delete (gdbm_file, key_data) != 0)
+ if (gdbm_delete (gdbm_file, param->argv[0]->v.dat) != 0)
{
if (gdbm_errno == GDBM_ITEM_NOT_FOUND)
terror (0, _("Item not found"));
@@ -370,14 +368,11 @@ delete_handler (struct handler_param *param)
void
fetch_handler (struct handler_param *param)
{
- if (key_data.dptr != NULL)
- free (key_data.dptr);
- key_data.dptr = strdup (param->argv[0]);
- key_data.dsize = strlen (param->argv[0]) + key_z;
- return_data = gdbm_fetch (gdbm_file, key_data);
+ return_data = gdbm_fetch (gdbm_file, param->argv[0]->v.dat);
if (return_data.dptr != NULL)
{
- fprintf (param->fp, "%.*s\n", return_data.dsize, return_data.dptr);
+ datum_format (param->fp, &return_data, dsdef[DS_CONTENT], ",");
+ fputc ('\n', param->fp);
free (return_data.dptr);
}
else
@@ -388,14 +383,9 @@ fetch_handler (struct handler_param *param)
void
store_handler (struct handler_param *param)
{
- datum key;
- datum data;
-
- key.dptr = param->argv[0];
- key.dsize = strlen (param->argv[0]) + key_z;
- data.dptr = param->argv[1];
- data.dsize = strlen (param->argv[1]) + data_z;
- if (gdbm_store (gdbm_file, key, data, GDBM_REPLACE) != 0)
+ if (gdbm_store (gdbm_file,
+ param->argv[0]->v.dat, param->argv[1]->v.dat,
+ GDBM_REPLACE) != 0)
fprintf (stderr, _("Item not inserted.\n"));
}
@@ -409,9 +399,13 @@ firstkey_handler (struct handler_param *param)
key_data = gdbm_firstkey (gdbm_file);
if (key_data.dptr != NULL)
{
- fprintf (param->fp, "%.*s\n", key_data.dsize, key_data.dptr);
+ datum_format (param->fp, &key_data, dsdef[DS_KEY], ",");
+ fputc ('\n', param->fp);
+
return_data = gdbm_fetch (gdbm_file, key_data);
- fprintf (param->fp, "%.*s\n", return_data.dsize, return_data.dptr);
+ datum_format (param->fp, &return_data, dsdef[DS_CONTENT], ",");
+ fputc ('\n', param->fp);
+
free (return_data.dptr);
}
else
@@ -422,20 +416,25 @@ firstkey_handler (struct handler_param *param)
void
nextkey_handler (struct handler_param *param)
{
- if (param->argv[0])
+ if (param->argc == 1)
{
if (key_data.dptr != NULL)
free (key_data.dptr);
- key_data.dptr = strdup (param->argv[0]);
- key_data.dsize = strlen (param->argv[0]) + key_z;
+ key_data.dptr = emalloc (param->argv[0]->v.dat.dsize);
+ key_data.dsize = param->argv[0]->v.dat.dsize;
+ memcpy (key_data.dptr, param->argv[0]->v.dat.dptr, key_data.dsize);
}
return_data = gdbm_nextkey (gdbm_file, key_data);
if (return_data.dptr != NULL)
{
key_data = return_data;
- fprintf (param->fp, "%.*s\n", key_data.dsize, key_data.dptr);
+ datum_format (param->fp, &key_data, dsdef[DS_KEY], ",");
+ fputc ('\n', param->fp);
+
return_data = gdbm_fetch (gdbm_file, key_data);
- fprintf (param->fp, "%.*s\n", return_data.dsize, return_data.dptr);
+ datum_format (param->fp, &return_data, dsdef[DS_CONTENT], ",");
+ fputc ('\n', param->fp);
+
free (return_data.dptr);
}
else
@@ -521,7 +520,7 @@ print_bucket_begin (struct handler_param *param, size_t *exp_count)
{
int temp;
- if (getnum (&temp, param->argv[0], NULL))
+ if (getnum (&temp, param->argv[0]->v.string, NULL))
return 1;
if (temp >= gdbm_file->header->dir_size / 4)
@@ -594,11 +593,8 @@ print_header_handler (struct handler_param *param)
void
hash_handler (struct handler_param *param)
{
- datum key;
-
- key.dptr = param->argv[0];
- key.dsize = strlen (param->argv[0]) + key_z;
- fprintf (param->fp, _("hash value = %x. \n"), _gdbm_hash (key));
+ fprintf (param->fp, _("hash value = %x. \n"),
+ _gdbm_hash (param->argv[0]->v.dat));
}
/* K - print the bucket cache */
@@ -623,6 +619,8 @@ print_version_handler (struct handler_param *param)
fprintf (param->fp, "%s\n", gdbm_version);
}
+#if 0
+FIXME
/* < file [replace] - read entries from file and store */
void
read_handler (struct handler_param *param)
@@ -630,6 +628,7 @@ read_handler (struct handler_param *param)
read_from_file (param->argv[0],
param->argv[1] && strcmp (param->argv[1], "replace") == 0);
}
+#endif
/* l - List all entries */
int
@@ -656,8 +655,10 @@ list_handler (struct handler_param *param)
terror (0, _("cannot fetch data (key %.*s)"), key.dsize, key.dptr);
else
{
- fprintf (param->fp, "%.*s %.*s\n", key.dsize, key.dptr, data.dsize,
- data.dptr);
+ datum_format (param->fp, &key, dsdef[DS_KEY], ",");
+ fputc (' ', param->fp);
+ datum_format (param->fp, &data, dsdef[DS_CONTENT], ",");
+ fputc ('\n', param->fp);
free (data.dptr);
}
free (key.dptr);
@@ -685,20 +686,21 @@ export_handler (struct handler_param *param)
for (i = 1; i < param->argc; i++)
{
- if (strcmp (param->argv[i], "truncate") == 0)
+ if (strcmp (param->argv[i]->v.string, "truncate") == 0)
flags = GDBM_NEWDB;
- else if (strcmp (param->argv[i], "binary") == 0)
+ else if (strcmp (param->argv[i]->v.string, "binary") == 0)
format = GDBM_DUMP_FMT_BINARY;
- else if (strcmp (param->argv[i], "ascii") == 0)
+ else if (strcmp (param->argv[i]->v.string, "ascii") == 0)
format = GDBM_DUMP_FMT_ASCII;
else
{
- syntax_error (_("unrecognized argument: %s"), param->argv[i]);
+ syntax_error (_("unrecognized argument: %s"),
+ param->argv[i]->v.string);
return;
}
}
- if (gdbm_dump (gdbm_file, param->argv[0], format, flags, 0600))
+ if (gdbm_dump (gdbm_file, param->argv[0]->v.string, format, flags, 0600))
{
terror (0, _("error dumping database: %s"), gdbm_strerror (gdbm_errno));
}
@@ -715,18 +717,20 @@ import_handler (struct handler_param *param)
for (i = 1; i < param->argc; i++)
{
- if (strcmp (param->argv[i], "replace") == 0)
+ if (strcmp (param->argv[i]->v.string, "replace") == 0)
flag = GDBM_REPLACE;
- else if (strcmp (param->argv[i], "nometa") == 0)
+ else if (strcmp (param->argv[i]->v.string, "nometa") == 0)
meta_mask = GDBM_META_MASK_MODE | GDBM_META_MASK_OWNER;
else
{
- syntax_error (_("unrecognized argument: %s"), param->argv[i]);
+ syntax_error (_("unrecognized argument: %s"),
+ param->argv[i]->v.string);
return;
}
}
- if (gdbm_load (&gdbm_file, param->argv[0], flag, meta_mask, &err_line))
+ if (gdbm_load (&gdbm_file, param->argv[0]->v.string, flag,
+ meta_mask, &err_line))
{
switch (gdbm_errno)
{
@@ -758,24 +762,6 @@ void
status_handler (struct handler_param *param)
{
fprintf (param->fp, _("Database file: %s\n"), file_name);
- fprintf (param->fp, _("Zero terminated keys: %s\n"), boolstr (key_z));
- fprintf (param->fp, _("Zero terminated data: %s\n"), boolstr (data_z));
-}
-
-/* z - toggle key nul-termination */
-void
-key_z_handler (struct handler_param *param)
-{
- key_z = !key_z;
- fprintf (param->fp, _("Zero terminated keys: %s\n"), boolstr (key_z));
-}
-
-/* Z - toggle data nul-termination */
-void
-data_z_handler (struct handler_param *param)
-{
- data_z = !data_z;
- fprintf (param->fp, _("Zero terminated data: %s\n"), boolstr (data_z));
}
struct prompt_exp;
@@ -874,12 +860,19 @@ void
prompt_handler (struct handler_param *param)
{
free (prompt);
- prompt = estrdup (param->argv[0]);
+ prompt = estrdup (param->argv[0]->v.string);
}
void help_handler (struct handler_param *param);
int help_begin (struct handler_param *param, size_t *exp_count);
+struct argdef
+{
+ char *name;
+ int type;
+ int ds;
+};
+
struct command
{
char *name; /* Command name */
@@ -887,7 +880,7 @@ struct command
int (*begin) (struct handler_param *param, size_t *);
void (*handler) (struct handler_param *param);
void (*end) (void *data);
- char *args[NARGS];
+ struct argdef args[NARGS];
char *doc;
};
@@ -896,81 +889,96 @@ struct command command_tab[] = {
#define S(s) #s, sizeof (#s) - 1
{ S(count),
NULL, count_handler, NULL,
- { NULL, NULL, }, N_("count (number of entries)") },
+ { { NULL } }, N_("count (number of entries)") },
{ S(delete),
NULL, delete_handler, NULL,
- { N_("key"), NULL, }, N_("delete") },
+ { { N_("key"), ARG_DATUM, DS_KEY }, { NULL } }, N_("delete") },
{ S(export),
NULL, export_handler, NULL,
- { N_("file"), "[truncate]", "[binary|ascii]" }, N_("export") },
+ { { N_("file"), ARG_STRING },
+ { "[truncate]", ARG_STRING },
+ { "[binary|ascii]", ARG_STRING },
+ { NULL } },
+ N_("export") },
{ S(fetch),
NULL, fetch_handler, NULL,
- { N_("key"), NULL }, N_("fetch") },
+ { { N_("key"), ARG_DATUM, DS_KEY }, { NULL } }, N_("fetch") },
{ S(import),
NULL, import_handler, NULL,
- { N_("file"), "[replace]", "[nometa]" }, N_("import") },
+ { { N_("file"), ARG_STRING },
+ { "[replace]", ARG_STRING },
+ { "[nometa]" , ARG_STRING },
+ { NULL } },
+ N_("import") },
{ S(list),
list_begin, list_handler, NULL,
- { NULL, NULL }, N_("list") },
+ { { NULL } }, N_("list") },
{ S(next),
NULL, nextkey_handler, NULL,
- { N_("[key]"), NULL }, N_("nextkey") },
+ { { N_("[key]"), ARG_STRING },
+ { NULL } },
+ N_("nextkey") },
{ S(store),
NULL, store_handler, NULL,
- { N_("key"), N_("data") }, N_("store") },
+ { { N_("key"), ARG_DATUM, DS_KEY },
+ { N_("data"), ARG_DATUM, DS_CONTENT },
+ { NULL } },
+ N_("store") },
{ S(first),
NULL, firstkey_handler, NULL,
- { NULL, NULL }, N_("firstkey") },
+ { { NULL } }, N_("firstkey") },
+#if 0
+ FIXME
{ S(read),
NULL, read_handler, NULL,
- { N_("file"), "[replace]" },
+ { { N_("file"), ARG_STRING },
+ { "[replace]", ARG_STRING },
+ { NULL } },
N_("read entries from file and store") },
+#endif
{ S(reorganize),
NULL, reorganize_handler, NULL,
- { NULL, NULL, }, N_("reorganize") },
- { S(key-zero),
- NULL, key_z_handler, NULL,
- { NULL, NULL }, N_("toggle key nul-termination") },
+ { { NULL } }, N_("reorganize") },
{ S(avail),
avail_begin, avail_handler, NULL,
- { NULL, NULL, }, N_("print avail list") },
+ { { NULL } }, N_("print avail list") },
{ S(bucket),
print_bucket_begin, print_current_bucket_handler, NULL,
- { N_("bucket-number"), NULL, }, N_("print a bucket") },
+ { { N_("bucket-number"), ARG_STRING },
+ { NULL } }, N_("print a bucket") },
{ S(current),
print_current_bucket_begin, print_current_bucket_handler, NULL,
- { NULL, NULL, },
+ { { NULL } },
N_("print current bucket") },
{ S(dir),
print_dir_begin, print_dir_handler, NULL,
- { NULL, NULL, }, N_("print hash directory") },
+ { { NULL } }, N_("print hash directory") },
{ S(header),
print_header_begin , print_header_handler, NULL,
- { NULL, NULL, }, N_("print file header") },
+ { { NULL } }, N_("print file header") },
{ S(hash),
NULL, hash_handler, NULL,
- { N_("key"), NULL, }, N_("hash value of key") },
+ { { N_("key"), ARG_DATUM, DS_KEY },
+ { NULL } }, N_("hash value of key") },
{ S(cache),
print_cache_begin, print_cache_handler, NULL,
- { NULL, NULL, }, N_("print the bucket cache") },
+ { { NULL } }, N_("print the bucket cache") },
{ S(status),
NULL, status_handler, NULL,
- { NULL, NULL }, N_("print current program status") },
+ { { NULL } }, N_("print current program status") },
{ S(version),
NULL, print_version_handler, NULL,
- { NULL, NULL, }, N_("print version of gdbm") },
- { S(data-zero),
- NULL, data_z_handler, NULL,
- { NULL, NULL }, N_("toggle data nul-termination") },
+ { { NULL } }, N_("print version of gdbm") },
{ S(help),
help_begin, help_handler, NULL,
- { NULL, NULL, }, N_("print this help list") },
+ { { NULL } }, N_("print this help list") },
{ S(prompt),
NULL, prompt_handler, NULL,
- { N_("text") }, N_("set command prompt") },
+ { { N_("text"), ARG_STRING },
+ { NULL } }, N_("set command prompt") },
{ S(quit),
NULL, quit_handler, NULL,
- { NULL, NULL, }, N_("quit the program") },
+ { { NULL } }, N_("quit the program") },
#undef S
{ 0 }
};
@@ -1015,8 +1023,8 @@ help_handler (struct handler_param *param)
n = fprintf (fp, " %s", cmd->name);
- for (i = 0; i < NARGS && cmd->args[i]; i++)
- n += fprintf (fp, " %s", gettext (cmd->args[i]));
+ for (i = 0; i < NARGS && cmd->args[i].name; i++)
+ n += fprintf (fp, " %s", gettext (cmd->args[i].name));
if (n < CMDCOLS)
fprintf (fp, "%*.s", CMDCOLS-n, "");
@@ -1086,6 +1094,136 @@ struct gdbm_option optab[] = {
#define ARGINC 16
+struct gdbmarg *
+gdbmarg_string (char *string)
+{
+ struct gdbmarg *arg = emalloc (sizeof (*arg));
+ arg->next = NULL;
+ arg->type = ARG_STRING;
+ arg->ref = 1;
+ arg->v.string = string;
+ return arg;
+}
+
+struct gdbmarg *
+gdbmarg_datum (datum *dat)
+{
+ struct gdbmarg *arg = emalloc (sizeof (*arg));
+ arg->next = NULL;
+ arg->type = ARG_DATUM;
+ arg->ref = 1;
+ arg->v.dat = *dat;
+ return arg;
+}
+
+struct gdbmarg *
+gdbmarg_kvpair (struct kvpair *kvp)
+{
+ struct gdbmarg *arg = emalloc (sizeof (*arg));
+ arg->next = NULL;
+ arg->type = ARG_KVPAIR;
+ arg->ref = 1;
+ arg->v.kvpair = kvp;
+ return arg;
+}
+
+struct slist *
+slist_new (char *s)
+{
+ struct slist *lp = emalloc (sizeof (*lp));
+ lp->next = NULL;
+ lp->str = s;
+}
+
+void
+slist_free (struct slist *lp)
+{
+ while (lp)
+ {
+ struct slist *next = lp->next;
+ free (lp->str);
+ free (lp);
+ lp = next;
+ }
+}
+
+struct kvpair *
+kvpair_string (struct locus *loc, char *val)
+{
+ struct kvpair *p = ecalloc (1, sizeof (*p));
+ p->type = KV_STRING;
+ if (loc)
+ p->loc = *loc;
+ p->val.s = val;
+ return p;
+}
+
+struct kvpair *
+kvpair_list (struct locus *loc, struct slist *s)
+{
+ struct kvpair *p = ecalloc (1, sizeof (*p));
+ p->type = KV_LIST;
+ if (loc)
+ p->loc = *loc;
+ p->val.l = s;
+ return p;
+}
+
+
+static void
+kvlist_free (struct kvpair *kvp)
+{
+ while (kvp)
+ {
+ struct kvpair *next = kvp->next;
+ free (kvp->key);
+ switch (kvp->type)
+ {
+ case KV_STRING:
+ free (kvp->val.s);
+ break;
+
+ case KV_LIST:
+ slist_free (kvp->val.l);
+ break;
+ }
+ free (kvp);
+ kvp = next;
+ }
+}
+
+int
+gdbmarg_free (struct gdbmarg *arg)
+{
+ if (arg && --arg->ref == 0)
+ {
+ switch (arg->type)
+ {
+ case ARG_STRING:
+ free (arg->v.string);
+ break;
+
+ case ARG_KVPAIR:
+ kvlist_free (arg->v.kvpair);
+ break;
+
+ case ARG_DATUM:
+ free (arg->v.dat.dptr);
+ break;
+ }
+ free (arg);
+ return 0;
+ }
+ return 1;
+}
+
+void
+gdbmarg_destroy (struct gdbmarg **parg)
+{
+ if (parg && gdbmarg_free (*parg))
+ *parg = NULL;
+}
+
void
gdbmarglist_init (struct gdbmarglist *lst, struct gdbmarg *arg)
{
@@ -1113,25 +1251,83 @@ gdbmarglist_free (struct gdbmarglist *lst)
for (arg = lst->head; arg; )
{
struct gdbmarg *next = arg->next;
- free (arg->string);
- free (arg);
+ gdbmarg_free (arg);
arg = next;
}
}
+
+struct handler_param param;
+size_t argmax;
+
+void
+param_free_argv (struct handler_param *param, int n)
+{
+ int i;
+
+ for (i = 0; i < n; i++)
+ gdbmarg_destroy (&param->argv[i]);
+ param->argc = 0;
+}
+
+typedef struct gdbmarg *(*coerce_type_t) (struct gdbmarg *arg,
+ struct argdef *def);
struct gdbmarg *
-gdbmarg_new (char *string)
+coerce_ref (struct gdbmarg *arg, struct argdef *def)
{
- struct gdbmarg *arg = emalloc (sizeof (*arg));
- arg->next = NULL;
- arg->string = string;
+ ++arg->ref;
return arg;
}
-
-struct handler_param param;
-size_t argmax;
+struct gdbmarg *
+coerce_k2d (struct gdbmarg *arg, struct argdef *def)
+{
+ datum d;
+
+ if (datum_scan (&d, dsdef[def->ds], arg->v.kvpair))
+ return NULL;
+ return gdbmarg_datum (&d);
+}
+
+struct gdbmarg *
+coerce_s2d (struct gdbmarg *arg, struct argdef *def)
+{
+ datum d;
+ struct kvpair kvp;
+
+ memset (&kvp, 0, sizeof (kvp));
+ kvp.type = KV_STRING;
+ kvp.val.s = arg->v.string;
+ if (datum_scan (&d, dsdef[def->ds], &kvp))
+ return NULL;
+ return gdbmarg_datum (&d);
+}
+
+#define coerce_fail NULL
+
+coerce_type_t coerce_tab[ARG_MAX][ARG_MAX] = {
+ /* s d k */
+ /* s */ { coerce_ref, coerce_fail, coerce_fail },
+ /* d */ { coerce_s2d, coerce_ref, coerce_k2d },
+ /* k */ { coerce_fail, coerce_fail, coerce_ref }
+};
+
+char *argtypestr[] = { "string", "datum", "k/v pair" };
+
+struct gdbmarg *
+coerce (struct gdbmarg *arg, struct argdef *def)
+{
+ if (!coerce_tab[def->type][arg->type])
+ {
+ //FIXME: locus
+ syntax_error (_("cannot coerce %s to %s"),
+ argtypestr[arg->type], argtypestr[def->type]);
+ return NULL;
+ }
+ return coerce_tab[def->type][arg->type] (arg, def);
+}
+
int
run_command (const char *verb, struct gdbmarglist *arglist)
{
@@ -1148,8 +1344,8 @@ run_command (const char *verb, struct gdbmarglist *arglist)
return 1;
arg = arglist ? arglist->head : NULL;
-
- for (i = 0; cmd->args[i] && arg; i++, arg = arg->next)
+
+ for (i = 0; cmd->args[i].name && arg; i++, arg = arg->next)
{
if (i >= argmax)
{
@@ -1157,15 +1353,22 @@ run_command (const char *verb, struct gdbmarglist *arglist)
param.argv = erealloc (param.argv,
sizeof (param.argv[0]) * argmax);
}
- param.argv[i] = estrdup (arg->string);
+ if ((param.argv[i] = coerce (arg, &cmd->args[i])) == NULL)
+ {
+ param_free_argv (&param, i);
+ return 1;
+ }
}
- for (; cmd->args[i]; i++)
+ for (; cmd->args[i].name; i++)
{
- char *argname = cmd->args[i];
+ char *argname = cmd->args[i].name;
+ struct gdbmarg *t;
+
if (*argname == '[')
/* Optional argument */
break;
+
if (!interactive)
{
syntax_error (_("%s: not enough arguments"), cmd->name);
@@ -1183,7 +1386,14 @@ run_command (const char *verb, struct gdbmarglist *arglist)
param.argv = erealloc (param.argv,
sizeof (param.argv[0]) * argmax);
}
- param.argv[i] = estrdup (argbuf);
+
+ t = gdbmarg_string (estrdup (argbuf));
+ if ((param.argv[i] = coerce (t, &cmd->args[i])) == NULL)
+ {
+ gdbmarg_free (t);
+ param_free_argv (&param, i);
+ return 1;
+ }
}
if (arg)
@@ -1194,6 +1404,12 @@ run_command (const char *verb, struct gdbmarglist *arglist)
/* Prepare for calling the handler */
param.argc = i;
+ if (!param.argv)
+ {
+ argmax = ARGINC;
+ param.argv = ecalloc (argmax, sizeof (param.argv[0]));
+ }
+ param.argv[i] = NULL;
param.fp = NULL;
param.data = NULL;
pagfp = NULL;
@@ -1227,10 +1443,8 @@ run_command (const char *verb, struct gdbmarglist *arglist)
if (pagfp)
pclose (pagfp);
}
-
- for (i = 0; i < param.argc; i++)
- free (param.argv[i]);
- param.argc = 0;
+
+ param_free_argv (&param, param.argc);
return 0;
}
@@ -1325,6 +1539,8 @@ main (int argc, char *argv[])
/* Initialize variables. */
interactive = isatty (0);
+ dsdef[DS_KEY] = dsegm_new_field (datadef_locate ("string"), NULL, 1);
+ dsdef[DS_CONTENT] = dsegm_new_field (datadef_locate ("string"), NULL, 1);
if (reader)
{
diff --git a/src/gdbmtool.h b/src/gdbmtool.h
index f2807b9..64335eb 100644
--- a/src/gdbmtool.h
+++ b/src/gdbmtool.h
@@ -99,11 +99,52 @@ void setsource (const char *filename, FILE *file);
extern int interactive;
+struct slist
+{
+ struct slist *next;
+ char *str;
+};
+
+struct slist *slist_new (char *s);
+void slist_free (struct slist *);
+
+#define KV_STRING 0
+#define KV_LIST 1
+
+struct kvpair
+{
+ struct kvpair *next;
+ int type;
+ struct locus loc;
+ char *key;
+ union
+ {
+ char *s;
+ struct slist *l;
+ } val;
+};
+
+struct kvpair *kvpair_string (struct locus *loc, char *val);
+struct kvpair *kvpair_list (struct locus *loc, struct slist *s);
+
+
+#define ARG_STRING 0
+#define ARG_DATUM 1
+#define ARG_KVPAIR 2
+#define ARG_MAX 3
+
/* Argument to a command handler */
struct gdbmarg
{
struct gdbmarg *next;
- char *string;
+ int type;
+ int ref;
+ union
+ {
+ char *string;
+ datum dat;
+ struct kvpair *kvpair;
+ } v;
};
/* List of arguments */
@@ -116,7 +157,57 @@ void gdbmarglist_init (struct gdbmarglist *, struct gdbmarg *);
void gdbmarglist_add (struct gdbmarglist *, struct gdbmarg *);
void gdbmarglist_free (struct gdbmarglist *lst);
-struct gdbmarg *gdbmarg_new (char *);
-
+struct gdbmarg *gdbmarg_string (char *);
+struct gdbmarg *gdbmarg_datum (datum *);
+struct gdbmarg *gdbmarg_kvpair (struct kvpair *kvl);
+
+int gdbmarg_free (struct gdbmarg *arg);
+void gdbmarg_destroy (struct gdbmarg **parg);
+
int run_command (const char *verb, struct gdbmarglist *arglist);
+
+struct xdatum;
+void xd_expand (struct xdatum *xd, size_t size);
+void xd_store (struct xdatum *xd, void *val, size_t size);
+
+struct datadef
+{
+ char *name;
+ int size;
+ int (*format) (FILE *, void *ptr, int size);
+ int (*scan) (struct xdatum *xd, char *str);
+};
+
+struct datadef *datadef_locate (const char *name);
+
+struct field
+{
+ struct datadef *type;
+ int dim;
+ char *name;
+};
+
+#define FDEF_FLD 0
+#define FDEF_OFF 1
+#define FDEF_PAD 2
+
+struct dsegm
+{
+ struct dsegm *next;
+ int type;
+ union
+ {
+ int n;
+ struct field field;
+ } v;
+};
+
+struct dsegm *dsegm_new (int type);
+struct dsegm *dsegm_new_field (struct datadef *type, char *id, int dim);
+void dsegm_free_list (struct dsegm *dp);
+
+#define DS_KEY 0
+#define DS_CONTENT 1
+#define DS_MAX 2
+extern struct dsegm *dsdef[];
diff --git a/src/gram.y b/src/gram.y
index d9db0d7..c3324dc 100644
--- a/src/gram.y
+++ b/src/gram.y
@@ -19,18 +19,38 @@
#include <autoconf.h>
#include "gdbmtool.h"
+struct dsegm *dsdef[DS_MAX];
+
%}
%error-verbose
%locations
-%token <string> T_IDENT T_WORD
-%type <string> arg verb
+%token <type> T_TYPE
+%token T_OFF T_PAD T_DEF
+%token <num> T_NUM
+%token <string> T_IDENT T_WORD
+%type <string> string verb
+%type <arg> arg
%type <arglist> arglist arg1list
+%type <dsegm> def
+%type <dsegmlist> deflist
+%type <num> defid
+%type <kvpair> kvpair compound value
+%type <kvlist> kvlist
+%type <slist> slist
%union {
char *string;
+ struct kvpair *kvpair;
+ struct { struct kvpair *head, *tail; } kvlist;
+ struct { struct slist *head, *tail; } slist;
+ struct gdbmarg *arg;
struct gdbmarglist arglist;
+ int num;
+ struct datadef *type;
+ struct dsegm *dsegm;
+ struct { struct dsegm *head, *tail; } dsegmlist;
}
%%
@@ -50,7 +70,8 @@ stmt : /* empty */ '\n'
exit (EXIT_USAGE);
gdbmarglist_free (&$2);
}
- | error '\n'
+ | defn '\n'
+ | error { end_def(); } '\n'
{
if (interactive)
{
@@ -74,19 +95,140 @@ arglist : /* empty */
arg1list : arg
{
- gdbmarglist_init (&$$, gdbmarg_new ($1));
+ gdbmarglist_init (&$$, $1);
}
| arg1list arg
{
- gdbmarglist_add (&$1, gdbmarg_new ($2));
+ gdbmarglist_add (&$1, $2);
$$ = $1;
}
;
-arg : T_IDENT
+arg : string
+ {
+ $$ = gdbmarg_string ($1);
+ }
+ | compound
+ {
+ $$ = gdbmarg_kvpair ($1);
+ }
+ ;
+
+compound : '{' kvlist '}'
+ {
+ $$ = $2.head;
+ }
+ ;
+
+kvlist : kvpair
+ {
+ $$.head = $$.tail = $1;
+ }
+ | kvlist ',' kvpair
+ {
+ $1.tail->next = $3;
+ $1.tail = $3;
+ $$ = $1;
+ }
+ ;
+
+kvpair : value
+ | T_IDENT '=' value
+ {
+ $3->key = $1;
+ $$ = $3;
+ }
+ ;
+
+value : string
+ {
+ $$ = kvpair_string (&@1, $1);
+ }
+ | '{' slist '}'
+ {
+ $$ = kvpair_list (&@1, $2.head);
+ }
+ ;
+
+slist : string
+ {
+ $$.head = $$.tail = slist_new ($1);
+ }
+ | slist ',' string
+ {
+ struct slist *s = slist_new ($3);
+ $1.tail->next = s;
+ $1.tail = s;
+ $$ = $1;
+ }
+ ;
+
+string : T_IDENT
| T_WORD
+ | T_DEF
+ {
+ $$ = estrdup ("def");
+ }
+ ;
+
+defn : T_DEF defid { begin_def (); } '{' deflist optcomma '}'
+ {
+ end_def ();
+ dsegm_free_list (dsdef[$2]);
+ dsdef[$2] = $5.head;
+ }
+ ;
+
+optcomma : /* empty */
+ | ','
+ ;
+
+defid : T_IDENT
+ {
+ if (strcmp ($1, "key") == 0)
+ $$ = DS_KEY;
+ else if (strcmp ($1, "content") == 0)
+ $$ = DS_CONTENT;
+ else
+ {
+ syntax_error (_("expected \"key\" or \"content\", "
+ "but found \"%s\""), $1);
+ YYERROR;
+ }
+ }
;
+deflist : def
+ {
+ $$.head = $$.tail = $1;
+ }
+ | deflist ',' def
+ {
+ $1.tail->next = $3;
+ $1.tail = $3;
+ $$ = $1;
+ }
+ ;
+
+def : T_TYPE T_IDENT
+ {
+ $$ = dsegm_new_field ($1, $2, 1);
+ }
+ | T_TYPE T_IDENT '[' T_NUM ']'
+ {
+ $$ = dsegm_new_field ($1, $2, $4);
+ }
+ | T_OFF T_NUM
+ {
+ $$ = dsegm_new (FDEF_OFF);
+ $$->v.n = $2;
+ }
+ | T_PAD T_NUM
+ {
+ $$ = dsegm_new (FDEF_PAD);
+ $$->v.n = $2;
+ }
+ ;
%%
void
diff --git a/src/lex.l b/src/lex.l
index 7a8c99b..5644aa3 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -16,7 +16,6 @@
You should have received a copy of the GNU General Public License
along with GDBM. If not, see <http://www.gnu.org/licenses/>. */
-#include <autoconf.h>
#include "gdbmtool.h"
#include "gram.h"
@@ -62,9 +61,14 @@ static ssize_t read_input (char *buf, size_t size);
%}
%x STR
+%s DEF
WS [ \t][ \t]*
-IDENT [a-zA-Z_][a-zA-Z_0-9]*
+IDENT [a-zA-Z_][a-zA-Z_0-9-]*
+N [0-9][0-9]*
+P [1-9][0-9]*
+X [0-9a-fA-F]
+O [0-7]
%%
^[ \t]*#[ \t]*line[ \t].*\n {
@@ -75,6 +79,10 @@ IDENT [a-zA-Z_][a-zA-Z_0-9]*
for (p = strchr (yytext, '#') + 1; *p == ' ' || *p == '\t'; p++);
p += 4;
for (; *p == ' ' || *p == '\t'; p++);
+
+ line = strtol (p, &p, 10);
+ for (; *p == ' ' || *p == '\t'; p++);
+
if (*p == '"')
{
p++;
@@ -89,22 +97,40 @@ IDENT [a-zA-Z_][a-zA-Z_0-9]*
file[len] = 0;
for (p += len + 1; *p == ' ' || *p == '\t'; p++);
}
- line = strtol (p, &q, 10);
- if (*q && *q != ' ')
+ if (*p != '\n' )
{
yyerror (_("invalid #line statement"));
free (file);
REJECT;
}
- point.file = file;
+ if (file)
+ point.file = file;
point.line = line;
point.col = 0;
}
#.*\n advance_line ();
#.* /* end-of-file comment */;
-{IDENT} { yylval.string = estrdup (yytext); return T_IDENT; }
-[^ \t\n{},=]+ { yylval.string = estrdup (yytext); return T_WORD; }
+def { return T_DEF; }
+<DEF>off { return T_OFF; }
+<DEF>pad { return T_PAD; }
+<DEF>0[xX]{X}{X}* { yylval.num = strtoul (yytext, NULL, 16);
+ return T_NUM; };
+<DEF>0{O}{O}* { yylval.num = strtoul (yytext, NULL, 8);
+ return T_NUM; };
+<DEF>0|{P} { yylval.num = strtoul (yytext, NULL, 10);
+ return T_NUM; };
+
+{IDENT} { if (YYSTATE == DEF &&
+ (yylval.type = datadef_locate (yytext)))
+ return T_TYPE;
+ else
+ {
+ yylval.string = estrdup (yytext);
+ return T_IDENT;
+ }
+ }
+[^ \t\n\[\]{},=]+ { yylval.string = estrdup (yytext); return T_WORD; }
\"[^\\\"\n]*\" { yylval.string = emalloc (yyleng - 1);
memcpy (yylval.string, yytext+1, yyleng-2);
yylval.string[yyleng-2] = 0;
@@ -112,16 +138,16 @@ IDENT [a-zA-Z_][a-zA-Z_0-9]*
\"[^\\\"\n]*\\. { string_begin ();
string_add (yytext + 1, yyleng - 3);
string_addc (unescape (yytext[yyleng-1]));
- BEGIN(STR); }
+ BEGIN (STR); }
<STR>[^\\\"\n]*\" { if (yyleng > 1)
string_add (yytext, yyleng - 1);
yylval.string = string_end ();
- BEGIN(INITIAL);
+ BEGIN (INITIAL);
return T_WORD; }
<STR>[^\\\"\n]*\\. { string_add (yytext, yyleng - 2);
string_addc (unescape (yytext[yyleng-1])); }
{WS} ;
-\n { advance_line (); return '\n'; }
+\n { advance_line (); if (YYSTATE == INITIAL) return '\n'; }
. return yytext[0];
%%
@@ -140,6 +166,18 @@ yywrap ()
return 1;
}
+void
+begin_def (void)
+{
+ BEGIN (DEF);
+}
+
+void
+end_def (void)
+{
+ BEGIN (INITIAL);
+}
+
static ssize_t
read_input (char *buf, size_t size)
{
@@ -226,10 +264,11 @@ string_end (void)
return ret;
}
+static char transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
+
int
unescape (int c)
{
- static char transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
char *p;
for (p = transtab; *p; p += 2)
@@ -240,6 +279,18 @@ unescape (int c)
return c;
}
+int
+escape (int c)
+{
+ char *p;
+ for (p = transtab + sizeof (transtab) - 2; p > transtab; p -= 2)
+ {
+ if (*p == c)
+ return p[-1];
+ }
+ return 0;
+}
+
void
vparse_error (struct locus *loc, const char *fmt, va_list ap)
{
diff --git a/tests/dtload.c b/tests/dtload.c
index 6ebd638..a02b36c 100644
--- a/tests/dtload.c
+++ b/tests/dtload.c
@@ -134,11 +134,12 @@ main (int argc, char **argv)
progname, line);
continue;
}
-
+ buf[j] = 0;
+
key.dptr = buf;
key.dsize = j + data_z;
- data.dptr = buf + j + 1;
- data.dsize = strlen (buf + j + 1) + data_z;
+ data.dptr = buf + i + 1;
+ data.dsize = strlen (data.dptr) + data_z;
if (store (key, data) != 0)
{
fprintf (stderr, "%s: %d: item not inserted\n",
diff --git a/tests/gtload.c b/tests/gtload.c
index b89ae1f..2920463 100644
--- a/tests/gtload.c
+++ b/tests/gtload.c
@@ -157,11 +157,12 @@ main (int argc, char **argv)
progname, line);
continue;
}
-
+ buf[j] = 0;
+
key.dptr = buf;
key.dsize = j + data_z;
- data.dptr = buf + j + 1;
- data.dsize = strlen (buf + j + 1) + data_z;
+ data.dptr = buf + i + 1;
+ data.dsize = strlen (data.dptr) + data_z;
if (gdbm_store (dbf, key, data, replace) != 0)
{
fprintf (stderr, "%s: %d: item not inserted\n",

Return to:

Send suggestions and report system problems to the System administrator.