aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-05-13 16:46:30 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2013-05-13 16:46:30 +0000
commitaa0eaa5bc642167db8cfb5778cf9a0091401a4f3 (patch)
treea5a6cbdc9ca61b6867bd902fc880efd2eaa0f29c
parent1638ed6202b77b521214128189dc4aacdb5fe098 (diff)
downloadgdbm-aa0eaa5bc642167db8cfb5778cf9a0091401a4f3.tar.gz
gdbm-aa0eaa5bc642167db8cfb5778cf9a0091401a4f3.tar.bz2
Implement shell variables in gdbmtool.
* src/var.c: New file. * src/datconv.c (datum_format): Remove the "delim" parameter, use "delim1" and "delim2" shell variables instead. * src/gdbmtool.c: Remove "prompt" command. Use "set ps[12]" instead. (print_prompt): Move to lex.l * src/gdbmtool.h (variable_set) (variable_get, variable_print_all): New protos. * src/gram.y: Handle the "set" command. * src/lex.l: Update.
-rw-r--r--ChangeLog17
-rw-r--r--src/Makefile.am3
-rw-r--r--src/datconv.c12
-rw-r--r--src/gdbmtool.c122
-rw-r--r--src/gdbmtool.h14
-rw-r--r--src/gram.y68
-rw-r--r--src/lex.l107
-rw-r--r--src/var.c148
8 files changed, 371 insertions, 120 deletions
diff --git a/ChangeLog b/ChangeLog
index 42a7a71..b650759 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2013-05-13 Sergey Poznyakoff <gray@gnu.org.ua>
+ Implement shell variables in gdbmtool.
+
+ * src/var.c: New file.
+ * src/Makefile.am: Add var.c
+ * src/datconv.c (datum_format): Remove the "delim"
+ parameter, use "delim1" and "delim2" shell variables
+ instead.
+ * src/gdbmtool.c: Remove "prompt" command. Use "set ps[12]"
+ instead.
+ (print_prompt): Move to lex.l
+ * src/gdbmtool.h (variable_set)
+ (variable_get, variable_print_all): New protos.
+ * src/gram.y: Handle the "set" command.
+ * src/lex.l: Update.
+
+2013-05-13 Sergey Poznyakoff <gray@gnu.org.ua>
+
Handle structured key and content data in gdbmtool.
* src/datconv.c: New file.
diff --git a/src/Makefile.am b/src/Makefile.am
index 795832d..832fd55 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -84,7 +84,8 @@ gdbmtool_SOURCES = \
gram.y\
lex.l\
gdbmtool.h\
- gdbmtool.c
+ gdbmtool.c\
+ var.c
AM_YFLAGS = -dtv
#AM_LFLAGS = -d
diff --git a/src/datconv.c b/src/datconv.c
index 2ef64a6..10a1406 100644
--- a/src/datconv.c
+++ b/src/datconv.c
@@ -207,15 +207,21 @@ dsegm_free_list (struct dsegm *dp)
}
void
-datum_format (FILE *fp, datum const *dat, struct dsegm *ds, char *delim)
+datum_format (FILE *fp, datum const *dat, struct dsegm *ds)
{
int off = 0;
+ char *delim[2];
if (!ds)
{
fprintf (fp, "%.*s\n", dat->dsize, dat->dptr);
return;
}
+
+ if (variable_get ("delim1", VART_STRING, (void*) &delim[0]))
+ abort ();
+ if (variable_get ("delim2", VART_STRING, (void*) &delim[1]))
+ abort ();
for (; ds && off <= dat->dsize; ds = ds->next)
{
@@ -233,7 +239,7 @@ datum_format (FILE *fp, datum const *dat, struct dsegm *ds, char *delim)
for (i = 0; i < ds->v.field.dim; i++)
{
if (i)
- fwrite (delim, strlen (delim), 1, fp);
+ fwrite (delim[0], strlen (delim[0]), 1, fp);
if (off + ds->v.field.type->size > dat->dsize)
{
fprintf (fp, _("(not enough data)"));
@@ -253,7 +259,7 @@ datum_format (FILE *fp, datum const *dat, struct dsegm *ds, char *delim)
}
if (ds->v.field.dim > 1)
fprintf (fp, " }");
- fwrite (delim, strlen (delim), 1, fp);
+ fwrite (delim[1], strlen (delim[1]), 1, fp);
break;
case FDEF_OFF:
diff --git a/src/gdbmtool.c b/src/gdbmtool.c
index 78ffb6e..48dd986 100644
--- a/src/gdbmtool.c
+++ b/src/gdbmtool.c
@@ -30,9 +30,6 @@
# include <locale.h>
#endif
-#define DEFAULT_PROMPT "%p>%_"
-char *prompt;
-
char *file_name = NULL; /* Database file name */
GDBM_FILE gdbm_file = NULL; /* Database to operate upon */
int interactive; /* Are we running in interactive mode? */
@@ -371,7 +368,7 @@ fetch_handler (struct handler_param *param)
return_data = gdbm_fetch (gdbm_file, param->argv[0]->v.dat);
if (return_data.dptr != NULL)
{
- datum_format (param->fp, &return_data, dsdef[DS_CONTENT], ",");
+ datum_format (param->fp, &return_data, dsdef[DS_CONTENT]);
fputc ('\n', param->fp);
free (return_data.dptr);
}
@@ -399,11 +396,11 @@ firstkey_handler (struct handler_param *param)
key_data = gdbm_firstkey (gdbm_file);
if (key_data.dptr != NULL)
{
- datum_format (param->fp, &key_data, dsdef[DS_KEY], ",");
+ datum_format (param->fp, &key_data, dsdef[DS_KEY]);
fputc ('\n', param->fp);
return_data = gdbm_fetch (gdbm_file, key_data);
- datum_format (param->fp, &return_data, dsdef[DS_CONTENT], ",");
+ datum_format (param->fp, &return_data, dsdef[DS_CONTENT]);
fputc ('\n', param->fp);
free (return_data.dptr);
@@ -428,11 +425,11 @@ nextkey_handler (struct handler_param *param)
if (return_data.dptr != NULL)
{
key_data = return_data;
- datum_format (param->fp, &key_data, dsdef[DS_KEY], ",");
+ datum_format (param->fp, &key_data, dsdef[DS_KEY]);
fputc ('\n', param->fp);
return_data = gdbm_fetch (gdbm_file, key_data);
- datum_format (param->fp, &return_data, dsdef[DS_CONTENT], ",");
+ datum_format (param->fp, &return_data, dsdef[DS_CONTENT]);
fputc ('\n', param->fp);
free (return_data.dptr);
@@ -655,9 +652,9 @@ list_handler (struct handler_param *param)
terror (0, _("cannot fetch data (key %.*s)"), key.dsize, key.dptr);
else
{
- datum_format (param->fp, &key, dsdef[DS_KEY], ",");
+ datum_format (param->fp, &key, dsdef[DS_KEY]);
fputc (' ', param->fp);
- datum_format (param->fp, &data, dsdef[DS_CONTENT], ",");
+ datum_format (param->fp, &data, dsdef[DS_CONTENT]);
fputc ('\n', param->fp);
free (data.dptr);
}
@@ -764,105 +761,6 @@ status_handler (struct handler_param *param)
fprintf (param->fp, _("Database file: %s\n"), file_name);
}
-struct prompt_exp;
-
-void
-pe_file_name (struct prompt_exp *p)
-{
- fwrite (file_name, strlen (file_name), 1, stdout);
-}
-
-void
-pe_program_name (struct prompt_exp *p)
-{
- fwrite (progname, strlen (progname), 1, stdout);
-}
-
-void
-pe_package_name (struct prompt_exp *p)
-{
- fwrite (PACKAGE_NAME, sizeof (PACKAGE_NAME) - 1, 1, stdout);
-}
-
-void
-pe_program_version (struct prompt_exp *p)
-{
- fwrite (PACKAGE_VERSION, sizeof (PACKAGE_VERSION) - 1, 1, stdout);
-}
-
-void
-pe_space (struct prompt_exp *p)
-{
- fwrite (" ", 1, 1, stdout);
-}
-
-struct prompt_exp
-{
- int ch;
- void (*fun) (struct prompt_exp *);
- char *cache;
-};
-
-struct prompt_exp prompt_exp[] = {
- { 'f', pe_file_name },
- { 'p', pe_program_name },
- { 'P', pe_package_name },
- { 'v', pe_program_version },
- { '_', pe_space },
- { 0 }
-};
-
-static void
-expand_char (int c)
-{
- struct prompt_exp *p;
-
- if (c && c != '%')
- {
- for (p = prompt_exp; p->ch; p++)
- {
- if (c == p->ch)
- {
- if (p->cache)
- free (p->cache);
- return p->fun (p);
- }
- }
- }
- putchar ('%');
- putchar (c);
-}
-
-void
-print_prompt ()
-{
- char *s;
-
- for (s = prompt; *s; s++)
- {
- if (*s == '%')
- {
- if (!*++s)
- {
- putchar ('%');
- break;
- }
- expand_char (*s);
- }
- else
- putchar (*s);
- }
-
- fflush (stdout);
-}
-
-void
-prompt_handler (struct handler_param *param)
-{
- free (prompt);
- 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);
@@ -972,10 +870,6 @@ struct command command_tab[] = {
{ S(help),
help_begin, help_handler, NULL,
{ { NULL } }, N_("print this help list") },
- { S(prompt),
- NULL, prompt_handler, NULL,
- { { N_("text"), ARG_STRING },
- { NULL } }, N_("set command prompt") },
{ S(quit),
NULL, quit_handler, NULL,
{ { NULL } }, N_("quit the program") },
@@ -1569,8 +1463,6 @@ main (int argc, char *argv[])
/* Welcome message. */
if (interactive && !quiet_option)
printf (_("\nWelcome to the gdbm tool. Type ? for help.\n\n"));
- if (interactive)
- prompt = estrdup (DEFAULT_PROMPT);
memset (&param, 0, sizeof (param));
argmax = 0;
diff --git a/src/gdbmtool.h b/src/gdbmtool.h
index 64335eb..98c6758 100644
--- a/src/gdbmtool.h
+++ b/src/gdbmtool.h
@@ -97,6 +97,7 @@ void print_prompt (void);
void setsource (const char *filename, FILE *file);
+extern char *file_name;
extern int interactive;
struct slist
@@ -211,3 +212,16 @@ void dsegm_free_list (struct dsegm *dp);
#define DS_MAX 2
extern struct dsegm *dsdef[];
+
+#define VART_STRING 0
+#define VART_BOOL 1
+
+#define VAR_OK 0
+#define VAR_ERR_NOTDEF 1
+#define VAR_ERR_BADTYPE 2
+
+int variable_set (const char *name, int type, void *val);
+int variable_get (const char *name, int type, void **val);
+void variable_print_all (FILE *fp);
+
+
diff --git a/src/gram.y b/src/gram.y
index c3324dc..810eba3 100644
--- a/src/gram.y
+++ b/src/gram.y
@@ -27,7 +27,7 @@ struct dsegm *dsdef[DS_MAX];
%locations
%token <type> T_TYPE
-%token T_OFF T_PAD T_DEF
+%token T_OFF T_PAD T_DEF T_SET
%token <num> T_NUM
%token <string> T_IDENT T_WORD
%type <string> string verb
@@ -70,6 +70,7 @@ stmt : /* empty */ '\n'
exit (EXIT_USAGE);
gdbmarglist_free (&$2);
}
+ | set '\n'
| defn '\n'
| error { end_def(); } '\n'
{
@@ -169,6 +170,10 @@ string : T_IDENT
{
$$ = estrdup ("def");
}
+ | T_SET
+ {
+ $$ = estrdup ("set");
+ }
;
defn : T_DEF defid { begin_def (); } '{' deflist optcomma '}'
@@ -229,6 +234,67 @@ def : T_TYPE T_IDENT
$$->v.n = $2;
}
;
+
+set : T_SET
+ {
+ variable_print_all (stdout);
+ }
+ | T_SET varlist
+ ;
+
+varlist : var
+ | varlist var
+ ;
+
+var : T_IDENT
+ {
+ int t = 1;
+ int rc;
+ char *varname = $1;
+
+ rc = variable_set (varname, VART_BOOL, &t);
+ if (rc == VAR_ERR_NOTDEF && strncmp (varname, "no", 2) == 0)
+ {
+ t = 0;
+ varname += 2;
+ rc = variable_set (varname, VART_BOOL, &t);
+ }
+
+ switch (rc)
+ {
+ case VAR_OK:
+ break;
+
+ case VAR_ERR_NOTDEF:
+ parse_error (&@1, _("no such variable: %s"), varname);
+ break;
+
+ case VAR_ERR_BADTYPE:
+ parse_error (&@1, _("%s is not a boolean variable"), varname);
+ break;
+ }
+ free($1);
+ }
+ | T_IDENT '=' string
+ {
+ int rc = variable_set ($1, VART_STRING, $3);
+ free ($3);
+ switch (rc)
+ {
+ case VAR_OK:
+ break;
+
+ case VAR_ERR_NOTDEF:
+ parse_error (&@1, _("no such variable: %s"), $1);
+ break;
+
+ case VAR_ERR_BADTYPE:
+ parse_error (&@1, _("%s is not a string variable"), $1);
+ break;
+ }
+ free($1);
+ }
+ ;
%%
void
diff --git a/src/lex.l b/src/lex.l
index 5644aa3..09b5e36 100644
--- a/src/lex.l
+++ b/src/lex.l
@@ -112,6 +112,7 @@ O [0-7]
#.* /* end-of-file comment */;
def { return T_DEF; }
+set { return T_SET; }
<DEF>off { return T_OFF; }
<DEF>pad { return T_PAD; }
<DEF>0[xX]{X}{X}* { yylval.num = strtoul (yytext, NULL, 16);
@@ -312,3 +313,109 @@ parse_error (struct locus *loc, const char *fmt, ...)
vparse_error (loc, fmt, ap);
va_end (ap);
}
+
+
+struct prompt_exp;
+
+void
+pe_file_name (struct prompt_exp *p)
+{
+ fwrite (file_name, strlen (file_name), 1, stdout);
+}
+
+void
+pe_program_name (struct prompt_exp *p)
+{
+ fwrite (progname, strlen (progname), 1, stdout);
+}
+
+void
+pe_package_name (struct prompt_exp *p)
+{
+ fwrite (PACKAGE_NAME, sizeof (PACKAGE_NAME) - 1, 1, stdout);
+}
+
+void
+pe_program_version (struct prompt_exp *p)
+{
+ fwrite (PACKAGE_VERSION, sizeof (PACKAGE_VERSION) - 1, 1, stdout);
+}
+
+void
+pe_space (struct prompt_exp *p)
+{
+ fwrite (" ", 1, 1, stdout);
+}
+
+struct prompt_exp
+{
+ int ch;
+ void (*fun) (struct prompt_exp *);
+ char *cache;
+};
+
+struct prompt_exp prompt_exp[] = {
+ { 'f', pe_file_name },
+ { 'p', pe_program_name },
+ { 'P', pe_package_name },
+ { 'v', pe_program_version },
+ { '_', pe_space },
+ { 0 }
+};
+
+static void
+expand_char (int c)
+{
+ struct prompt_exp *p;
+
+ if (c && c != '%')
+ {
+ for (p = prompt_exp; p->ch; p++)
+ {
+ if (c == p->ch)
+ {
+ if (p->cache)
+ free (p->cache);
+ return p->fun (p);
+ }
+ }
+ }
+ putchar ('%');
+ putchar (c);
+}
+
+char const *
+psname ()
+{
+ if (YYSTATE == DEF)
+ return "ps2";
+ return "ps1";
+}
+
+void
+print_prompt ()
+{
+ const char *s;
+ const char *prompt;
+
+ if (variable_get (psname (), VART_STRING, (void *) &prompt))
+ abort ();
+
+ for (s = prompt; *s; s++)
+ {
+ if (*s == '%')
+ {
+ if (!*++s)
+ {
+ putchar ('%');
+ break;
+ }
+ expand_char (*s);
+ }
+ else
+ putchar (*s);
+ }
+
+ fflush (stdout);
+}
+
diff --git a/src/var.c b/src/var.c
new file mode 100644
index 0000000..4a0ea60
--- /dev/null
+++ b/src/var.c
@@ -0,0 +1,148 @@
+/* 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 VARF_DFL 0x00
+#define VARF_SET 0x01
+
+struct variable
+{
+ char *name;
+ int type;
+ int flags;
+ union
+ {
+ char *string;
+ int bool;
+ } v;
+};
+
+static struct variable vartab[] = {
+ /* Top-level prompt */
+ { "ps1", VART_STRING, VARF_DFL, { "%p>%_" } },
+ /* Second-level prompt (used within "def" block) */
+ { "ps2", VART_STRING, VARF_DFL, { "%_>%_" } },
+ /* This delimits array members */
+ { "delim1", VART_STRING, VARF_DFL, { "," } },
+ /* This delimits structure members */
+ { "delim2", VART_STRING, VARF_DFL, { "," } },
+ { NULL }
+};
+
+static struct variable *
+varfind (const char *name)
+{
+ struct variable *vp;
+
+ for (vp = vartab; vp->name; vp++)
+ if (strcmp (vp->name, name) == 0)
+ return vp;
+
+ return NULL;
+}
+
+int
+variable_set (const char *name, int type, void *val)
+{
+ struct variable *vp = varfind (name);
+
+ if (!vp)
+ return VAR_ERR_NOTDEF;
+
+ 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;
+ }
+
+ vp->flags |= VARF_SET;
+
+ return VAR_OK;
+}
+
+int
+variable_get (const char *name, int type, void **val)
+{
+ struct variable *vp = varfind (name);
+
+ if (!vp)
+ return VAR_ERR_NOTDEF;
+
+ if (type != vp->type)
+ return VAR_ERR_BADTYPE;
+
+ switch (vp->type)
+ {
+ case VART_STRING:
+ *val = vp->v.string;
+ break;
+
+ case VART_BOOL:
+ *(int*)val = vp->v.bool;
+ break;
+ }
+
+ return VAR_OK;
+}
+
+void
+variable_print_all (FILE *fp)
+{
+ struct variable *vp;
+ char *s;
+
+ for (vp = vartab; vp->name; vp++)
+ {
+ switch (vp->type)
+ {
+ case VART_BOOL:
+ fprintf (fp, "%s%s", vp->v.bool ? "no" : "", vp->name);
+ break;
+
+ case VART_STRING:
+ fprintf (fp, "%s=\"", vp->name);
+ for (s = vp->v.string; *s; s++)
+ {
+ int c;
+
+ if (isprint (*s))
+ fputc (*s, fp);
+ else if ((c = escape (*s)))
+ fprintf (fp, "\\%c", c);
+ else
+ fprintf (fp, "\\%03o", *s);
+ }
+ fprintf (fp, "\"");
+ }
+ fputc ('\n', fp);
+ }
+}
+

Return to:

Send suggestions and report system problems to the System administrator.