diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-05-13 16:46:30 +0000 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2013-05-13 16:46:30 +0000 |
commit | aa0eaa5bc642167db8cfb5778cf9a0091401a4f3 (patch) | |
tree | a5a6cbdc9ca61b6867bd902fc880efd2eaa0f29c /src | |
parent | 1638ed6202b77b521214128189dc4aacdb5fe098 (diff) | |
download | gdbm-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.
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 3 | ||||
-rw-r--r-- | src/datconv.c | 12 | ||||
-rw-r--r-- | src/gdbmtool.c | 122 | ||||
-rw-r--r-- | src/gdbmtool.h | 14 | ||||
-rw-r--r-- | src/gram.y | 68 | ||||
-rw-r--r-- | src/lex.l | 107 | ||||
-rw-r--r-- | src/var.c | 148 |
7 files changed, 354 insertions, 120 deletions
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 (¶m, 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); + + @@ -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 @@ -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); + } +} + |