aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2013-05-11 05:01:49 +0000
committerSergey Poznyakoff <gray@gnu.org.ua>2013-05-11 05:01:49 +0000
commit4785154fda6411a384a4ead5abb18c22bb77a8f0 (patch)
treea066bdac8c98434cb3b0edaf13ee4f48769117b9
parent19f30b06d3dacb1ab87ebc654411ea84e6123d08 (diff)
downloadgdbm-4785154fda6411a384a4ead5abb18c22bb77a8f0.tar.gz
gdbm-4785154fda6411a384a4ead5abb18c22bb77a8f0.tar.bz2
Rewrite gdbmtool parser.
* src/testgdbm.c: Remove. * src/gdbmtool.c: New file. * src/gdbmtool.h: New file. * src/gram.y: New file. * src/lex.l: New file. * src/Makefile.am: Update.
-rw-r--r--ChangeLog11
-rw-r--r--configure.ac4
-rw-r--r--src/.cvsignore4
-rw-r--r--src/Makefile.am11
-rw-r--r--src/gdbmtool.c (renamed from src/testgdbm.c)384
-rw-r--r--src/gdbmtool.h122
-rw-r--r--src/gram.y107
-rw-r--r--src/lex.l263
8 files changed, 705 insertions, 201 deletions
diff --git a/ChangeLog b/ChangeLog
index 9740d9c..1fb7809 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2013-05-11 Sergey Poznyakoff <gray@gnu.org.ua>
+
+ Rewrite gdbmtool parser.
+
+ * src/testgdbm.c: Remove.
+ * src/gdbmtool.c: New file.
+ * src/gdbmtool.h: New file.
+ * src/gram.y: New file.
+ * src/lex.l: New file.
+ * src/Makefile.am: Update.
+
2013-05-09 Sergey Poznyakoff <gray@gnu.org.ua>
Add new prompt escapes.
diff --git a/configure.ac b/configure.ac
index ce00344..f2a37e5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -84,8 +84,8 @@ AC_PROG_CPP
AC_PROG_INSTALL
AC_PROG_LIBTOOL
AC_SYS_LARGEFILE
-dnl AC_PROG_RANLIB
-dnl AC_C_BIGENDIAN([])
+AC_PROG_YACC
+AC_PROG_LEX
AC_C_CONST
dnl Internationalization macros.
diff --git a/src/.cvsignore b/src/.cvsignore
index 70e7a26..bc1099e 100644
--- a/src/.cvsignore
+++ b/src/.cvsignore
@@ -6,7 +6,9 @@ Makefile.in
gdbm.h
*.lo
libgdbm.la
-testgdbm
gdbmtool
gdbm_dump
gdbm_load
+gram.[ch]
+gram.output
+lex.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 7b1a2d2..d5561ea 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -77,7 +77,16 @@ libgdbmapp_a_SOURCES =\
# Programs
bin_PROGRAMS = gdbmtool gdbm_load gdbm_dump
+
gdbmtool_LDADD = ./libgdbmapp.a ./libgdbm.la
-gdbmtool_SOURCES = testgdbm.c
+gdbmtool_SOURCES = \
+ gram.y\
+ lex.l\
+ gdbmtool.h\
+ gdbmtool.c
+
+AM_YFLAGS = -dtv
+#AM_LFLAGS = -d
+
gdbm_load_LDADD = ./libgdbmapp.a ./libgdbm.la
gdbm_dump_LDADD = ./libgdbmapp.a ./libgdbm.la
diff --git a/src/testgdbm.c b/src/gdbmtool.c
index 5214526..82da808 100644
--- a/src/testgdbm.c
+++ b/src/gdbmtool.c
@@ -15,12 +15,8 @@
You should have received a copy of the GNU General Public License
along with GDBM. If not, see <http://www.gnu.org/licenses/>. */
-/* Include system configuration before all else. */
-#include "autoconf.h"
-
-#include "gdbmdefs.h"
+#include "gdbmtool.h"
#include "gdbm.h"
-#include "gdbmapp.h"
#include <errno.h>
#include <ctype.h>
@@ -34,8 +30,6 @@
# include <locale.h>
#endif
-const char *progname; /* Program name */
-
#define DEFAULT_PROMPT "%p>%_"
char *prompt;
@@ -67,22 +61,6 @@ terror (int code, const char *fmt, ...)
exit (code);
}
-void
-syntax_error (const char *fmt, ...)
-{
- va_list ap;
- if (!interactive)
- fprintf (stderr, "%s: ", progname);
- fprintf (stderr, "%u: ", input_line);
- va_start (ap, fmt);
- vfprintf (stderr, fmt, ap);
- va_end (ap);
- fputc ('\n', stderr);
- if (!interactive)
- exit (EXIT_USAGE);
-}
-
-
size_t
bucket_print_lines (hash_bucket *bucket)
@@ -870,7 +848,7 @@ expand_char (int c)
}
void
-outprompt ()
+print_prompt ()
{
char *s;
@@ -906,7 +884,6 @@ struct command
{
char *name; /* Command name */
size_t len; /* Name length */
- int abbrev; /* Single-letter shortkey (optional) */
int (*begin) (struct handler_param *param, size_t *);
void (*handler) (struct handler_param *param);
void (*end) (void *data);
@@ -917,81 +894,81 @@ struct command
struct command command_tab[] = {
#define S(s) #s, sizeof (#s) - 1
- { S(count), 'c',
+ { S(count),
NULL, count_handler, NULL,
{ NULL, NULL, }, N_("count (number of entries)") },
- { S(delete), 'd',
+ { S(delete),
NULL, delete_handler, NULL,
{ N_("key"), NULL, }, N_("delete") },
- { S(export), 'e',
+ { S(export),
NULL, export_handler, NULL,
{ N_("file"), "[truncate]", "[binary|ascii]" }, N_("export") },
- { S(fetch), 'f',
+ { S(fetch),
NULL, fetch_handler, NULL,
{ N_("key"), NULL }, N_("fetch") },
- { S(import), 'i',
+ { S(import),
NULL, import_handler, NULL,
{ N_("file"), "[replace]", "[nometa]" }, N_("import") },
- { S(list), 'l',
+ { S(list),
list_begin, list_handler, NULL,
{ NULL, NULL }, N_("list") },
- { S(next), 'n',
+ { S(next),
NULL, nextkey_handler, NULL,
{ N_("[key]"), NULL }, N_("nextkey") },
- { S(store), 's',
+ { S(store),
NULL, store_handler, NULL,
{ N_("key"), N_("data") }, N_("store") },
- { S(first), '1',
+ { S(first),
NULL, firstkey_handler, NULL,
{ NULL, NULL }, N_("firstkey") },
- { S(read), '<',
+ { S(read),
NULL, read_handler, NULL,
{ N_("file"), "[replace]" },
N_("read entries from file and store") },
- { S(reorganize), 'r',
+ { S(reorganize),
NULL, reorganize_handler, NULL,
{ NULL, NULL, }, N_("reorganize") },
- { S(key-zero), 'z',
+ { S(key-zero),
NULL, key_z_handler, NULL,
{ NULL, NULL }, N_("toggle key nul-termination") },
- { S(avail), 'A',
+ { S(avail),
avail_begin, avail_handler, NULL,
{ NULL, NULL, }, N_("print avail list") },
- { S(bucket), 'B',
+ { S(bucket),
print_bucket_begin, print_current_bucket_handler, NULL,
{ N_("bucket-number"), NULL, }, N_("print a bucket") },
- { S(current), 'C',
+ { S(current),
print_current_bucket_begin, print_current_bucket_handler, NULL,
{ NULL, NULL, },
N_("print current bucket") },
- { S(dir), 'D',
+ { S(dir),
print_dir_begin, print_dir_handler, NULL,
{ NULL, NULL, }, N_("print hash directory") },
- { S(header), 'F',
+ { S(header),
print_header_begin , print_header_handler, NULL,
{ NULL, NULL, }, N_("print file header") },
- { S(hash), 'H',
+ { S(hash),
NULL, hash_handler, NULL,
{ N_("key"), NULL, }, N_("hash value of key") },
- { S(cache), 'K',
+ { S(cache),
print_cache_begin, print_cache_handler, NULL,
{ NULL, NULL, }, N_("print the bucket cache") },
- { S(status), 'S',
+ { S(status),
NULL, status_handler, NULL,
{ NULL, NULL }, N_("print current program status") },
- { S(version), 'v',
+ { S(version),
NULL, print_version_handler, NULL,
{ NULL, NULL, }, N_("print version of gdbm") },
- { S(data-zero), 'Z',
+ { S(data-zero),
NULL, data_z_handler, NULL,
{ NULL, NULL }, N_("toggle data nul-termination") },
- { S(help), '?',
+ { S(help),
help_begin, help_handler, NULL,
{ NULL, NULL, }, N_("print this help list") },
- { S(prompt), 0,
+ { S(prompt),
NULL, prompt_handler, NULL,
{ N_("text") }, N_("set command prompt") },
- { S(quit), 'q',
+ { S(quit),
NULL, quit_handler, NULL,
{ NULL, NULL, }, N_("quit the program") },
#undef S
@@ -1036,12 +1013,7 @@ help_handler (struct handler_param *param)
int i;
int n;
- if (cmd->abbrev)
- n = fprintf (fp, " %c, ", cmd->abbrev);
- else
- n = fprintf (fp, " ");
-
- n += fprintf (fp, "%s", cmd->name);
+ n = fprintf (fp, " %s", cmd->name);
for (i = 0; i < NARGS && cmd->args[i]; i++)
n += fprintf (fp, " %s", gettext (cmd->args[i]));
@@ -1054,19 +1026,12 @@ help_handler (struct handler_param *param)
}
struct command *
-find_command (char *str)
+find_command (const char *str)
{
enum { fcom_init, fcom_found, fcom_ambig, fcom_abort } state = fcom_init;
struct command *cmd, *found = NULL;
size_t len = strlen (str);
- if (len == 1)
- {
- for (cmd = command_tab; cmd->name; cmd++)
- if (cmd->abbrev == *str)
- return cmd;
- }
-
for (cmd = command_tab; state != fcom_abort && cmd->name; cmd++)
{
if (memcmp (cmd->name, str, len < cmd->len ? len : cmd->len) == 0)
@@ -1097,30 +1062,11 @@ find_command (char *str)
}
if (state == fcom_init)
- terror (0, interactive ? _("Invalid command. Try ? for help.") :
- _("Unknown command"));
+ syntax_error (interactive ? _("Invalid command. Try ? for help.") :
+ _("Unknown command"));
return found;
}
-
-#define SKIPWS(p) while (*(p) && isspace (*(p))) (p)++
-#define SKIPWORD(p) while (*(p) && !isspace (*(p))) (p)++
-
-char *
-getword (char *s, char **endp)
-{
- char *p;
- SKIPWS (s);
- p = s;
- SKIPWORD (s);
- if (*s)
- {
- *s++ = 0;
- SKIPWS (s);
- }
- *endp = s;
- return p;
-}
-
+
char *parseopt_program_doc = N_("examine and/or modify a GDBM database");
char *parseopt_program_args = N_("DBFILE");
@@ -1139,6 +1085,156 @@ struct gdbm_option optab[] = {
#define ARGINC 16
+
+void
+gdbmarglist_init (struct gdbmarglist *lst, struct gdbmarg *arg)
+{
+ if (arg)
+ arg->next = NULL;
+ lst->head = lst->tail = arg;
+}
+
+void
+gdbmarglist_add (struct gdbmarglist *lst, struct gdbmarg *arg)
+{
+ arg->next = NULL;
+ if (lst->tail)
+ lst->tail->next = arg;
+ else
+ lst->head = arg;
+ lst->tail = arg;
+}
+
+void
+gdbmarglist_free (struct gdbmarglist *lst)
+{
+ struct gdbmarg *arg;
+
+ for (arg = lst->head; arg; )
+ {
+ struct gdbmarg *next = arg->next;
+ free (arg->string);
+ free (arg);
+ arg = next;
+ }
+}
+
+struct gdbmarg *
+gdbmarg_new (char *string)
+{
+ struct gdbmarg *arg = emalloc (sizeof (*arg));
+ arg->next = NULL;
+ arg->string = string;
+ return arg;
+}
+
+
+struct handler_param param;
+size_t argmax;
+
+int
+run_command (const char *verb, struct gdbmarglist *arglist)
+{
+ int i;
+ struct command *cmd;
+ struct gdbmarg *arg;
+ char *pager = getenv ("PAGER");
+ char argbuf[128];
+ size_t expected_lines, *expected_lines_ptr;
+ FILE *pagfp = NULL;
+
+ cmd = find_command (verb);
+ if (!cmd)
+ return 1;
+
+ arg = arglist ? arglist->head : NULL;
+
+ for (i = 0; cmd->args[i] && arg; i++, arg = arg->next)
+ {
+ if (i >= argmax)
+ {
+ argmax += ARGINC;
+ param.argv = erealloc (param.argv,
+ sizeof (param.argv[0]) * argmax);
+ }
+ param.argv[i] = estrdup (arg->string);
+ }
+
+ for (; cmd->args[i]; i++)
+ {
+ char *argname = cmd->args[i];
+ if (*argname == '[')
+ /* Optional argument */
+ break;
+ if (!interactive)
+ {
+ syntax_error (_("%s: not enough arguments"), cmd->name);
+ return 1;
+ }
+ printf ("%s? ", argname);
+ fflush (stdout);
+ if (fgets (argbuf, sizeof argbuf, stdin) == NULL)
+ terror (EXIT_USAGE, _("unexpected eof"));
+
+ trimnl (argbuf);
+ if (i >= argmax)
+ {
+ argmax += ARGINC;
+ param.argv = erealloc (param.argv,
+ sizeof (param.argv[0]) * argmax);
+ }
+ param.argv[i] = estrdup (argbuf);
+ }
+
+ if (arg)
+ {
+ syntax_error (_("%s: too many arguments"), cmd->name);
+ return 1;
+ }
+
+ /* Prepare for calling the handler */
+ param.argc = i;
+ param.fp = NULL;
+ param.data = NULL;
+ pagfp = NULL;
+
+ expected_lines = 0;
+ expected_lines_ptr = (interactive && pager) ? &expected_lines : NULL;
+ if (!(cmd->begin && cmd->begin (&param, expected_lines_ptr)))
+ {
+ if (pager && expected_lines > get_screen_lines ())
+ {
+ pagfp = popen (pager, "w");
+ if (pagfp)
+ param.fp = pagfp;
+ else
+ {
+ terror (0, _("cannot run pager `%s': %s"), pager,
+ strerror (errno));
+ pager = NULL;
+ param.fp = stdout;
+ }
+ }
+ else
+ param.fp = stdout;
+
+ cmd->handler (&param);
+ if (cmd->end)
+ cmd->end (param.data);
+ else if (param.data)
+ free (param.data);
+
+ if (pagfp)
+ pclose (pagfp);
+ }
+
+ for (i = 0; i < param.argc; i++)
+ free (param.argv[i]);
+ param.argc = 0;
+
+ return 0;
+}
+
int
main (int argc, char *argv[])
{
@@ -1151,11 +1247,7 @@ main (int argc, char *argv[])
char reader = FALSE;
char newdb = FALSE;
int flags = 0;
- char *pager = getenv ("PAGER");
- struct handler_param param;
- size_t argmax;
-
set_progname (argv[0]);
#ifdef HAVE_SETLOCALE
@@ -1263,115 +1355,13 @@ main (int argc, char *argv[])
printf (_("\nWelcome to the gdbm tool. Type ? for help.\n\n"));
if (interactive)
prompt = estrdup (DEFAULT_PROMPT);
-
+
memset (&param, 0, sizeof (param));
argmax = 0;
-
- while (1)
- {
- int i;
- char *p, *sp;
- char argbuf[128];
- struct command *cmd;
- size_t expected_lines, *expected_lines_ptr;
- FILE *pagfp = NULL;
-
- for (i = 0; i < param.argc; i++)
- free (param.argv[i]);
- param.argc = 0;
-
- input_line++;
-
- if (interactive)
- outprompt ();
-
- if (fgets (cmdbuf, sizeof cmdbuf, stdin) == NULL)
- {
- putchar ('\n');
- break;
- }
-
- trimnl (cmdbuf);
- p = getword (cmdbuf, &sp);
- if (!*p)
- continue;
- cmd = find_command (p);
- if (!cmd)
- continue;
-
- for (i = 0; cmd->args[i]; i++)
- {
- char *arg = cmd->args[i];
-
- p = getword (sp, &sp);
- if (!*p)
- {
- if (*arg == '[')
- /* Optional argument */
- break;
- if (!interactive)
- syntax_error (_("%s: not enough arguments"), cmd->name);
- printf ("%s? ", arg);
- if (fgets (argbuf, sizeof argbuf, stdin) == NULL)
- terror (EXIT_USAGE, _("unexpected eof"));
-
- trimnl (argbuf);
- p = argbuf;
- }
-
- if (i >= argmax)
- {
- argmax += ARGINC;
- param.argv = erealloc (param.argv,
- sizeof (param.argv[0]) * argmax);
- }
- param.argv[i] = estrdup (p);
- }
-
- if (*sp)
- {
- syntax_error (_("%s: too many arguments"), cmd->name);
- continue;
- }
-
- /* Prepare for calling the handler */
- param.argc = i;
- param.fp = NULL;
- param.data = NULL;
- pagfp = NULL;
-
- expected_lines = 0;
- expected_lines_ptr = (interactive && pager) ? &expected_lines : NULL;
- if (cmd->begin && cmd->begin (&param, expected_lines_ptr))
- continue;
- if (pager && expected_lines > get_screen_lines ())
- {
- pagfp = popen (pager, "w");
- if (pagfp)
- param.fp = pagfp;
- else
- {
- terror (0, _("cannot run pager `%s': %s"), pager,
- strerror (errno));
- pager = NULL;
- param.fp = stdout;
- }
- }
- else
- param.fp = stdout;
-
- cmd->handler (&param);
- if (cmd->end)
- cmd->end (param.data);
- else if (param.data)
- free (param.data);
-
- if (pagfp)
- pclose (pagfp);
-
- }
- /* Quit normally. */
- quit_handler (NULL);
+ setsource ("stdin", stdin);
+ //FIXME
+ return yyparse ();
+
return 0;
}
diff --git a/src/gdbmtool.h b/src/gdbmtool.h
new file mode 100644
index 0000000..f2807b9
--- /dev/null
+++ b/src/gdbmtool.h
@@ -0,0 +1,122 @@
+/* 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 "autoconf.h"
+#include "gdbmdefs.h"
+#include "gdbm.h"
+#include "gdbmapp.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+/* Position in input file */
+struct point
+{
+ char *file; /* file name */
+ unsigned line; /* line number */
+ unsigned col; /* column number */
+};
+
+/* Location in input file */
+struct locus
+{
+ struct point beg, end;
+};
+
+typedef struct locus gdbm_yyltype_t;
+
+#define YYLTYPE gdbm_yyltype_t
+
+#define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ { \
+ if (N) \
+ { \
+ (Current).beg = YYRHSLOC(Rhs, 1).beg; \
+ (Current).end = YYRHSLOC(Rhs, N).end; \
+ } \
+ else \
+ { \
+ (Current).beg = YYRHSLOC(Rhs, 0).end; \
+ (Current).end = (Current).beg; \
+ } \
+ } \
+ while (0)
+
+#define YY_LOCATION_PRINT(File, Loc) \
+ do \
+ { \
+ if ((Loc).beg.col == 0) \
+ fprintf (File, "%s:%u", \
+ (Loc).beg.file, \
+ (Loc).beg.line); \
+ else if (strcmp ((Loc).beg.file, (Loc).end.file)) \
+ fprintf (File, "%s:%u.%u-%s:%u.%u", \
+ (Loc).beg.file, \
+ (Loc).beg.line, (Loc).beg.col, \
+ (Loc).end.file, \
+ (Loc).end.line, (Loc).end.col); \
+ else if ((Loc).beg.line != (Loc).end.line) \
+ fprintf (File, "%s:%u.%u-%u.%u", \
+ (Loc).beg.file, \
+ (Loc).beg.line, (Loc).beg.col, \
+ (Loc).end.line, (Loc).end.col); \
+ else if ((Loc).beg.col != (Loc).end.col) \
+ fprintf (File, "%s:%u.%u-%u", \
+ (Loc).beg.file, \
+ (Loc).beg.line, (Loc).beg.col, \
+ (Loc).end.col); \
+ else \
+ fprintf (File, "%s:%u.%u", \
+ (Loc).beg.file, \
+ (Loc).beg.line, \
+ (Loc).beg.col); \
+ } \
+ while (0)
+
+void vparse_error (struct locus *loc, const char *fmt, va_list ap);
+void parse_error (struct locus *loc, const char *fmt, ...);
+
+void syntax_error (const char *fmt, ...);
+
+void print_prompt (void);
+
+void setsource (const char *filename, FILE *file);
+
+extern int interactive;
+
+/* Argument to a command handler */
+struct gdbmarg
+{
+ struct gdbmarg *next;
+ char *string;
+};
+
+/* List of arguments */
+struct gdbmarglist
+{
+ struct gdbmarg *head, *tail;
+};
+
+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 *);
+
+int run_command (const char *verb, struct gdbmarglist *arglist);
+
diff --git a/src/gram.y b/src/gram.y
new file mode 100644
index 0000000..d9db0d7
--- /dev/null
+++ b/src/gram.y
@@ -0,0 +1,107 @@
+%{
+/* 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 <autoconf.h>
+#include "gdbmtool.h"
+
+%}
+
+%error-verbose
+%locations
+
+%token <string> T_IDENT T_WORD
+%type <string> arg verb
+%type <arglist> arglist arg1list
+
+%union {
+ char *string;
+ struct gdbmarglist arglist;
+}
+
+%%
+
+input : /* empty */
+ | stmtlist
+ ;
+
+stmtlist : stmt
+ | stmtlist stmt
+ ;
+
+stmt : /* empty */ '\n'
+ | verb arglist '\n'
+ {
+ if (run_command ($1, &$2) && !interactive)
+ exit (EXIT_USAGE);
+ gdbmarglist_free (&$2);
+ }
+ | error '\n'
+ {
+ if (interactive)
+ {
+ yyclearin;
+ yyerrok;
+ }
+ else
+ YYERROR;
+ }
+ ;
+
+verb : T_IDENT
+ ;
+
+arglist : /* empty */
+ {
+ gdbmarglist_init (&$$, NULL);
+ }
+ | arg1list
+ ;
+
+arg1list : arg
+ {
+ gdbmarglist_init (&$$, gdbmarg_new ($1));
+ }
+ | arg1list arg
+ {
+ gdbmarglist_add (&$1, gdbmarg_new ($2));
+ $$ = $1;
+ }
+ ;
+
+arg : T_IDENT
+ | T_WORD
+ ;
+
+%%
+
+void
+syntax_error (const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ vparse_error (&yylloc, fmt, ap);
+ va_end (ap);
+}
+
+int
+yyerror (char *s)
+{
+ syntax_error ("%s", s);
+ return 0;
+}
diff --git a/src/lex.l b/src/lex.l
new file mode 100644
index 0000000..7a8c99b
--- /dev/null
+++ b/src/lex.l
@@ -0,0 +1,263 @@
+%{
+/* 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 <autoconf.h>
+#include "gdbmtool.h"
+#include "gram.h"
+
+struct point point;
+
+/* Advance locus to the next line */
+void
+advance_line ()
+{
+ ++point.line;
+ point.col = 0;
+}
+
+#define YY_USER_ACTION \
+ do \
+ { \
+ if (YYSTATE == 0) \
+ { \
+ yylloc.beg = point; \
+ yylloc.beg.col++; \
+ } \
+ point.col += yyleng; \
+ yylloc.end = point; \
+ } \
+ while (0);
+
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ do \
+ { \
+ result = read_input (buf, max_size); \
+ } \
+ while (0);
+
+void string_begin (void);
+void string_add (const char *s, int l);
+void string_addc (int c);
+char *string_end (void);
+int unescape (int c);
+
+static ssize_t read_input (char *buf, size_t size);
+
+%}
+
+%x STR
+
+WS [ \t][ \t]*
+IDENT [a-zA-Z_][a-zA-Z_0-9]*
+
+%%
+^[ \t]*#[ \t]*line[ \t].*\n {
+ char *p, *q;
+ char *file = NULL;
+ int line, len;
+
+ for (p = strchr (yytext, '#') + 1; *p == ' ' || *p == '\t'; p++);
+ p += 4;
+ for (; *p == ' ' || *p == '\t'; p++);
+ if (*p == '"')
+ {
+ p++;
+ len = strcspn (p, "\"");
+ if (p[len] == 0)
+ {
+ yyerror (_("invalid #line statement"));
+ REJECT;
+ }
+ file = emalloc (len + 1);
+ memcpy (file, p, len);
+ file[len] = 0;
+ for (p += len + 1; *p == ' ' || *p == '\t'; p++);
+ }
+ line = strtol (p, &q, 10);
+ if (*q && *q != ' ')
+ {
+ yyerror (_("invalid #line statement"));
+ free (file);
+ REJECT;
+ }
+ 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; }
+\"[^\\\"\n]*\" { yylval.string = emalloc (yyleng - 1);
+ memcpy (yylval.string, yytext+1, yyleng-2);
+ yylval.string[yyleng-2] = 0;
+ return T_WORD; }
+\"[^\\\"\n]*\\. { string_begin ();
+ string_add (yytext + 1, yyleng - 3);
+ string_addc (unescape (yytext[yyleng-1]));
+ BEGIN(STR); }
+<STR>[^\\\"\n]*\" { if (yyleng > 1)
+ string_add (yytext, yyleng - 1);
+ yylval.string = string_end ();
+ BEGIN(INITIAL);
+ return T_WORD; }
+<STR>[^\\\"\n]*\\. { string_add (yytext, yyleng - 2);
+ string_addc (unescape (yytext[yyleng-1])); }
+{WS} ;
+\n { advance_line (); return '\n'; }
+. return yytext[0];
+%%
+
+void
+setsource (const char *filename, FILE *file)
+{
+ point.file = (char*) filename;
+ point.line = 1;
+ point.col = 0;
+ yyin = file;
+}
+
+int
+yywrap ()
+{
+ return 1;
+}
+
+static ssize_t
+read_input (char *buf, size_t size)
+{
+ if (interactive)
+ {
+ if (YY_AT_BOL ())
+ print_prompt ();
+ if (fgets (buf, size, yyin) == NULL)
+ return 0;
+ return strlen (buf);
+ }
+ return fread (buf, 1, size, yyin);
+}
+
+
+struct strseg
+{
+ struct strseg *next;
+ int len;
+ char ptr[1];
+};
+
+static struct strseg *strseg_head, *strseg_tail;
+
+void
+string_begin (void)
+{
+ strseg_head = strseg_tail = NULL;
+}
+
+void
+strseg_attach (struct strseg *seg)
+{
+ seg->next = NULL;
+ if (strseg_tail)
+ strseg_tail->next = seg;
+ else
+ strseg_head = seg;
+ strseg_tail = seg;
+}
+
+void
+string_add (const char *s, int l)
+{
+ struct strseg *seg = emalloc (sizeof (*seg) + l);
+ memcpy (seg->ptr, s, l);
+ seg->len = l;
+ strseg_attach (seg);
+}
+
+void
+string_addc (int c)
+{
+ struct strseg *seg = emalloc (sizeof (*seg));
+ seg->ptr[0] = c;
+ seg->len = 1;
+ strseg_attach (seg);
+}
+
+char *
+string_end (void)
+{
+ int len = 1;
+ struct strseg *seg;
+ char *ret, *p;
+
+ for (seg = strseg_head; seg; seg = seg->next)
+ len += seg->len;
+
+ ret = emalloc (len);
+ p = ret;
+ for (seg = strseg_head; seg; )
+ {
+ struct strseg *next = seg->next;
+ memcpy (p, seg->ptr, seg->len);
+ p += seg->len;
+ free (seg);
+ seg = next;
+ }
+ *p = 0;
+
+ strseg_head = strseg_tail = NULL;
+
+ return ret;
+}
+
+int
+unescape (int c)
+{
+ static char transtab[] = "\\\\\"\"a\ab\bf\fn\nr\rt\tv\v";
+ char *p;
+
+ for (p = transtab; *p; p += 2)
+ {
+ if (*p == c)
+ return p[1];
+ }
+ return c;
+}
+
+void
+vparse_error (struct locus *loc, const char *fmt, va_list ap)
+{
+ if (!interactive)
+ fprintf (stderr, "%s", progname);
+ if (loc)
+ YY_LOCATION_PRINT (stderr, *loc);
+ fprintf (stderr, ": ");
+ vfprintf (stderr, fmt, ap);
+ fputc ('\n', stderr);
+}
+
+void
+parse_error (struct locus *loc, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start (ap, fmt);
+ vparse_error (loc, fmt, ap);
+ va_end (ap);
+}

Return to:

Send suggestions and report system problems to the System administrator.