From a836810f4e209530a9aee940fa90191eb7c6e524 Mon Sep 17 00:00:00 2001
From: Antonio Huete Jimenez <tuxillo@quantumachine.net>
Date: Thu, 4 Jun 2020 22:50:41 +0200
Subject: [PATCH] WIP 1/x

---
 sbin/dbcli/Makefile    |  13 +++++
 sbin/dbcli/dbcli.c     | 110 ++++++++++++++++++++++++++++++++++++
 sbin/dbcli/dbcli.h     |  91 ++++++++++++++++++++++++++++++
 sbin/dbcli/parser.y    | 125 +++++++++++++++++++++++++++++++++++++++++
 sbin/dbcli/tokenizer.l | 112 ++++++++++++++++++++++++++++++++++++
 5 files changed, 451 insertions(+)
 create mode 100644 sbin/dbcli/Makefile
 create mode 100644 sbin/dbcli/dbcli.c
 create mode 100644 sbin/dbcli/dbcli.h
 create mode 100644 sbin/dbcli/parser.y
 create mode 100644 sbin/dbcli/tokenizer.l

diff --git a/sbin/dbcli/Makefile b/sbin/dbcli/Makefile
new file mode 100644
index 0000000000..48a79dc0ba
--- /dev/null
+++ b/sbin/dbcli/Makefile
@@ -0,0 +1,13 @@
+# $DragonFly
+
+PROG=	dbcli
+
+SRCS+=	dbcli.c tokenizer.l parser.y y.tab.h
+
+CFLAGS+= -g
+#CFLAGS+= -DYYDEBUG=1
+YFLAGS+= -v --debug
+NO_MAN=
+NO_WERROR=
+
+.include <bsd.prog.mk>
diff --git a/sbin/dbcli/dbcli.c b/sbin/dbcli/dbcli.c
new file mode 100644
index 0000000000..9ddee3879c
--- /dev/null
+++ b/sbin/dbcli/dbcli.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2020 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name of The DragonFly Project nor the names of its
+ *    contributors may be used to endorse or promote products derived
+ *    from this software without specific, prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <fcntl.h>
+#include <db.h>
+#include <err.h>
+
+#include <sys/stat.h>
+
+#include "dbcli.h"
+
+/* Allowed commands */
+struct dbcli_cmd dbcli_cmds[] = {
+	{ "open",    DBC_OPEN },
+	{ "commit",  DBC_COMMIT },
+	{ "close",   DBC_CLOSE },
+	{ "select",  DBC_SELECT },
+	{ "insert",  DBC_INSERT },
+	{ "delete",  DBC_DELETE },
+	{ "replace", DBC_REPLACE },
+	{ "set",     DBC_SET },
+	{ "exit",    DBC_EXIT },
+	{ "quit",    DBC_EXIT },
+	{ 0, 0 }
+};
+
+/* Options for the SET command */
+struct dbcli_opt dbcli_opts[] = {
+	{ "autocommit", DBO_AUTOCOMMIT },
+	{ "readonly",   DBO_READONLY },
+	{ "create",     DBO_CREATE },
+	{ 0, 0 }
+};
+
+/* Globals */
+int autocommit;
+int readonly;
+int create;
+
+int
+setoptions(int option, int toggle)
+{
+	switch (option) {
+	case DBO_AUTOCOMMIT:
+		autocommit = toggle;
+		break;
+	case DBO_READONLY:
+		readonly = toggle;
+		break;
+	case DBO_CREATE:
+		create = toggle;
+		break;
+	default:
+		return -1;
+		break;	/* NOT REACHED */
+	}
+
+	printf("%d set to %d\n", option, toggle);
+
+	return 0;
+}
+
+int
+main(int argc, char *argv[])
+{
+
+	/* Basic parse error recovery */
+	for (;;) {
+		if (feof(stdin))
+			break;
+		prompt();
+		yyparse();
+	}
+
+	return 0;
+}
diff --git a/sbin/dbcli/dbcli.h b/sbin/dbcli/dbcli.h
new file mode 100644
index 0000000000..0c996b1d40
--- /dev/null
+++ b/sbin/dbcli/dbcli.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2020 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *
+ * Database operations
+ *
+ * OPEN     <databasefile>
+ * COMMIT
+ * CLOSE
+ *
+ * Settings (user defined)
+ *
+ * SET [AUTOCOMMIT|CREATE|READONLY] [ON|OFF]
+ *
+ * Record operations
+ *
+ * SELECT  <field> WHERE <condition>
+ * INSERT  <key>, <value>
+ * DELETE  <key>
+ * REPLACE <key>, <value>
+ *
+ *
+ * Detailed information
+ *
+ * AUTOCOMMIT syncs changes to disk
+ * CREAT      creates the specified database.
+ * RDONLY     open the database in read-only mode
+ *
+ * <field>     string that can be either key or value.
+ * <condition> only one condition is accepted, it has to
+ *            be in the format of {key,value}=<desired value>
+ *
+ * <key>       key identifier
+ * <value>     value identifier
+ *
+ */
+
+#ifndef _DBCLI_H_
+#define _DBCLI_H_
+
+#include "y.tab.h"
+
+/* Command struct */
+struct dbcli_cmd {
+       const char *cname;
+       int cval;
+};
+
+/* SET options */
+struct dbcli_opt {
+       const char *oname;
+       int oval;
+};
+
+extern struct dbcli_cmd dbcli_cmds[];
+extern struct dbcli_opt dbcli_opts[];
+
+
+int setoptions(int, int);
+
+#endif	/* _DBCLI_H_ */
diff --git a/sbin/dbcli/parser.y b/sbin/dbcli/parser.y
new file mode 100644
index 0000000000..a7d9b0407e
--- /dev/null
+++ b/sbin/dbcli/parser.y
@@ -0,0 +1,125 @@
+/*-
+ * Copyright (c) 2020 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+%{
+#include <stdio.h>
+#include <string.h>
+
+#include "dbcli.h"
+
+extern int      yylex(void);
+
+int yydebug = 1;
+
+void      yyerror(const char *);
+int	  yywrap(void);
+
+void prompt(void);
+
+void yyerror(const char *str)
+{
+	fprintf(stderr, "error in command: %s\n", str);
+}
+
+int yywrap(void)
+{
+	return 1;
+}
+
+%}
+
+%union {
+	char *s;
+	int i;
+}
+
+%token <s> DBC_OPEN
+%token <s> DBC_COMMIT
+%token <s> DBC_CLOSE
+%token <s> DBC_SET
+%token <s> DBC_SELECT
+%token <s> DBC_INSERT
+%token <s> DBC_REPLACE
+%token <s> DBC_DELETE
+%token <s> DBC_EXIT
+%token <i> DBO_AUTOCOMMIT
+%token <i> DBO_READONLY
+%token <i> DBO_CREATE
+%token <s> TOGGLE
+%token <i> SET_OPT
+%token <s> PATH
+%token <s> NEWL
+%token <s> ID
+
+%type <i> options
+
+%%
+
+commands
+	: command
+	| commands command
+	;
+
+command:
+	| DBC_OPEN ID
+	;
+	| DBC_SET options TOGGLE
+	{
+		int toggle = 0;
+
+		if (!strcmp("on", $3))
+			toggle = 1;
+
+		if ((setoptions($2, toggle)) == -1) {
+			yyerror("bad option");
+			return;
+		}
+	}
+	;
+	| DBC_EXIT
+	{
+		printf("bye!\n");
+		exit(EXIT_SUCCESS);
+	}
+	;
+	| NEWL { prompt(); }
+	;
+
+options
+	: DBO_AUTOCOMMIT
+	;
+	| DBO_CREATE
+	;
+	| DBO_READONLY
+	;
diff --git a/sbin/dbcli/tokenizer.l b/sbin/dbcli/tokenizer.l
new file mode 100644
index 0000000000..7512bfdd97
--- /dev/null
+++ b/sbin/dbcli/tokenizer.l
@@ -0,0 +1,112 @@
+%{
+/*-
+ * Copyright (c) 2020 The DragonFly Project.  All rights reserved.
+ *
+ * This code is derived from software contributed to The DragonFly Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <stdio.h>
+#include <unistd.h>
+
+#include "y.tab.h"
+#include "dbcli.h"
+
+int cmd_lookup(const char *s);
+int opt_lookup(const char *s);
+
+void prompt(void);
+
+%}
+WORD	[A-Za-z_][-A-Za-z_]*
+ID	[0-9A-Za-z_][-A-Za-z_0-9]*
+PATH	[0-9A-Za-z_][-A-Za-z_0-9]*
+TOGGLE	on|off
+SET_OPT	autocommit|readonly|create
+NEWL	[\n\r]
+
+%option caseless
+%option noinput
+%option nounput
+%%
+{TOGGLE}	{	yylval.s = strdup(yytext); return TOGGLE;	}
+{SET_OPT}		{
+			int i;
+
+			if ((i = opt_lookup(yytext)) == -1) {
+				yyerror("bad option");
+				return -1;
+			}
+			yylval.i = i;
+			return i;
+		}
+{WORD}		{
+			int i;
+
+			if ((i = cmd_lookup(yytext)) == -1)
+			{
+				yylval.s = strdup(yytext);
+				return(ID);
+			}
+			return(i);
+		}
+{NEWL}		{ return NEWL;	}
+[\t ]+		;
+
+%%
+
+int
+cmd_lookup(const char *s)
+{
+        struct dbcli_cmd *dcmd;
+
+        for (dcmd = dbcli_cmds; dcmd->cname != NULL; dcmd++)
+                if (!strcasecmp(s, dcmd->cname))
+                        return(dcmd->cval);
+        return(-1);
+}
+
+int
+opt_lookup(const char *s)
+{
+        struct dbcli_opt *dopt;
+
+        for (dopt = dbcli_opts; dopt->oname != NULL; dopt++)
+                if (!strcasecmp(s, dopt->oname))
+                        return(dopt->oval);
+        return(-1);
+}
+
+void
+prompt(void)
+{
+	if (isatty(STDIN_FILENO))
+		printf("dbcli> ");
+}
-- 
2.26.1

