[repo.or.cz] iwhd.git branch bison-flex deleted: v0.0-194-g65c39ae
by Jim Meyering
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, bison-flex has been deleted
was 65c39ae177bd3242af677b9d4220141de95ccb85
-----------------------------------------------------------------------
65c39ae177bd3242af677b9d4220141de95ccb85 now that lexer calls strdup, free those strings
-----------------------------------------------------------------------
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months
[repo.or.cz] iwhd.git branch cleanup created: v0.0-217-g579fbe2
by Jim Meyering
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, cleanup has been created
at 579fbe2eb103e80401fcaaaebebc9060fa2517b5 (commit)
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/579fbe2eb103e80401fcaaaebebc9060fa2517b5
commit 579fbe2eb103e80401fcaaaebebc9060fa2517b5
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Oct 20 12:03:30 2010 +0200
query parser: avoid 25 reduce/reduce conflicts
* qparser.y (T_SPACE): Remove token and all related rules.
* qlexer.l: Ignore white space rather than returning T_SPACE.
* t/parser-test: Adjust sole failing test: "$ a" was rejected before,
due to ignored white space; now it's interpreted as "$a".
Add one more: "$.a" that does still fail.
diff --git a/qlexer.l b/qlexer.l
index 59c6fb1..976939b 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -35,7 +35,7 @@
! { return T_NOT; }
&& { return T_AND; }
|| { return T_OR; }
-[ tnr]+ { return T_SPACE; }
+[ tnr]+ { }
. { return T_INVALID; }
<<EOF>> { yyterminate (); /* aka return 0; */ }
diff --git a/qparser.y b/qparser.y
index 961ccbc..07f0501 100644
--- a/qparser.y
+++ b/qparser.y
@@ -159,7 +159,7 @@ yyerror (void *scanner ATTRIBUTE_UNUSED,
%parse-param { value_t **result }
%token <str> T_STRING T_COMP T_DATE T_ID T_LINK T_NUMBER T_OFIELD T_SFIELD
-%token T_EQ T_NE T_NOT T_AND T_OR T_SPACE T_INVALID
+%token T_EQ T_NE T_NOT T_AND T_OR T_INVALID
%token T_LT T_GT T_LE T_GE
%type <val> atom bbool_expr comp_expr field
@@ -186,11 +186,6 @@ bbool_expr:
bbool_expr T_OR ubool_expr {
// printf("found OR expressionn");
$$ = make_tree(T_OR,$1,$3);
- }|
- bbool_expr T_SPACE {
- $$ = $1;
- }| T_SPACE bbool_expr {
- $$ = $2;
};
ubool_expr:
@@ -201,11 +196,6 @@ ubool_expr:
T_NOT comp_expr {
// printf("found NOT expressionn");
$$ = make_tree(T_NOT,$2,NULL);
- }|
- ubool_expr T_SPACE {
- $$ = $1;
- }| T_SPACE ubool_expr {
- $$ = $2;
};
@@ -237,11 +227,6 @@ comp_expr:
atom T_GT atom {
// printf("found GREATER THAN expressionn");
$$ = make_comp(C_GREATERTHAN,$1,$3);
- }|
- comp_expr T_SPACE {
- $$ = $1;
- }| T_SPACE comp_expr {
- $$ = $2;
};
atom:
@@ -256,11 +241,6 @@ atom:
paren_expr {
// printf("promoting paren_expr to atomn");
$$ = $1;
- }|
- atom T_SPACE {
- $$ = $1;
- }| T_SPACE atom {
- $$ = $2;
};
link_field:
diff --git a/t/parser-test b/t/parser-test
index cf006c6..0daead1 100755
--- a/t/parser-test
+++ b/t/parser-test
@@ -27,8 +27,12 @@ parser '#a == "fubar" && ! ( $b.c.d < 3)' > white-space 2> err || fail=1
compare white-space f.exp || fail=1
compare /dev/null err || fail=1
-parser '$ a' > e1.out 2>&1; test $? = 1 || fail=1
-printf "could not parse '$ a'n" > e1.exp
+parser '$ a' > a.out 2>&1 || fail=1
+printf "OBJECT FIELD a (2)ns= 2n" > a.exp
+compare a.out a.exp || fail=1
+
+parser '$.a' > e1.out 2>&1; test $? = 1 || fail=1
+printf "could not parse '$.a'n" > e1.exp
compare e1.exp e1.out || fail=1
parser '1 = = 1' > e2.out 2>&1; test $? = 1 || fail=1
http://repo.or.cz/w/iwhd.git/commit/9bf769abd180bc4502457371840830694997a0c5
commit 9bf769abd180bc4502457371840830694997a0c5
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Oct 20 11:37:18 2010 +0200
simplify parser: <, >, >=, <=
diff --git a/qlexer.l b/qlexer.l
index 6bb82f4..59c6fb1 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -25,7 +25,11 @@
return yylval_param->str ? T_NUMBER : T_INVALID; }
[a-z_]+ { yylval_param->str = strdup(yytext);
return yylval_param->str ? T_ID : T_INVALID; }
-[=$#()<>.] { return yytext[0]; }
+[$#().] { return yytext[0]; }
+[<] { return T_LT; }
+[<]= { return T_LE; }
+> { return T_GT; }
+>= { return T_GE; }
== { return T_EQ; }
!= { return T_NE; }
! { return T_NOT; }
diff --git a/qparser.y b/qparser.y
index abd0d15..961ccbc 100644
--- a/qparser.y
+++ b/qparser.y
@@ -160,6 +160,7 @@ yyerror (void *scanner ATTRIBUTE_UNUSED,
%token <str> T_STRING T_COMP T_DATE T_ID T_LINK T_NUMBER T_OFIELD T_SFIELD
%token T_EQ T_NE T_NOT T_AND T_OR T_SPACE T_INVALID
+%token T_LT T_GT T_LE T_GE
%type <val> atom bbool_expr comp_expr field
%type <val> link_field literal paren_expr ubool_expr
@@ -213,13 +214,13 @@ comp_expr:
// printf("promoting atom to comp_exprn");
$$ = $1;
}|
- atom '<' atom {
+ atom T_LT atom {
// printf("found LESS THAN expressionn");
$$ = make_comp(C_LESSTHAN,$1,$3);
}|
- atom '<' '=' atom {
+ atom T_LE atom {
// printf("found LESS OR EQUAL expressionn");
- $$ = make_comp(C_LESSOREQ,$1,$4);
+ $$ = make_comp(C_LESSOREQ,$1,$3);
}|
atom T_EQ atom {
// printf("found EQUAL expressionn");
@@ -229,11 +230,11 @@ comp_expr:
// printf("found NOT EQUAL expressionn");
$$ = make_comp(C_DIFFERENT,$1,$3);
}|
- atom '>' '=' atom {
+ atom T_GE atom {
// printf("found GREATER OR EQUAL expressionn");
- $$ = make_comp(C_GREATEROREQ,$1,$4);
+ $$ = make_comp(C_GREATEROREQ,$1,$3);
}|
- atom '>' atom {
+ atom T_GT atom {
// printf("found GREATER THAN expressionn");
$$ = make_comp(C_GREATERTHAN,$1,$3);
}|
http://repo.or.cz/w/iwhd.git/commit/37e06749f1331723d5a9c7e99c9ffe812be5743a
commit 37e06749f1331723d5a9c7e99c9ffe812be5743a
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Oct 20 11:34:00 2010 +0200
simplify parser: T_EQ
diff --git a/qlexer.l b/qlexer.l
index 5d0e488..6bb82f4 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -26,6 +26,7 @@
[a-z_]+ { yylval_param->str = strdup(yytext);
return yylval_param->str ? T_ID : T_INVALID; }
[=$#()<>.] { return yytext[0]; }
+== { return T_EQ; }
!= { return T_NE; }
! { return T_NOT; }
&& { return T_AND; }
diff --git a/qparser.y b/qparser.y
index 9b9efce..abd0d15 100644
--- a/qparser.y
+++ b/qparser.y
@@ -159,7 +159,7 @@ yyerror (void *scanner ATTRIBUTE_UNUSED,
%parse-param { value_t **result }
%token <str> T_STRING T_COMP T_DATE T_ID T_LINK T_NUMBER T_OFIELD T_SFIELD
-%token T_NE T_NOT T_AND T_OR T_SPACE T_INVALID
+%token T_EQ T_NE T_NOT T_AND T_OR T_SPACE T_INVALID
%type <val> atom bbool_expr comp_expr field
%type <val> link_field literal paren_expr ubool_expr
@@ -221,9 +221,9 @@ comp_expr:
// printf("found LESS OR EQUAL expressionn");
$$ = make_comp(C_LESSOREQ,$1,$4);
}|
- atom '=' '=' atom {
+ atom T_EQ atom {
// printf("found EQUAL expressionn");
- $$ = make_comp(C_EQUAL,$1,$4);
+ $$ = make_comp(C_EQUAL,$1,$3);
}|
atom T_NE atom {
// printf("found NOT EQUAL expressionn");
http://repo.or.cz/w/iwhd.git/commit/a8d1ea65e6d513e25f148c2dda2b9a41901dfe41
commit a8d1ea65e6d513e25f148c2dda2b9a41901dfe41
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Oct 20 11:32:59 2010 +0200
simplify parser: T_NE
diff --git a/qlexer.l b/qlexer.l
index 5f354df..5d0e488 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -26,6 +26,7 @@
[a-z_]+ { yylval_param->str = strdup(yytext);
return yylval_param->str ? T_ID : T_INVALID; }
[=$#()<>.] { return yytext[0]; }
+!= { return T_NE; }
! { return T_NOT; }
&& { return T_AND; }
|| { return T_OR; }
diff --git a/qparser.y b/qparser.y
index 0ff2e7b..9b9efce 100644
--- a/qparser.y
+++ b/qparser.y
@@ -159,7 +159,7 @@ yyerror (void *scanner ATTRIBUTE_UNUSED,
%parse-param { value_t **result }
%token <str> T_STRING T_COMP T_DATE T_ID T_LINK T_NUMBER T_OFIELD T_SFIELD
-%token T_NOT T_AND T_OR T_SPACE T_INVALID
+%token T_NE T_NOT T_AND T_OR T_SPACE T_INVALID
%type <val> atom bbool_expr comp_expr field
%type <val> link_field literal paren_expr ubool_expr
@@ -225,9 +225,9 @@ comp_expr:
// printf("found EQUAL expressionn");
$$ = make_comp(C_EQUAL,$1,$4);
}|
- atom T_NOT '=' atom {
+ atom T_NE atom {
// printf("found NOT EQUAL expressionn");
- $$ = make_comp(C_DIFFERENT,$1,$4);
+ $$ = make_comp(C_DIFFERENT,$1,$3);
}|
atom '>' '=' atom {
// printf("found GREATER OR EQUAL expressionn");
http://repo.or.cz/w/iwhd.git/commit/f8f366e1a856be5e95f8bb8ace348865e4ff735b
commit f8f366e1a856be5e95f8bb8ace348865e4ff735b
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Oct 20 11:14:53 2010 +0200
mark more unused parameters
diff --git a/qparser.y b/qparser.y
index 3455c42..0ff2e7b 100644
--- a/qparser.y
+++ b/qparser.y
@@ -145,8 +145,11 @@ make_link (value_t *left, const char *right)
}
static void
-yyerror (void *scanner, value_t **result, const char *msg)
+yyerror (void *scanner ATTRIBUTE_UNUSED,
+ value_t **result ATTRIBUTE_UNUSED,
+ const char *msg ATTRIBUTE_UNUSED)
{
+ /* empty */
}
%}
http://repo.or.cz/w/iwhd.git/commit/601d9ff306989b4c9e79aa81bd07af712d2ff0bb
commit 601d9ff306989b4c9e79aa81bd07af712d2ff0bb
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Oct 20 09:43:03 2010 +0200
remove final "static" state variable from the parser
* qparser.y: Remove "syntax_error" decl.
(yyerror): Adjust. Make this function static, too.
<policy>: Adjust the sole rule that used it.
diff --git a/qparser.y b/qparser.y
index 182926f..3455c42 100644
--- a/qparser.y
+++ b/qparser.y
@@ -19,6 +19,8 @@
#include <string.h>
#include <ctype.h>
+#include "iwh.h"
+
#define YY_DECL int yylex(YYSTYPE *, void *scanner);
YY_DECL
@@ -142,22 +144,9 @@ make_link (value_t *left, const char *right)
return make_tree(T_LINK,left,(value_t *)copy);
}
-/*
- * IMO it's wrong for us to get into the bbool_expr=policy rule when there's
- * a syntax error, but we do. The good news is that it's easy to free the
- * erroneous tree properly this way. The bad news is that we need to wait
- * until yyparse is done, then check this flag (which we have to maintain
- * ourselves) to figure out whether we got a valid tree or not.
- * No, yynerrs doesn't seem to give the right answer.
- */
-static int syntax_error = 0;
-
-void
+static void
yyerror (void *scanner, value_t **result, const char *msg)
{
- // error (0, 0, "parse error: %sn", msg);
- // FIXME do this via param, not file-global
- syntax_error = 1;
}
%}
@@ -178,12 +167,7 @@ yyerror (void *scanner, value_t **result, const char *msg)
policy:
bbool_expr {
- if (syntax_error) {
- printf("bad policy!n");
- }
- else {
- *result = $1;
- }
+ *result = $1;
};
bbool_expr:
http://repo.or.cz/w/iwhd.git/commit/a573c2d19dfd41e6dc3af8e2f5f6f3df6cf48cff
commit a573c2d19dfd41e6dc3af8e2f5f6f3df6cf48cff
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Oct 20 10:20:33 2010 +0200
mark unused parameters as such
diff --git a/backend.c b/backend.c
index 8d3547c..6795ef9 100644
--- a/backend.c
+++ b/backend.c
@@ -1035,13 +1035,13 @@ cf_put_child (void * ctx)
}
static int
-cf_delete (const provider_t *prov, const char *bucket, const char *key,
- const char *url)
+cf_delete (const provider_t *prov,
+ const char *bucket ATTRIBUTE_UNUSED,
+ const char *key ATTRIBUTE_UNUSED,
+ const char *url)
{
CURL *curl;
char fixed[1024];
- int chars;
- char auth_hdr[HEADER_SIZE];
long rc;
struct curl_slist *slist = NULL;
@@ -1072,7 +1072,10 @@ cf_delete (const provider_t *prov, const char *bucket, const char *key,
}
static size_t
-cf_null_reader (void *ptr, size_t size, size_t nmemb, void *stream)
+cf_null_reader (void *ptr ATTRIBUTE_UNUSED,
+ size_t size ATTRIBUTE_UNUSED,
+ size_t nmemb ATTRIBUTE_UNUSED,
+ void *stream ATTRIBUTE_UNUSED)
{
return 0;
}
http://repo.or.cz/w/iwhd.git/commit/f1f8ba5a3338fe94c3adccae737b4d30d34fbb45
commit f1f8ba5a3338fe94c3adccae737b4d30d34fbb45
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Oct 20 09:25:33 2010 +0200
remove decls of unused variables
diff --git a/backend.c b/backend.c
index 502ce14..8d3547c 100644
--- a/backend.c
+++ b/backend.c
@@ -868,7 +868,6 @@ cf_add_token (struct curl_slist *in_slist, const char *token)
{
int chars;
char auth_hdr[HEADER_SIZE];
- struct curl_slist *out_slist;
if (!token) {
return in_slist;
@@ -887,10 +886,9 @@ static void
cf_init (provider_t *prov)
{
CURL *curl;
- char addr[ADDR_SIZE];
- char auth_user[HEADER_SIZE];
- char auth_key[HEADER_SIZE];
- char *token;
+ char addr[ADDR_SIZE];
+ char auth_user[HEADER_SIZE];
+ char auth_key[HEADER_SIZE];
struct curl_slist *slist;
int chars;
@@ -1084,8 +1082,6 @@ cf_bcreate (const provider_t *prov, const char *bucket)
{
char fixed[1024];
CURL *curl;
- int chars;
- char auth_hdr[HEADER_SIZE];
long rc;
struct curl_slist *slist = NULL;
diff --git a/meta.cpp b/meta.cpp
index de9dfa2..d467c1e 100644
--- a/meta.cpp
+++ b/meta.cpp
@@ -644,10 +644,7 @@ RepoMeta::GetAttrList (const char *bucket, const char *key)
{
auto_ptr<DBClientCursor> curs;
Query q;
- AttrList * poc;
BSONObj bo;
- const char * name;
- const char * value;
q = QUERY("bucket"<<bucket<<"key"<<key);
curs = GetCursor(q);
diff --git a/replica.c b/replica.c
index 4376d0a..9487c33 100644
--- a/replica.c
+++ b/replica.c
@@ -93,7 +93,6 @@ proxy_repl_cons (void *ctx)
repl_item *item = ctx;
my_state *ms = item->ms;
pipe_private *pp;
- void *rc;
pp = pipe_init_private(&ms->pipe);
if (!pp) {
http://repo.or.cz/w/iwhd.git/commit/cc4972ea5ad864db65cc69e8db34a6c8b4c19807
commit cc4972ea5ad864db65cc69e8db34a6c8b4c19807
Author: Jim Meyering <meyering(a)redhat.com>
Date: Wed Oct 20 09:13:39 2010 +0200
qparser: remove dead code
* qparser.y (make_link): Remove now-useless test;
xmalloc never returns NULL.
diff --git a/qparser.y b/qparser.y
index e5bd1ad..182926f 100644
--- a/qparser.y
+++ b/qparser.y
@@ -138,9 +138,6 @@ make_link (value_t *left, const char *right)
copy = xstrdup(right);
free ((void *) right);
- if (!copy) {
- return NULL;
- }
return make_tree(T_LINK,left,(value_t *)copy);
}
http://repo.or.cz/w/iwhd.git/commit/af7f9208dcded36890f0fb9940439d38756c6155
commit af7f9208dcded36890f0fb9940439d38756c6155
Author: Jim Meyering <meyering(a)redhat.com>
Date: Tue Oct 19 18:27:52 2010 +0200
automatically generate man page
* configure.ac (AC_CONFIG_FILES): Add man/Makefile.
Check for help2man.
* Makefile.am (SUBDIRS): Add "." and man.
* man/Makefile.am: New file.
* .gitignore: Ignore new artifacts and anchor patterns.
* iwhd.spec.in (%files): Add man page file name.
diff --git a/.gitignore b/.gitignore
index e85dc40..6fbf252 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,25 +2,26 @@
*~
.#*
.deps
+/aclocal.m4
+/autom4te.cache/
+/build-aux
+/config.h
+/config.hin
+/config.log
+/config.status
+/configure
+/iwhd
+/iwhd-*.tar.gz
+/iwhd-qparser.c
+/iwhd-qparser.h
+/iwhd.spec
+/man/iwhd.8
+/qlexer.c
+/stamp-h1
+/t/*.log
+/t/parser
+/t/parser.c
ChangeLog
Makefile
Makefile.in
#*#
-aclocal.m4
-autom4te.cache/
-build-aux
-config.h
-config.hin
-config.log
-config.status
-configure
-iwhd
-iwhd-*.tar.gz
-iwhd-qparser.c
-iwhd-qparser.h
-iwhd.spec
-qlexer.c
-stamp-h1
-t/*.log
-t/parser
-t/parser.c
diff --git a/Makefile.am b/Makefile.am
index 5510cf1..44ff506 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -20,7 +20,7 @@ AM_CPPFLAGS = -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include
iwhd_YFLAGS = -d
-SUBDIRS = t
+SUBDIRS = . t man
ACLOCAL_AMFLAGS = -I ax
# iwhd is short for Image WareHouse Daemon.
diff --git a/configure.ac b/configure.ac
index afbe4c3..78eb70b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -30,6 +30,7 @@ AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_YACC
AC_PROG_LEX
+AM_MISSING_PROG([HELP2MAN], [help2man])
AC_CHECK_LIB([curl], [curl_easy_init],
[CURL_LIB=-lcurl],
@@ -88,5 +89,9 @@ AC_FUNC_MALLOC
AC_FUNC_REALLOC
AC_CHECK_FUNCS([gettimeofday memmove memset strcasecmp strdup strndup strtoul])
-AC_CONFIG_FILES([Makefile t/Makefile])
+AC_CONFIG_FILES([
+Makefile
+t/Makefile
+man/Makefile
+])
AC_OUTPUT
diff --git a/iwhd.spec.in b/iwhd.spec.in
index 282370e..2b28b53 100644
--- a/iwhd.spec.in
+++ b/iwhd.spec.in
@@ -57,6 +57,7 @@ rm -rf %{buildroot}
%defattr(-,root,root,-)
%doc AUTHORS COPYING README NEWS
%{_bindir}/iwhd
+%{_mandir}/man8/iwhd.8*
%changelog
* Wed Oct 7 2010 Jim Meyering <meyering(a)redhat.com> - 0.90-1
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 0000000..7399460
--- /dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,26 @@
+# Automakefile for GNU diffutils man pages
+
+# Copyright (C) 2002, 2009-2010 Free Software Foundation, Inc.
+
+# This program 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 of the License, or
+# (at your option) any later version.
+
+# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+
+dist_man8_MANS = iwhd.8
+MAINTAINERCLEANFILES = $(dist_man8_MANS)
+
+# Depend on configure.ac to get version number changes.
+iwhd.8: $(top_srcdir)/configure.ac $(top_srcdir)/rest.c
+ $(AM_V_GEN) + (echo '[NAME]' && sed 's@/* *@@; s/-/\-/; q' $S/rest.c) | + $(HELP2MAN) -i - -S '$(PACKAGE) $(VERSION)' ../iwhd | + sed 's/^.B info .*/.B info FIXME/' > $@-t && mv $@-t $@
-----------------------------------------------------------------------
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months
[repo.or.cz] iwhd.git branch master updated: v0.0-207-g3a8570e
by Jeff Darcy
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, master has been updated
via 3a8570e05e1e906435c97f456150ec8683b35c91 (commit)
via e8e1e84c9af5996630f65b9bf0b9dbe1108092e9 (commit)
from 8e27a1a5623d6fe674ebcaefa5ae43cae372873f (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/3a8570e05e1e906435c97f456150ec8683b35c91
commit 3a8570e05e1e906435c97f456150ec8683b35c91
Author: Jeff Darcy <jdarcy(a)redhat.com>
Date: Tue Oct 19 21:10:49 2010 -0400
Fix two pipe-initialization races that occur in replication.
Turns out there were two race conditions, either of which could lead to
a replication task hanging. In the first, the consumer thread could
potentially run before the pipe_shared structure was re-initialized in
the producer. In the second, the producer could post the first chunk
before the consumer initialized its pipe_private, so the sequence
numbers would be off. That's kind of ironic, since the sequence number
isn't strictly necessary and is only there to guard against a whole
different class of synchronization problems (for which purpose I think
it should remain). Here's a brief summary.
* replica.c: moved re-initialization of pipe_shared to be before thread
start (race #1)
* mpipe.c: changed initialization of pp->sequence in pipe_init_private
(race #2)
* iwh.h: added PID to DPRINTF to distinguish parent/child output
* backend.c: fixed bytes==0 behavior in fs_put_child (unrelated)
* rest.c: fixed pipe_prod_wait_init check in proxy_put_data (unrelated)
diff --git a/backend.c b/backend.c
index a2972d1..502ce14 100644
--- a/backend.c
+++ b/backend.c
@@ -1189,24 +1189,24 @@ fs_put_child (void * ctx)
pipe_cons_siginit(ps, 0);
while (pipe_cons_wait(pp)) {
- offset = 0;
- do {
+ for (offset = 0; offset < ps->data_len; offset += bytes) {
bytes = write(fd,
ps->data_ptr+offset,ps->data_len-offset);
if (bytes <= 0) {
if (bytes < 0) {
error (0, errno, "%s: write failed",
file);
+ pipe_cons_signal(pp, errno);
}
- pipe_cons_signal(pp, errno);
- goto done;
+ else {
+ pipe_cons_signal(pp, ENOSPC);
+ }
+ break;
}
- offset += bytes;
- } while (offset < ps->data_len);
+ }
pipe_cons_signal(pp, 0);
}
-done:
close(fd);
DPRINTF("%s returningn",__func__);
diff --git a/iwh.h b/iwh.h
index a97322d..d6475de 100644
--- a/iwh.h
+++ b/iwh.h
@@ -28,11 +28,11 @@ GLOBAL(const char *, db_host, "localhost");
GLOBAL(unsigned short, db_port, 0);
GLOBAL(const char *, me, "here");
-#define DPRINTF(fmt,args...) do { - if (verbose) { - printf(fmt,##args); - fflush(stdout); - } +#define DPRINTF(fmt,args...) do { + if (verbose) { + printf("%d " fmt,getpid(),##args); + fflush(stdout); + } } while (0)
#ifndef __attribute__
diff --git a/mpipe.c b/mpipe.c
index 0570316..46b3ad2 100644
--- a/mpipe.c
+++ b/mpipe.c
@@ -51,7 +51,12 @@ pipe_init_private (pipe_shared *ps)
pp = malloc(sizeof(*pp));
if (pp) {
pp->shared = ps;
- pp->sequence = ps->sequence + 1;
+ /*
+ * The producer might already have posted #1, so we can't use
+ * ps->sequence+1. This precludes consumers joining
+ * mid-stream, but that was never a goal anyway.
+ */
+ pp->sequence = 1;
pp->offset = 0;
}
return pp;
@@ -63,6 +68,7 @@ pipe_cons_wait (pipe_private *pp)
pipe_shared *ps = pp->shared;
int rc;
+ pp->offset = 0;
pthread_mutex_lock(&ps->lock);
while (ps->sequence != pp->sequence) {
@@ -212,4 +218,5 @@ pipe_prod_finish (pipe_shared *ps)
ps->cons_total,ps->cons_done,ps->cons_error);
}
pthread_mutex_unlock(&ps->lock);
+ DPRINTF("producer finished with sequence %ldn",ps->sequence);
}
diff --git a/replica.c b/replica.c
index 6170a83..4376d0a 100644
--- a/replica.c
+++ b/replica.c
@@ -95,13 +95,6 @@ proxy_repl_cons (void *ctx)
pipe_private *pp;
void *rc;
- /*
- * Do a full initialization here, not just in the rest. It's
- * necessary in the oddball case where we're re-replicating as
- * a result of an attribute/policy change, and it's not harmful
- * in the normal case where we're actually storing a new file.
- */
- pipe_init_shared(&ms->pipe,ms,1);
pp = pipe_init_private(&ms->pipe);
if (!pp) {
pipe_cons_siginit(&ms->pipe,-1);
@@ -177,6 +170,7 @@ repl_worker (void *notused ATTRIBUTE_UNUSED)
repl_item *item;
pthread_t cons;
pthread_t prod;
+ my_state *ms;
for (;;) {
sem_wait(&queue_sema);
@@ -188,6 +182,14 @@ repl_worker (void *notused ATTRIBUTE_UNUSED)
}
pthread_mutex_unlock(&queue_lock);
+ /*
+ * Do a full initialization here, not just in the rest. It's
+ * necessary in the oddball case where we're re-replicating as
+ * a result of an attribute/policy change, and it's not harmful
+ * in the normal case where we're actually storing a new file.
+ */
+ ms = item->ms;
+ pipe_init_shared(&ms->pipe,ms,1);
switch (item->type) {
case REPL_PUT:
if (pipe(item->pipes) >= 0) {
diff --git a/rest.c b/rest.c
index d09e7c1..28bc401 100644
--- a/rest.c
+++ b/rest.c
@@ -463,7 +463,7 @@ proxy_put_data (void *cctx, struct MHD_Connection *conn, const char *url,
* out peace.
*/
rc = pipe_prod_wait_init(&ms->pipe);
- if (rc < 0) {
+ if (rc != 0) {
DPRINTF("producer wait failedn");
resp = MHD_create_response_from_data(0,NULL,
MHD_NO,MHD_NO);
http://repo.or.cz/w/iwhd.git/commit/e8e1e84c9af5996630f65b9bf0b9dbe1108092e9
commit e8e1e84c9af5996630f65b9bf0b9dbe1108092e9
Author: Jeff Darcy <jdarcy(a)redhat.com>
Date: Tue Oct 19 20:59:33 2010 -0400
Undo accidental reversal of wait_for_repl return values.
diff --git a/t/replication b/t/replication
index 78911cc..e9a26d5 100644
--- a/t/replication
+++ b/t/replication
@@ -47,8 +47,8 @@ api=http://localhost:$port
wait_for_repl() {
local n_req=$(curl -d op=rep_status $api) || return 1
case $n_req in
- '0 requests') return 1 ;;
- *) return 0 ;;
+ '0 requests') return 0 ;;
+ *) return 1 ;;
esac
}
bkt=$api/rbucket
-----------------------------------------------------------------------
Summary of changes:
backend.c | 14 +++++++-------
iwh.h | 10 +++++-----
mpipe.c | 9 ++++++++-
replica.c | 16 +++++++++-------
rest.c | 2 +-
t/replication | 4 ++--
6 files changed, 32 insertions(+), 23 deletions(-)
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months
[repo.or.cz] iwhd.git branch master updated: v0.0-205-g8e27a1a
by Jim Meyering
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, master has been updated
via 8e27a1a5623d6fe674ebcaefa5ae43cae372873f (commit)
from 0317fd51b2994b9c512122ce97092fd3d0252ffc (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/8e27a1a5623d6fe674ebcaefa5ae43cae372873f
commit 8e27a1a5623d6fe674ebcaefa5ae43cae372873f
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Oct 7 13:44:31 2010 +0200
add iwhd.spec.in and Makefile rules
With these, you can now run "make rpm" to invoke rpmbuild
on a just-created tarball.
diff --git a/.gitignore b/.gitignore
index c495020..e85dc40 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ iwhd
iwhd-*.tar.gz
iwhd-qparser.c
iwhd-qparser.h
+iwhd.spec
qlexer.c
stamp-h1
t/*.log
diff --git a/Makefile.am b/Makefile.am
index 60dce9a..5510cf1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -23,11 +23,18 @@ iwhd_YFLAGS = -d
SUBDIRS = t
ACLOCAL_AMFLAGS = -I ax
+# iwhd is short for Image WareHouse Daemon.
bin_PROGRAMS = iwhd
-EXTRA_DIST = iwhd-qparser.h
+
+EXTRA_DIST = + iwhd-qparser.h + iwhd.spec + iwhd.spec.in
+
BUILT_SOURCES = iwhd-qparser.h qlexer.c
-# iwhd is short for Image WareHouse Daemon.
+MOSTLYCLEANFILES =
+MAINTAINERCLEANFILES =
iwhd_SOURCES = auto.c @@ -51,6 +58,19 @@ iwhd_SOURCES =
EXTRA_iwhd_SOURCES = qlexer.l
+MOSTLYCLEANFILES += iwhd.spec
+MAINTAINERCLEANFILES += iwhd.spec
+iwhd.spec: iwhd.spec.in Makefile.am
+ rm -f $@-t $@
+ sed 's/@''VERSION@/$(VERSION)/' $< > $@-t
+ chmod a=r $@-t
+ mv $@-t $@
+
+.PHONY: rpm
+rpm: dist iwhd.spec
+ chmod 644 $(distdir).tar.gz
+ rpmbuild -ta $(distdir).tar.gz
+
iwhd_CPPFLAGS = $(HAIL_CFLAGS)
iwhd_LDADD = -lmongoclient @@ -65,6 +85,6 @@ iwhd_LDADD = $(GLIB2_LIB) $(HAIL_LIBS)
-MOSTLYCLEANFILES = qlexer.c
-MAINTAINERCLEANFILES = qlexer.c
+MOSTLYCLEANFILES += qlexer.c
+MAINTAINERCLEANFILES += qlexer.c
EXTRA_DIST += qlexer.c
diff --git a/iwhd.spec.in b/iwhd.spec.in
new file mode 100644
index 0000000..282370e
--- /dev/null
+++ b/iwhd.spec.in
@@ -0,0 +1,63 @@
+Name: iwhd
+Version: @VERSION@
+Release: 1%{?dist}
+Summary: Image WareHouse Daemon
+
+Group: System Environment/Libraries
+License: GPLv3
+
+# FIXME: this is just the gitweb URL. Do we need more?
+URL: http://repo.or.cz/w/iwhd.git
+
+# pulled from upstream git,
+# to recreate tarball, check out commit, then run "make dist"
+Source0: iwhd-%{version}.tar.gz
+
+BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
+
+BuildRequires: boost-devel
+BuildRequires: boost-filesystem
+BuildRequires: glib2-devel
+BuildRequires: hail-devel
+BuildRequires: jansson-devel
+BuildRequires: libcurl-devel
+BuildRequires: libmicrohttpd-devel
+BuildRequires: libxml2-devel
+BuildRequires: mongodb-devel
+BuildRequires: bison
+BuildRequires: flex
+BuildRequires: autoconf
+BuildRequires: automake
+BuildRequires: mongodb-server
+BuildRequires: help2man
+
+%description
+Deltacloud image-warehouse daemon
+
+%prep
+%setup -q
+
+%build
+%configure
+make %{?_smp_mflags}
+
+%install
+rm -rf %{buildroot}
+make install DESTDIR=%{buildroot}
+
+%check
+make -s check
+
+%clean
+rm -rf %{buildroot}
+
+%post
+
+%files
+%defattr(-,root,root,-)
+%doc AUTHORS COPYING README NEWS
+%{_bindir}/iwhd
+
+%changelog
+* Wed Oct 7 2010 Jim Meyering <meyering(a)redhat.com> - 0.90-1
+- Initial release.
-----------------------------------------------------------------------
Summary of changes:
.gitignore | 1 +
Makefile.am | 28 ++++++++++++++++++++++---
iwhd.spec.in | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 88 insertions(+), 4 deletions(-)
create mode 100644 iwhd.spec.in
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months
[repo.or.cz] iwhd.git branch master updated: v0.0-204-g0317fd5
by Jim Meyering
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, master has been updated
via 0317fd51b2994b9c512122ce97092fd3d0252ffc (commit)
via d28494103e69b75ca5a242b09eb761570d15f930 (commit)
via 2d0b629e6cf361f18e660df7419c66ae61c56355 (commit)
via 136c20fc5c20bc053f86c643d2863d8ceb116dac (commit)
via 7a1642252d00263da1b36237661fb310f9d9cee7 (commit)
via 8da2bda33280f84f2a209be74f3cb4abd9798ef9 (commit)
via 61be1a9c7d0e2756613470fb82e285c980635950 (commit)
via 319d8c1f35ff61956c5c319976b81fed70b24267 (commit)
via cc926cc887f194d8ec7c97e7905baa669fff185e (commit)
via c366f6de5cb002e3306197e8ef2249b3120c635b (commit)
via 8d267f6f44e8c64623f66dfbb73673297c2514d5 (commit)
via b3302bb0a5b82689d8c890cc703fd0efc55512b8 (commit)
via 43e90569e516a77ed71bc2d568e8a25e2e1bc15d (commit)
via 172ce552307317456a644868ad02aba5b3528ba8 (commit)
via 66864937990bf7de81e6e5e2fba6ebf521f109c3 (commit)
via e1f97c75f4afa180643691324fa0552877fd8454 (commit)
via cddd16da84f4beb975f9e96546ea7ad1a6557fb8 (commit)
via 31e05f1f8045bd38d47eeacfd09a4c27895b10db (commit)
via 90c6359047186d03e04a4e73e99d0c935e40be1a (commit)
via 41f6621794a607e2a8a5940d6fb2be22746d2cf1 (commit)
via 9d0990a469ada32886e0c09e98da498a5106b2fd (commit)
via 19f9c826b6a2e6ad5dc51f1e1c4030f1eac82553 (commit)
via 5ed3c7cb77b0d921759f9407dd17dbb9b2b54ba3 (commit)
via fd0cbe4410ec2b1ad831e418b472cc46fd4cacaf (commit)
from 9ca9c3d6bdd3d210b5c58fca4bc9c63aacbea78d (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/0317fd51b2994b9c512122ce97092fd3d0252ffc
commit 0317fd51b2994b9c512122ce97092fd3d0252ffc
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 16:36:45 2010 +0200
avoid NULL deref on failed strdup
* qlexer.l: Don't dereference NULL on failed strdup.
diff --git a/qlexer.l b/qlexer.l
index c51bad8..5f354df 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -17,10 +17,14 @@
%%
"[^"]*" { yytext[yyleng-1] = 0; yytext++;
- yylval_param->str = strdup(yytext); return T_STRING; }
-~[^~]*~ { yylval_param->str = strdup(yytext); return T_DATE; }
-[0-9]+ { yylval_param->str = strdup(yytext); return T_NUMBER; }
-[a-z_]+ { yylval_param->str = strdup(yytext); return T_ID; }
+ yylval_param->str = strdup(yytext);
+ return yylval_param->str ? T_STRING : T_INVALID; }
+~[^~]*~ { yylval_param->str = strdup(yytext);
+ return yylval_param->str ? T_DATE : T_INVALID; }
+[0-9]+ { yylval_param->str = strdup(yytext);
+ return yylval_param->str ? T_NUMBER : T_INVALID; }
+[a-z_]+ { yylval_param->str = strdup(yytext);
+ return yylval_param->str ? T_ID : T_INVALID; }
[=$#()<>.] { return yytext[0]; }
! { return T_NOT; }
&& { return T_AND; }
http://repo.or.cz/w/iwhd.git/commit/d28494103e69b75ca5a242b09eb761570d15f930
commit d28494103e69b75ca5a242b09eb761570d15f930
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 16:24:39 2010 +0200
xrealloc was not used; #if-0 it out
diff --git a/qparser.y b/qparser.y
index 4ddf5ff..e5bd1ad 100644
--- a/qparser.y
+++ b/qparser.y
@@ -44,6 +44,7 @@ xmalloc (size_t n)
return p;
}
+#if 0 // not used
/* Change the size of an allocated block of memory P to N bytes,
with error checking. */
static void *
@@ -54,6 +55,7 @@ xrealloc (void *p, size_t n)
xalloc_die ();
return p;
}
+#endif
/* Clone an object P of size S, with error checking. There's no need
for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
http://repo.or.cz/w/iwhd.git/commit/2d0b629e6cf361f18e660df7419c66ae61c56355
commit 2d0b629e6cf361f18e660df7419c66ae61c56355
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 14:02:33 2010 +0200
now that lexer calls strdup, free those strings
diff --git a/qparser.y b/qparser.y
index a82309a..4ddf5ff 100644
--- a/qparser.y
+++ b/qparser.y
@@ -82,6 +82,7 @@ make_number (const char *text)
tmp->as_num = strtoll(text,NULL,10);
tmp->resolved = NULL;
}
+ free ((void *) text);
return tmp;
}
@@ -96,6 +97,7 @@ make_string (const char *text, type_t t)
tmp->as_str = xstrdup(text);
tmp->resolved = NULL;
}
+ free ((void *) text);
return tmp;
}
@@ -133,6 +135,7 @@ make_link (value_t *left, const char *right)
char *copy;
copy = xstrdup(right);
+ free ((void *) right);
if (!copy) {
return NULL;
}
http://repo.or.cz/w/iwhd.git/commit/136c20fc5c20bc053f86c643d2863d8ceb116dac
commit 136c20fc5c20bc053f86c643d2863d8ceb116dac
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 12:37:57 2010 +0200
qlexer.l: rewrite not to need static var, at_eof.
diff --git a/qlexer.l b/qlexer.l
index 551d590..c51bad8 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -9,8 +9,6 @@
#include "iwhd-qparser.h"
#undef YY_DECL
#define YY_DECL extern int yylex (YYSTYPE *yylval_param, yyscan_t yyscanner)
-
-static int at_eof = 0;
%}
%option warn nounput noinput noyywrap
@@ -30,7 +28,7 @@ static int at_eof = 0;
[ tnr]+ { return T_SPACE; }
. { return T_INVALID; }
-<<EOF>> { at_eof = 1; yyterminate (); }
+<<EOF>> { yyterminate (); /* aka return 0; */ }
%%
@@ -50,9 +48,12 @@ main (int argc, char **argv)
YY_BUFFER_STATE buf
= yy_scan_string (""!@#" ~xxx~ 123 abc $#()<>=!&|.", scanner);
- do {
+ while (1) {
YYSTYPE v;
int t = yylex(&v, scanner);
+ if (t == 0)
+ break;
+
switch (t) {
case T_STRING:
if (!yytext[0]) {
@@ -72,7 +73,7 @@ main (int argc, char **argv)
default:
printf("%dn",t);
}
- } while (!at_eof);
+ }
yy_delete_buffer (buf, scanner);
yylex_destroy (scanner);
http://repo.or.cz/w/iwhd.git/commit/7a1642252d00263da1b36237661fb310f9d9cee7
commit 7a1642252d00263da1b36237661fb310f9d9cee7
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 12:31:33 2010 +0200
handle yylex_init failure
diff --git a/qparser.y b/qparser.y
index c7e2fe8..a82309a 100644
--- a/qparser.y
+++ b/qparser.y
@@ -495,7 +495,8 @@ value_t *
parse (const char *text)
{
yyscan_t scanner;
- yylex_init (&scanner);
+ if (yylex_init (&scanner))
+ error (0, errno, "failed to initialize query parser");
YY_BUFFER_STATE buf = yy_scan_string (text, scanner);
value_t *result;
value_t *r = yyparse (scanner, &result) == 0 ? result : NULL;
http://repo.or.cz/w/iwhd.git/commit/8da2bda33280f84f2a209be74f3cb4abd9798ef9
commit 8da2bda33280f84f2a209be74f3cb4abd9798ef9
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 12:20:45 2010 +0200
pure, almost
diff --git a/qlexer.l b/qlexer.l
index e394800..551d590 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -1,4 +1,3 @@
-%option warn nounput noinput noyywrap
%{
#include <config.h>
#include <stdio.h>
@@ -9,17 +8,21 @@
#include "iwhd-qparser.h"
#undef YY_DECL
-#define YY_DECL extern int yylex (YYSTYPE *lvalp)
+#define YY_DECL extern int yylex (YYSTYPE *yylval_param, yyscan_t yyscanner)
static int at_eof = 0;
%}
+%option warn nounput noinput noyywrap
+%option bison-bridge reentrant
+
%%
-"[^"]*" { yytext[yyleng-1] = 0; yytext++; return T_STRING; }
-~[^~]*~ { return T_DATE; }
-[0-9]+ { return T_NUMBER; }
-[a-z_]+ { return T_ID; }
+"[^"]*" { yytext[yyleng-1] = 0; yytext++;
+ yylval_param->str = strdup(yytext); return T_STRING; }
+~[^~]*~ { yylval_param->str = strdup(yytext); return T_DATE; }
+[0-9]+ { yylval_param->str = strdup(yytext); return T_NUMBER; }
+[a-z_]+ { yylval_param->str = strdup(yytext); return T_ID; }
[=$#()<>.] { return yytext[0]; }
! { return T_NOT; }
&& { return T_AND; }
@@ -42,12 +45,14 @@ yyerror (const char *msg)
int
main (int argc, char **argv)
{
-
- yy_scan_string(""!@#" ~xxx~ 123 abc $#()<>=!&|.");
+ yyscan_t scanner;
+ yylex_init (&scanner);
+ YY_BUFFER_STATE buf
+ = yy_scan_string (""!@#" ~xxx~ 123 abc $#()<>=!&|.", scanner);
do {
YYSTYPE v;
- int t = yylex(&v);
+ int t = yylex(&v, scanner);
switch (t) {
case T_STRING:
if (!yytext[0]) {
@@ -69,6 +74,9 @@ main (int argc, char **argv)
}
} while (!at_eof);
+ yy_delete_buffer (buf, scanner);
+ yylex_destroy (scanner);
+
return 0;
}
#endif
diff --git a/qparser.y b/qparser.y
index e8a60d0..c7e2fe8 100644
--- a/qparser.y
+++ b/qparser.y
@@ -19,7 +19,7 @@
#include <string.h>
#include <ctype.h>
-#define YY_DECL int yylex(YYSTYPE *);
+#define YY_DECL int yylex(YYSTYPE *, void *scanner);
YY_DECL
static void
@@ -141,16 +141,6 @@ make_link (value_t *left, const char *right)
}
/*
- * For some reason the bison-generated code isn't setting up yysv* properly,
- * so $n doesn't work with terminals. Be very careful to use this only
- * when the token we want is the last one in the current rule. If the
- * syntax ever gets complicated enough that we can't get away with that, we'll
- * just have to wrap all the terminals in singleton non-terminals just so that
- * $n will work in the real syntax rules.
- */
-extern char *yytext;
-
-/*
* IMO it's wrong for us to get into the bbool_expr=policy rule when there's
* a syntax error, but we do. The good news is that it's easy to free the
* erroneous tree properly this way. The bad news is that we need to wait
@@ -161,7 +151,7 @@ extern char *yytext;
static int syntax_error = 0;
void
-yyerror (value_t **result, const char *msg)
+yyerror (void *scanner, value_t **result, const char *msg)
{
// error (0, 0, "parse error: %sn", msg);
// FIXME do this via param, not file-global
@@ -170,6 +160,8 @@ yyerror (value_t **result, const char *msg)
%}
+%lex-param { yyscan_t scanner }
+%parse-param { void *scanner }
%parse-param { value_t **result }
%token <str> T_STRING T_COMP T_DATE T_ID T_LINK T_NUMBER T_OFIELD T_SFIELD
@@ -288,35 +280,35 @@ link_field:
}|
link_field '.' T_ID {
// printf("found LINK FIELDn");
- $$ = make_link($1,yytext);
+ $$ = make_link($1,$3);
};
field:
'$' T_ID {
// printf("found DOLLAR FIELDn");
- $$ = make_string(yytext,T_OFIELD);
+ $$ = make_string($2,T_OFIELD);
}|
'#' T_ID {
// printf("found WAFFLE FIELDn");
- $$ = make_string(yytext,T_SFIELD);
+ $$ = make_string($2,T_SFIELD);
};
literal:
T_NUMBER {
- // printf("found NUMBER %sn",yytext);
- $$ = make_number(yytext);
+ // printf("found NUMBER %sn",$1);
+ $$ = make_number($1);
}|
T_STRING {
- // printf("found STRING %sn",yytext);
- $$ = make_string(yytext,T_STRING);
+ // printf("found STRING %sn",$1);
+ $$ = make_string($1,T_STRING);
}|
T_DATE {
// printf("found DATEn");
- $$ = make_string(yytext,T_DATE);
+ $$ = make_string($1,T_DATE);
}|
T_ID {
- // printf("found ID %sn",yytext);
- $$ = make_string(yytext,T_ID);
+ // printf("found ID %sn",$1);
+ $$ = make_string($1,T_ID);
};
paren_expr:
@@ -502,10 +494,13 @@ free_value (value_t *v)
value_t *
parse (const char *text)
{
- yy_scan_string(text);
+ yyscan_t scanner;
+ yylex_init (&scanner);
+ YY_BUFFER_STATE buf = yy_scan_string (text, scanner);
value_t *result;
- value_t *r = yyparse (&result) == 0 ? result : NULL;
- yylex_destroy();
+ value_t *r = yyparse (scanner, &result) == 0 ? result : NULL;
+ yy_delete_buffer (buf, scanner);
+ yylex_destroy (scanner);
return r;
}
http://repo.or.cz/w/iwhd.git/commit/61be1a9c7d0e2756613470fb82e285c980635950
commit 61be1a9c7d0e2756613470fb82e285c980635950
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 11:16:05 2010 +0200
add beginnings of %union support
diff --git a/qparser.y b/qparser.y
index cb59065..e8a60d0 100644
--- a/qparser.y
+++ b/qparser.y
@@ -3,14 +3,21 @@
%{
#include <config.h>
+#include "query.h"
+#include "iwhd-qparser.h"
+%}
+
+%union {
+ char *str;
+ struct value_t *val;
+}
+
+%{
#include <error.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
-#define YYSTYPE value_t *
-#include "query.h"
-#include "iwhd-qparser.h"
#define YY_DECL int yylex(YYSTYPE *);
YY_DECL
@@ -165,10 +172,11 @@ yyerror (value_t **result, const char *msg)
%parse-param { value_t **result }
-%token T_STRING T_DATE T_NUMBER T_ID
-%token T_NOT T_AND T_OR
-%token T_SPACE T_INVALID
-%token T_OFIELD T_SFIELD T_COMP T_LINK
+%token <str> T_STRING T_COMP T_DATE T_ID T_LINK T_NUMBER T_OFIELD T_SFIELD
+%token T_NOT T_AND T_OR T_SPACE T_INVALID
+
+%type <val> atom bbool_expr comp_expr field
+%type <val> link_field literal paren_expr ubool_expr
%start policy
http://repo.or.cz/w/iwhd.git/commit/319d8c1f35ff61956c5c319976b81fed70b24267
commit 319d8c1f35ff61956c5c319976b81fed70b24267
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 11:01:54 2010 +0200
query.h: use struct value_t (same name as typedef)
This is required to allow bison to parse the incoming %union decl.
diff --git a/query.h b/query.h
index 83ad2b4..523dd91 100644
--- a/query.h
+++ b/query.h
@@ -42,15 +42,15 @@ typedef enum yytokentype type_t;
* a value_t, but for T_LINK it's a bare string.
* TBD: use a separate as_link union member for T_LINK.
*/
-typedef struct _value {
+typedef struct value_t {
type_t type;
union {
long long as_num;
char *as_str;
struct {
comp_t op;
- struct _value *left;
- struct _value *right;
+ struct value_t *left;
+ struct value_t *right;
} as_tree;
};
const char *resolved; /* saved result for T_OFIELD/T_SFIELD/T_LINK */
http://repo.or.cz/w/iwhd.git/commit/cc926cc887f194d8ec7c97e7905baa669fff185e
commit cc926cc887f194d8ec7c97e7905baa669fff185e
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 10:55:19 2010 +0200
add missing #define part of double-inclusion guard
diff --git a/query.h b/query.h
index 253e19b..83ad2b4 100644
--- a/query.h
+++ b/query.h
@@ -13,7 +13,8 @@
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
-#if !defined(_QUERY_H)
+#ifndef _QUERY_H
+#define _QUERY_H 1
#if defined(__CPLUSPLUS__) || defined(__cplusplus)
extern "C" {
http://repo.or.cz/w/iwhd.git/commit/c366f6de5cb002e3306197e8ef2249b3120c635b
commit c366f6de5cb002e3306197e8ef2249b3120c635b
Author: Jim Meyering <meyering(a)redhat.com>
Date: Mon Oct 18 10:16:44 2010 +0200
lex && and || as tokens, not "&" and "|"
There is no point in allowing spaces between the bytes
of these operators.
diff --git a/qlexer.l b/qlexer.l
index 41232a3..e394800 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -22,8 +22,8 @@ static int at_eof = 0;
[a-z_]+ { return T_ID; }
[=$#()<>.] { return yytext[0]; }
! { return T_NOT; }
-& { return T_AND; }
-| { return T_OR; }
+&& { return T_AND; }
+|| { return T_OR; }
[ tnr]+ { return T_SPACE; }
. { return T_INVALID; }
diff --git a/qparser.y b/qparser.y
index bb6e760..cb59065 100644
--- a/qparser.y
+++ b/qparser.y
@@ -189,13 +189,13 @@ bbool_expr:
// printf("promoting ubool_expr to bbool_exprn");
$$ = $1;
}|
- bbool_expr T_AND T_AND ubool_expr {
+ bbool_expr T_AND ubool_expr {
// printf("found AND expressionn");
- $$ = make_tree(T_AND,$1,$4);
+ $$ = make_tree(T_AND,$1,$3);
}|
- bbool_expr T_OR T_OR ubool_expr {
+ bbool_expr T_OR ubool_expr {
// printf("found OR expressionn");
- $$ = make_tree(T_OR,$1,$4);
+ $$ = make_tree(T_OR,$1,$3);
}|
bbool_expr T_SPACE {
$$ = $1;
http://repo.or.cz/w/iwhd.git/commit/8d267f6f44e8c64623f66dfbb73673297c2514d5
commit 8d267f6f44e8c64623f66dfbb73673297c2514d5
Author: Jeff Darcy <jdarcy(a)redhat.com>
Date: Fri Oct 15 12:01:20 2010 -0400
Add query.h comments back in.
diff --git a/query.h b/query.h
index b726632..253e19b 100644
--- a/query.h
+++ b/query.h
@@ -21,14 +21,26 @@ extern "C" {
#include "iwhd-qparser.h"
+/*
+ * Comparisons are all the same type to the parser, but when it comes to
+ * evaluation we need to know the difference so we use these subtypes.
+ */
typedef enum {
C_LESSTHAN, C_LESSOREQ,
C_EQUAL, C_DIFFERENT,
C_GREATEROREQ, C_GREATERTHAN
} comp_t;
+/* The actual values are generated by the parser. */
typedef enum yytokentype type_t;
+/*
+ * Universal AST object. T_NUMBER uses as_num, and some day T_DATE might as
+ * well. Several types (T_STRING, T_ID, T_*FIELD) all use as_str. The rest
+ * use as_tree, but there's a caveat. In most cases as_tree.right really is
+ * a value_t, but for T_LINK it's a bare string.
+ * TBD: use a separate as_link union member for T_LINK.
+ */
typedef struct _value {
type_t type;
union {
@@ -43,12 +55,27 @@ typedef struct _value {
const char *resolved; /* saved result for T_OFIELD/T_SFIELD/T_LINK */
} value_t;
+/*
+ * In a higher-level language, this would be a method pointer. It's just
+ * a pointer to a function plus a little piece of the caller's context (in
+ * the replication-policy case it's the current bucket and key) so that we
+ * can do concurrent evaluations with separate contexts.
+ */
typedef struct {
const char *(*func) (void *, const char *);
void *ctx;
} getter_t;
#define CALL_GETTER(g,x) g->func(g->ctx,x)
+/*
+ * In the normal case a caller would invoke parse once, eval multiple times,
+ * and free_value once. print_value is just for debugging/testing.
+ * TBD: make parse reentrant (eval already is, free_value doesn't need to be.
+ * Unfortunately, a quick scan of generated code and information on the web
+ * seems to indicate that even a "reentrant" bison parser only encapsulates
+ * user state and still relies quite a bit on internal globals. That might
+ * mean that we just have to put a lock around it instead.
+ */
int eval (const value_t *expr,
const getter_t *oget, const getter_t *sget);
void free_value (value_t *);
http://repo.or.cz/w/iwhd.git/commit/b3302bb0a5b82689d8c890cc703fd0efc55512b8
commit b3302bb0a5b82689d8c890cc703fd0efc55512b8
Author: Jim Meyering <meyering(a)redhat.com>
Date: Fri Oct 15 15:07:19 2010 +0200
build: ensure we use only Flex
diff --git a/qlexer.l b/qlexer.l
index c4d3a63..41232a3 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -3,6 +3,10 @@
#include <config.h>
#include <stdio.h>
+#ifndef FLEX_SCANNER
+# error This scanner must be made using flex, not lex.
+#endif
+
#include "iwhd-qparser.h"
#undef YY_DECL
#define YY_DECL extern int yylex (YYSTYPE *lvalp)
http://repo.or.cz/w/iwhd.git/commit/43e90569e516a77ed71bc2d568e8a25e2e1bc15d
commit 43e90569e516a77ed71bc2d568e8a25e2e1bc15d
Author: Jim Meyering <meyering(a)redhat.com>
Date: Fri Oct 15 14:24:21 2010 +0200
qlexer.l: simplify
* qlexer.l: Include <config.h> first.
Use a few %options.
Use <<EOF>> rather than yywrap.
diff --git a/qlexer.l b/qlexer.l
index 7ae9e87..c4d3a63 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -1,9 +1,13 @@
+%option warn nounput noinput noyywrap
%{
+#include <config.h>
#include <stdio.h>
#include "iwhd-qparser.h"
#undef YY_DECL
#define YY_DECL extern int yylex (YYSTYPE *lvalp)
+
+static int at_eof = 0;
%}
%%
@@ -19,15 +23,10 @@
[ tnr]+ { return T_SPACE; }
. { return T_INVALID; }
-%%
+<<EOF>> { at_eof = 1; yyterminate (); }
-static int at_eof = 0;
-int
-yywrap (void)
-{
- return ++at_eof;
-}
+%%
#if defined(UNIT_TEST)
static void
http://repo.or.cz/w/iwhd.git/commit/172ce552307317456a644868ad02aba5b3528ba8
commit 172ce552307317456a644868ad02aba5b3528ba8
Author: Jim Meyering <meyering(a)redhat.com>
Date: Fri Oct 15 13:05:44 2010 +0200
avoid undefined-yydecl warning
diff --git a/qlexer.l b/qlexer.l
index bd2e196..7ae9e87 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -2,6 +2,7 @@
#include <stdio.h>
#include "iwhd-qparser.h"
+#undef YY_DECL
#define YY_DECL extern int yylex (YYSTYPE *lvalp)
%}
diff --git a/qparser.y b/qparser.y
index c52c2ba..bb6e760 100644
--- a/qparser.y
+++ b/qparser.y
@@ -12,6 +12,9 @@
#include "query.h"
#include "iwhd-qparser.h"
+#define YY_DECL int yylex(YYSTYPE *);
+YY_DECL
+
static void
xalloc_die (void)
{
http://repo.or.cz/w/iwhd.git/commit/66864937990bf7de81e6e5e2fba6ebf521f109c3
commit 66864937990bf7de81e6e5e2fba6ebf521f109c3
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Oct 14 18:00:11 2010 +0200
use literals in bison
diff --git a/qlexer.l b/qlexer.l
index 33c86a6..bd2e196 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -11,17 +11,10 @@
~[^~]*~ { return T_DATE; }
[0-9]+ { return T_NUMBER; }
[a-z_]+ { return T_ID; }
-$ { return T_DOLLAR; }
-# { return T_WAFFLE; }
-( { return T_LPAREN; }
-) { return T_RPAREN; }
-< { return T_LESS; }
-> { return T_GREATER; }
-= { return T_EQUAL; }
+[=$#()<>.] { return yytext[0]; }
! { return T_NOT; }
& { return T_AND; }
| { return T_OR; }
-. { return T_DOT; }
[ tnr]+ { return T_SPACE; }
. { return T_INVALID; }
diff --git a/qparser.y b/qparser.y
index 1f3a389..c52c2ba 100644
--- a/qparser.y
+++ b/qparser.y
@@ -163,9 +163,6 @@ yyerror (value_t **result, const char *msg)
%parse-param { value_t **result }
%token T_STRING T_DATE T_NUMBER T_ID
-%token T_DOLLAR T_WAFFLE T_DOT
-%token T_LPAREN T_RPAREN
-%token T_LESS T_GREATER T_EQUAL
%token T_NOT T_AND T_OR
%token T_SPACE T_INVALID
%token T_OFIELD T_SFIELD T_COMP T_LINK
@@ -224,27 +221,27 @@ comp_expr:
// printf("promoting atom to comp_exprn");
$$ = $1;
}|
- atom T_LESS atom {
+ atom '<' atom {
// printf("found LESS THAN expressionn");
$$ = make_comp(C_LESSTHAN,$1,$3);
}|
- atom T_LESS T_EQUAL atom {
+ atom '<' '=' atom {
// printf("found LESS OR EQUAL expressionn");
$$ = make_comp(C_LESSOREQ,$1,$4);
}|
- atom T_EQUAL T_EQUAL atom {
+ atom '=' '=' atom {
// printf("found EQUAL expressionn");
$$ = make_comp(C_EQUAL,$1,$4);
}|
- atom T_NOT T_EQUAL atom {
+ atom T_NOT '=' atom {
// printf("found NOT EQUAL expressionn");
$$ = make_comp(C_DIFFERENT,$1,$4);
}|
- atom T_GREATER T_EQUAL atom {
+ atom '>' '=' atom {
// printf("found GREATER OR EQUAL expressionn");
$$ = make_comp(C_GREATEROREQ,$1,$4);
}|
- atom T_GREATER atom {
+ atom '>' atom {
// printf("found GREATER THAN expressionn");
$$ = make_comp(C_GREATERTHAN,$1,$3);
}|
@@ -278,17 +275,17 @@ link_field:
// printf("promoting field to link_fieldn");
$$ = $1;
}|
- link_field T_DOT T_ID {
+ link_field '.' T_ID {
// printf("found LINK FIELDn");
$$ = make_link($1,yytext);
};
field:
- T_DOLLAR T_ID {
+ '$' T_ID {
// printf("found DOLLAR FIELDn");
$$ = make_string(yytext,T_OFIELD);
}|
- T_WAFFLE T_ID {
+ '#' T_ID {
// printf("found WAFFLE FIELDn");
$$ = make_string(yytext,T_SFIELD);
};
@@ -312,7 +309,7 @@ literal:
};
paren_expr:
- T_LPAREN bbool_expr T_RPAREN {
+ '(' bbool_expr ')' {
// printf("found PAREN expressionn");
$$ = $2;
};
http://repo.or.cz/w/iwhd.git/commit/e1f97c75f4afa180643691324fa0552877fd8454
commit e1f97c75f4afa180643691324fa0552877fd8454
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Oct 14 17:01:43 2010 +0200
static and const
diff --git a/qlexer.l b/qlexer.l
index c90bf15..33c86a6 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -27,7 +27,7 @@
%%
-int at_eof = 0;
+static int at_eof = 0;
int
yywrap (void)
@@ -37,7 +37,7 @@ yywrap (void)
#if defined(UNIT_TEST)
static void
-yyerror (char *msg)
+yyerror (const char *msg)
{
printf("%s: %sn",__func__,msg);
}
diff --git a/qparser.y b/qparser.y
index 82f9774..1f3a389 100644
--- a/qparser.y
+++ b/qparser.y
@@ -1,3 +1,6 @@
+%define api.pure
+%error-verbose
+
%{
#include <config.h>
#include <error.h>
@@ -59,7 +62,7 @@ xstrdup (char const *string)
}
/* TBD: use separate function to parse dates differently */
-value_t *
+static value_t *
make_number (const char *text)
{
value_t *tmp = malloc(sizeof(*tmp));
@@ -73,7 +76,7 @@ make_number (const char *text)
return tmp;
}
-value_t *
+static value_t *
make_string (const char *text, type_t t)
{
value_t *tmp = malloc(sizeof(*tmp));
@@ -87,23 +90,23 @@ make_string (const char *text, type_t t)
return tmp;
}
-value_t *
-make_tree (type_t t, value_t *left, value_t *right)
+static value_t *
+make_tree (type_t t, const value_t *left, const value_t *right)
{
value_t *tmp = malloc(sizeof(*tmp));
if (tmp) {
tmp->type = t;
- tmp->as_tree.left = left;
- tmp->as_tree.right = right;
+ tmp->as_tree.left = (value_t *) left;
+ tmp->as_tree.right = (value_t *) right;
tmp->resolved = NULL;
}
return tmp;
}
-value_t *
-make_comp (comp_t c, value_t *left, value_t *right)
+static value_t *
+make_comp (comp_t c, const value_t *left, const value_t *right)
{
value_t *tmp = make_tree(T_COMP,left,right);
@@ -114,8 +117,8 @@ make_comp (comp_t c, value_t *left, value_t *right)
return tmp;
}
-value_t *
-make_link (value_t *left, char *right)
+static value_t *
+make_link (value_t *left, const char *right)
{
char *copy;
@@ -157,7 +160,6 @@ yyerror (value_t **result, const char *msg)
%}
-%define api.pure
%parse-param { value_t **result }
%token T_STRING T_DATE T_NUMBER T_ID
@@ -318,7 +320,7 @@ paren_expr:
%%
#if defined PARSER_UNIT_TEST
-struct { char *name; char *value; } hacked_obj_fields[] = {
+static const struct { char *name; char *value; } hacked_obj_fields[] = {
/* Fake object fields for generic unit testing. */
{ "a", "2" }, { "b", "7" }, { "c", "11" },
/* This one's here to test links (e.g. $template.owner.name). */
@@ -327,7 +329,7 @@ struct { char *name; char *value; } hacked_obj_fields[] = {
};
/* Fake out the eval code for unit testing. */
-const char *
+static const char *
unit_oget_func (void * notused, const char *text)
{
int i;
@@ -340,18 +342,18 @@ unit_oget_func (void * notused, const char *text)
return NULL;
}
-getter_t unit_oget = { unit_oget_func };
+static const getter_t unit_oget = { unit_oget_func };
/*
* Same as above, but the site-field stuff is so similar to the object-field
* stuff that it's not worth exercising too much separately.
*/
-const char *
+static const char *
unit_sget_func (void * notused, const char *text)
{
return "never";
}
-getter_t unit_sget = { unit_sget_func };
+static const getter_t unit_sget = { unit_sget_func };
/* Fake links from an object/key tuple to an object/key string. */
struct { char *obj; char *key; char *value; } hacked_links[] = {
@@ -360,7 +362,7 @@ struct { char *obj; char *key; char *value; } hacked_links[] = {
{ NULL }
};
-char *
+static char *
follow_link (const char *object, const char *key)
{
unsigned int i;
@@ -381,7 +383,7 @@ follow_link (const char *object, const char *key)
extern char *follow_link (const char *object, const char *key);
#endif
-void
+static void
_print_value (const value_t *v, int level)
{
if (!v) {
@@ -505,7 +507,7 @@ parse (const char *text)
* and booleans.
*/
static const char *
-string_value (value_t *v, getter_t *oget, getter_t *sget)
+string_value (value_t *v, const getter_t *oget, const getter_t *sget)
{
const char *left;
@@ -537,7 +539,7 @@ string_value (value_t *v, getter_t *oget, getter_t *sget)
* Check whether a string looks like a simple decimal number. There's
* probably a library function for this somewhere.
*/
-int
+static int
is_ok_number (const char *a_str)
{
const char *p;
@@ -563,9 +565,9 @@ is_ok_number (const char *a_str)
* but the code is actually structured a different way to allow re-use of
* common operator-specific code at the end for both cases.
*/
-int
+static int
compare (value_t *left, comp_t op, value_t *right,
- getter_t *oget, getter_t *sget)
+ const getter_t *oget, const getter_t *sget)
{
const char *lstr;
const char *rstr;
@@ -652,7 +654,7 @@ compare (value_t *left, comp_t op, value_t *right,
*/
int
-eval (const value_t *v, getter_t *oget, getter_t *sget)
+eval (const value_t *v, const getter_t *oget, const getter_t *sget)
{
int res;
const char *str;
diff --git a/query.h b/query.h
index f7823e2..b726632 100644
--- a/query.h
+++ b/query.h
@@ -49,7 +49,8 @@ typedef struct {
} getter_t;
#define CALL_GETTER(g,x) g->func(g->ctx,x)
-int eval (const value_t *expr, getter_t *oget, getter_t *sget);
+int eval (const value_t *expr,
+ const getter_t *oget, const getter_t *sget);
void free_value (value_t *);
void print_value (const value_t *);
http://repo.or.cz/w/iwhd.git/commit/cddd16da84f4beb975f9e96546ea7ad1a6557fb8
commit cddd16da84f4beb975f9e96546ea7ad1a6557fb8
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Oct 14 16:43:06 2010 +0200
cast away "const" on free argument
diff --git a/qparser.y b/qparser.y
index c23c03e..82f9774 100644
--- a/qparser.y
+++ b/qparser.y
@@ -459,7 +459,7 @@ free_value (value_t *v)
printf("freeing resolved string "%s" (%p)n",
v->resolved, v->resolved);
}
- free(v->resolved);
+ free((void *)v->resolved);
switch (v->type) {
case T_STRING:
http://repo.or.cz/w/iwhd.git/commit/31e05f1f8045bd38d47eeacfd09a4c27895b10db
commit 31e05f1f8045bd38d47eeacfd09a4c27895b10db
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Oct 14 16:41:36 2010 +0200
qparser.y: Include <ctype.h> for use of isdigit
diff --git a/qparser.y b/qparser.y
index 81b2ef6..c23c03e 100644
--- a/qparser.y
+++ b/qparser.y
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#define YYSTYPE value_t *
#include "query.h"
#include "iwhd-qparser.h"
http://repo.or.cz/w/iwhd.git/commit/90c6359047186d03e04a4e73e99d0c935e40be1a
commit 90c6359047186d03e04a4e73e99d0c935e40be1a
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Oct 14 16:16:24 2010 +0200
apply Jeff's link-following change
diff --git a/qparser.y b/qparser.y
index d028098..81b2ef6 100644
--- a/qparser.y
+++ b/qparser.y
@@ -519,12 +519,14 @@ string_value (value_t *v, getter_t *oget, getter_t *sget)
case T_SFIELD:
return sget ? CALL_GETTER(sget,v->as_str) : NULL;
case T_LINK:
- left = string_value(v->as_tree.left,oget,sget);
- if (left) {
- return follow_link((char *)left,
- (char *)v->as_tree.right);
+ if (!v->resolved) {
+ left = string_value(v->as_tree.left,oget,sget);
+ if (left) {
+ v->resolved = follow_link((char *)left,
+ (char *)v->as_tree.right);
+ }
}
- /* Fall through. */
+ return v->resolved;
default:
return NULL;
}
http://repo.or.cz/w/iwhd.git/commit/41f6621794a607e2a8a5940d6fb2be22746d2cf1
commit 41f6621794a607e2a8a5940d6fb2be22746d2cf1
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Oct 14 16:07:33 2010 +0200
apply jeffs leak-fixing patch from master (manually merge 3 failed hunks)
diff --git a/qparser.y b/qparser.y
index 7902c90..d028098 100644
--- a/qparser.y
+++ b/qparser.y
@@ -66,6 +66,7 @@ make_number (const char *text)
if (tmp) {
tmp->type = T_NUMBER;
tmp->as_num = strtoll(text,NULL,10);
+ tmp->resolved = NULL;
}
return tmp;
@@ -79,6 +80,7 @@ make_string (const char *text, type_t t)
if (tmp) {
tmp->type = t;
tmp->as_str = xstrdup(text);
+ tmp->resolved = NULL;
}
return tmp;
@@ -93,6 +95,7 @@ make_tree (type_t t, value_t *left, value_t *right)
tmp->type = t;
tmp->as_tree.left = left;
tmp->as_tree.right = right;
+ tmp->resolved = NULL;
}
return tmp;
@@ -115,7 +118,7 @@ make_link (value_t *left, char *right)
{
char *copy;
- copy = strdup(right);
+ copy = xstrdup(right);
if (!copy) {
return NULL;
}
@@ -451,6 +454,12 @@ free_value (value_t *v)
return;
}
+ if (v->resolved) {
+ printf("freeing resolved string "%s" (%p)n",
+ v->resolved, v->resolved);
+ }
+ free(v->resolved);
+
switch (v->type) {
case T_STRING:
case T_OFIELD:
@@ -504,8 +513,7 @@ string_value (value_t *v, getter_t *oget, getter_t *sget)
return v->as_str;
case T_OFIELD:
if (!v->resolved) {
- v->resolved = oget
- ? CALL_GETTER(oget,v->as_str) : NULL;
+ v->resolved = oget ? CALL_GETTER(oget,v->as_str) : NULL;
}
return v->resolved;
case T_SFIELD:
http://repo.or.cz/w/iwhd.git/commit/9d0990a469ada32886e0c09e98da498a5106b2fd
commit 9d0990a469ada32886e0c09e98da498a5106b2fd
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Oct 14 16:02:08 2010 +0200
parse-test now passes
diff --git a/qparser.y b/qparser.y
index 32e7aac..7902c90 100644
--- a/qparser.y
+++ b/qparser.y
@@ -170,7 +170,6 @@ yyerror (value_t **result, const char *msg)
policy:
bbool_expr {
- printf("policy completen");
if (syntax_error) {
printf("bad policy!n");
}
@@ -314,6 +313,70 @@ paren_expr:
%%
+#if defined PARSER_UNIT_TEST
+struct { char *name; char *value; } hacked_obj_fields[] = {
+ /* Fake object fields for generic unit testing. */
+ { "a", "2" }, { "b", "7" }, { "c", "11" },
+ /* This one's here to test links (e.g. $template.owner.name). */
+ { "template", "templates/the_tmpl" },
+ { NULL }
+};
+
+/* Fake out the eval code for unit testing. */
+const char *
+unit_oget_func (void * notused, const char *text)
+{
+ int i;
+
+ for (i = 0; hacked_obj_fields[i].name; ++i) {
+ if (!strcmp(hacked_obj_fields[i].name,text)) {
+ return xstrdup(hacked_obj_fields[i].value);
+ }
+ }
+
+ return NULL;
+}
+getter_t unit_oget = { unit_oget_func };
+
+/*
+ * Same as above, but the site-field stuff is so similar to the object-field
+ * stuff that it's not worth exercising too much separately.
+ */
+const char *
+unit_sget_func (void * notused, const char *text)
+{
+ return "never";
+}
+getter_t unit_sget = { unit_sget_func };
+
+/* Fake links from an object/key tuple to an object/key string. */
+struct { char *obj; char *key; char *value; } hacked_links[] = {
+ { "templates/the_tmpl", "owner", "users/the_user" },
+ { "users/the_user", "name", "Jeff Darcy" },
+ { NULL }
+};
+
+char *
+follow_link (const char *object, const char *key)
+{
+ unsigned int i;
+
+ for (i = 0; hacked_links[i].obj; ++i) {
+ if (strcmp(object,hacked_links[i].obj)) {
+ continue;
+ }
+ if (strcmp(key,hacked_links[i].key)) {
+ continue;
+ }
+ return hacked_links[i].value;
+ }
+
+ return NULL;
+}
+#else
+extern char *follow_link (const char *object, const char *key);
+#endif
+
void
_print_value (const value_t *v, int level)
{
@@ -330,7 +393,7 @@ _print_value (const value_t *v, int level)
printf("%*sSTRING %sn",level,"",v->as_str);
break;
case T_OFIELD:
-#if defined(UNIT_TEST)
+#if defined PARSER_UNIT_TEST
printf("%*sOBJECT FIELD %s (%s)n",level,"",v->as_str,
unit_oget_func(NULL,v->as_str));
#else
@@ -338,7 +401,7 @@ _print_value (const value_t *v, int level)
#endif
break;
case T_SFIELD:
-#if defined(UNIT_TEST)
+#if defined PARSER_UNIT_TEST
printf("%*sSERVER FIELD %s (%s)n",level,"",v->as_str,
unit_sget_func(NULL,v->as_str));
#else
@@ -426,10 +489,208 @@ parse (const char *text)
return r;
}
+/*
+ * Return the string value of an expression for comparison or display, iff
+ * all component parts are string-valued themselves. That excludes numbers
+ * and booleans.
+ */
+static const char *
+string_value (value_t *v, getter_t *oget, getter_t *sget)
+{
+ const char *left;
+
+ switch (v->type) {
+ case T_STRING:
+ return v->as_str;
+ case T_OFIELD:
+ if (!v->resolved) {
+ v->resolved = oget
+ ? CALL_GETTER(oget,v->as_str) : NULL;
+ }
+ return v->resolved;
+ case T_SFIELD:
+ return sget ? CALL_GETTER(sget,v->as_str) : NULL;
+ case T_LINK:
+ left = string_value(v->as_tree.left,oget,sget);
+ if (left) {
+ return follow_link((char *)left,
+ (char *)v->as_tree.right);
+ }
+ /* Fall through. */
+ default:
+ return NULL;
+ }
+}
+
+/*
+ * Check whether a string looks like a simple decimal number. There's
+ * probably a library function for this somewhere.
+ */
+int
+is_ok_number (const char *a_str)
+{
+ const char *p;
+
+ if (!a_str) {
+ return 0;
+ }
+
+ for (p = a_str; *p; ++p) {
+ if (!isdigit(*p)) {
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/*
+ * Comparisons are a bit messy. If both sides are numbers, strings that look
+ * like numbers, or expressions that evaluate to numbers (booleans evaluate
+ * to 0/1), then we do a numeric comparison. Otherwise, if both sides
+ * evaluate to strings, we attempt a string comparison. That's the logic,
+ * but the code is actually structured a different way to allow re-use of
+ * common operator-specific code at the end for both cases.
+ */
+int
+compare (value_t *left, comp_t op, value_t *right,
+ getter_t *oget, getter_t *sget)
+{
+ const char *lstr;
+ const char *rstr;
+ int lval = 0; // solely to placate gcc
+ int rval;
+ int num_ok = 1;
+
+ lstr = string_value(left,oget,sget);
+ rstr = string_value(right,oget,sget);
+
+ if (left->type == T_NUMBER) {
+ lval = left->as_num;
+ }
+ else if (lstr) {
+ if (is_ok_number(lstr)) {
+ lval = strtoll(lstr,NULL,0);
+ }
+ else {
+ num_ok = 0;
+ }
+ }
+ else {
+ lval = eval(left,oget,sget);
+ if (lval < 0) {
+ return lval;
+ }
+ }
+
+ if (right->type == T_NUMBER) {
+ rval = right->as_num;
+ }
+ else if (rstr) {
+ if (is_ok_number(rstr)) {
+ rval = strtoll(rstr,NULL,0);
+ }
+ else {
+ num_ok = 0;
+ }
+ }
+ else {
+ rval = eval(right,oget,sget);
+ if (rval < 0) {
+ return rval;
+ }
+ }
+
+ /*
+ * Strcmp returns -1/0/1, but -1 for us would mean an error and
+ * which of 0/1 we return depends on which comparison operatoer
+ * we're dealing with. Therefore, we stick the strcmp result on
+ * the left side and let the switch below do an operator-appropriate
+ * compare against zero on the right.
+ */
+ if (!num_ok) {
+ if (!lstr || !rstr) {
+ return -1;
+ }
+ lval = strcmp(lstr,rstr);
+ rval = 0;
+ }
+
+ switch (op) {
+ case C_LESSTHAN: return (lval < rval);
+ case C_LESSOREQ: return (lval <= rval);
+ case C_EQUAL: return (lval == rval);
+ case C_DIFFERENT: return (lval != rval);
+ case C_GREATEROREQ: return (lval >= rval);
+ case C_GREATERTHAN: return (lval > rval);
+ default:
+ return -1;
+ }
+}
+
+/*
+ * Evaluate an AST in the current context to one of:
+ * true=1
+ * false=0
+ * error=-1
+ * It's up to the caller whether error is functionally the same as false.
+ * Note that even T_NUMBER gets squeezed down to these three values. The
+ * only thing numbers are used for is comparing against other numbers to
+ * yield a boolean for the query or replication-policy code. If you want
+ * something that returns a number, this is the wrong language for it.
+ */
+
+int
+eval (const value_t *v, getter_t *oget, getter_t *sget)
+{
+ int res;
+ const char *str;
+
+ switch (v->type) {
+ case T_NUMBER:
+ return v->as_num != 0;
+ case T_STRING:
+ return v->as_str && *v->as_str;
+ case T_OFIELD:
+ str = CALL_GETTER(oget,v->as_str);
+ return str && *str;
+ case T_SFIELD:
+ str = CALL_GETTER(sget,v->as_str);
+ return str && *str;
+ case T_LINK:
+ str = string_value(v->as_tree.left,oget,sget);
+ if (str) {
+ str = follow_link(str,(char *)v->as_tree.right);
+ }
+ return str && *str;
+ case T_COMP:
+ return compare(v->as_tree.left,(comp_t)v->as_tree.op,
+ v->as_tree.right, oget, sget);
+ case T_NOT:
+ res = eval(v->as_tree.left,oget,sget);
+ return (res >= 0) ? !res : res;
+ case T_AND:
+ res = eval(v->as_tree.left,oget,sget);
+ if (res > 0) {
+ res = eval(v->as_tree.right,oget,sget);
+ }
+ return res;
+ case T_OR:
+ res = eval(v->as_tree.left,oget,sget);
+ if (res > 0) {
+ return res;
+ }
+ return eval(v->as_tree.right,oget,sget);
+ default:
+ return -1;
+ }
+}
+
#ifdef PARSER_UNIT_TEST
int
main (int argc, char **argv)
{
+ int fail = 0;
unsigned int i;
for (i = 1; i < argc; ++i)
{
@@ -437,22 +698,21 @@ main (int argc, char **argv)
if (!expr)
{
printf ("could not parse '%s'n", argv[i]);
+ fail = 1;
continue;
}
print_value (expr);
-#if 0
- char *str = string_value (expr, &unit_oget, &unit_sget);
+
+ const char *str = string_value (expr, &unit_oget, &unit_sget);
if (str)
{
printf ("s= %sn", str);
continue;
}
- res = eval (expr, &unit_oget, &unit_sget);
- printf ("d= %dn", res);
-#endif
+ printf ("d= %dn", eval (expr, &unit_oget, &unit_sget));
}
- return 0;
+ return fail;
}
#endif
http://repo.or.cz/w/iwhd.git/commit/19f9c826b6a2e6ad5dc51f1e1c4030f1eac82553
commit 19f9c826b6a2e6ad5dc51f1e1c4030f1eac82553
Author: Jim Meyering <meyering(a)redhat.com>
Date: Fri Oct 15 14:50:59 2010 +0200
build: rearrange things to use Bison/Flex; adapt; clean up
diff --git a/.gitignore b/.gitignore
index e032047..c495020 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,6 +15,11 @@ config.log
config.status
configure
iwhd
-query-orig.c
-query.c
+iwhd-*.tar.gz
+iwhd-qparser.c
+iwhd-qparser.h
+qlexer.c
stamp-h1
+t/*.log
+t/parser
+t/parser.c
diff --git a/Makefile.am b/Makefile.am
index ac88336..60dce9a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -18,11 +18,14 @@ AM_CFLAGS = -W -Wall -Wextra -Wno-unused -Wformat-security
AM_CPPFLAGS = -I/usr/include/glib-2.0 -I/usr/lib64/glib-2.0/include
+iwhd_YFLAGS = -d
+
SUBDIRS = t
ACLOCAL_AMFLAGS = -I ax
bin_PROGRAMS = iwhd
-EXTRA_DIST = query.leg
+EXTRA_DIST = iwhd-qparser.h
+BUILT_SOURCES = iwhd-qparser.h qlexer.c
# iwhd is short for Image WareHouse Daemon.
@@ -37,7 +40,7 @@ iwhd_SOURCES = mpipe.h replica.c replica.h - query.c + qparser.y query.h rest.c setup.c @@ -46,6 +49,8 @@ iwhd_SOURCES = template.c template.h
+EXTRA_iwhd_SOURCES = qlexer.l
+
iwhd_CPPFLAGS = $(HAIL_CFLAGS)
iwhd_LDADD = -lmongoclient @@ -60,18 +65,6 @@ iwhd_LDADD = $(GLIB2_LIB) $(HAIL_LIBS)
-# leg is a lexer/parser-generator
-# http://piumarta.com/software/peg/peg-0.1.4.tar.gz
-query-orig.c: query.leg
- leg < $(srcdir)/query.leg > $@-t && mv $@-t $@
-
-# Apply this patch to fix NULL-deref bugs in the generated query-orig.c:
-query.c: query-orig.c query.c.diff
- patch --fuzz=0 query-orig.c $(srcdir)/query.c.diff --output=$@-t
- mv $@-t $@
-
-BUILT_SOURCES = query.c
-CLEANFILES = query-orig.c
-MOSTLYCLEANFILES = query.c query-orig.c-t
-MAINTAINERCLEANFILES = query.c query-orig.c
-EXTRA_DIST += query.c.diff
+MOSTLYCLEANFILES = qlexer.c
+MAINTAINERCLEANFILES = qlexer.c
+EXTRA_DIST += qlexer.c
diff --git a/configure.ac b/configure.ac
index bd0609b..afbe4c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,10 +28,8 @@ AM_SILENT_RULES([yes]) # make --enable-silent-rules the default.
AC_PROG_CXX
AC_PROG_CC
AM_PROG_CC_C_O
-
-leg -V > /dev/null 2>&1 ||
- AC_MSG_ERROR([you need the leg program to build this code;
- <http://piumarta.com/software/peg/>])
+AC_PROG_YACC
+AC_PROG_LEX
AC_CHECK_LIB([curl], [curl_easy_init],
[CURL_LIB=-lcurl],
diff --git a/qlexer.l b/qlexer.l
index 73e685f..c90bf15 100644
--- a/qlexer.l
+++ b/qlexer.l
@@ -1,22 +1,13 @@
%{
#include <stdio.h>
-#if defined(UNIT_TEST)
-enum {
- T_STRING, T_DATE, T_NUMBER, T_ID,
- T_DOLLAR, T_WAFFLE, T_LPAREN, T_RPAREN,
- T_LESS, T_GREATER, T_EQUAL, T_NOT,
- T_AND, T_OR, T_DOT, T_SPACE,
- T_INVALID
-};
-#else
-#include "qparser.tab.h"
-#endif
+#include "iwhd-qparser.h"
+#define YY_DECL extern int yylex (YYSTYPE *lvalp)
%}
%%
-"[^"]*" { return T_STRING; }
+"[^"]*" { yytext[yyleng-1] = 0; yytext++; return T_STRING; }
~[^~]*~ { return T_DATE; }
[0-9]+ { return T_NUMBER; }
[a-z_]+ { return T_ID; }
@@ -54,12 +45,12 @@ yyerror (char *msg)
int
main (int argc, char **argv)
{
- int t;
yy_scan_string(""!@#" ~xxx~ 123 abc $#()<>=!&|.");
do {
- t = yylex();
+ YYSTYPE v;
+ int t = yylex(&v);
switch (t) {
case T_STRING:
if (!yytext[0]) {
diff --git a/qparser.y b/qparser.y
index 7df27a1..32e7aac 100644
--- a/qparser.y
+++ b/qparser.y
@@ -4,9 +4,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include "query.h"
#define YYSTYPE value_t *
-#include "qparser.h"
+#include "query.h"
+#include "iwhd-qparser.h"
static void
xalloc_die (void)
@@ -133,9 +133,6 @@ make_link (value_t *left, char *right)
*/
extern char *yytext;
-/* In a sane world, yyparse would return this. */
-value_t *cur_val;
-
/*
* IMO it's wrong for us to get into the bbool_expr=policy rule when there's
* a syntax error, but we do. The good news is that it's easy to free the
@@ -144,17 +141,21 @@ value_t *cur_val;
* ourselves) to figure out whether we got a valid tree or not.
* No, yynerrs doesn't seem to give the right answer.
*/
-int syntax_error = 0;
+static int syntax_error = 0;
void
-yyerror (char *msg)
+yyerror (value_t **result, const char *msg)
{
- printf("%s: %sn",__func__,msg);
- syntax_error = 1;
+ // error (0, 0, "parse error: %sn", msg);
+ // FIXME do this via param, not file-global
+ syntax_error = 1;
}
%}
+%define api.pure
+%parse-param { value_t **result }
+
%token T_STRING T_DATE T_NUMBER T_ID
%token T_DOLLAR T_WAFFLE T_DOT
%token T_LPAREN T_RPAREN
@@ -174,21 +175,21 @@ policy:
printf("bad policy!n");
}
else {
- cur_val = $1;
+ *result = $1;
}
};
bbool_expr:
ubool_expr {
- printf("promoting ubool_expr to bbool_exprn");
+ // printf("promoting ubool_expr to bbool_exprn");
$$ = $1;
}|
bbool_expr T_AND T_AND ubool_expr {
- printf("found AND expressionn");
+ // printf("found AND expressionn");
$$ = make_tree(T_AND,$1,$4);
}|
bbool_expr T_OR T_OR ubool_expr {
- printf("found OR expressionn");
+ // printf("found OR expressionn");
$$ = make_tree(T_OR,$1,$4);
}|
bbool_expr T_SPACE {
@@ -199,11 +200,11 @@ bbool_expr:
ubool_expr:
comp_expr {
- printf("promoting comp_expr to ubool_exprn");
+ // printf("promoting comp_expr to ubool_exprn");
$$ = $1;
}|
T_NOT comp_expr {
- printf("found NOT expressionn");
+ // printf("found NOT expressionn");
$$ = make_tree(T_NOT,$2,NULL);
}|
ubool_expr T_SPACE {
@@ -215,31 +216,31 @@ ubool_expr:
comp_expr:
atom {
- printf("promoting atom to comp_exprn");
+ // printf("promoting atom to comp_exprn");
$$ = $1;
}|
atom T_LESS atom {
- printf("found LESS THAN expressionn");
+ // printf("found LESS THAN expressionn");
$$ = make_comp(C_LESSTHAN,$1,$3);
}|
atom T_LESS T_EQUAL atom {
- printf("found LESS OR EQUAL expressionn");
+ // printf("found LESS OR EQUAL expressionn");
$$ = make_comp(C_LESSOREQ,$1,$4);
}|
atom T_EQUAL T_EQUAL atom {
- printf("found EQUAL expressionn");
+ // printf("found EQUAL expressionn");
$$ = make_comp(C_EQUAL,$1,$4);
}|
atom T_NOT T_EQUAL atom {
- printf("found NOT EQUAL expressionn");
+ // printf("found NOT EQUAL expressionn");
$$ = make_comp(C_DIFFERENT,$1,$4);
}|
atom T_GREATER T_EQUAL atom {
- printf("found GREATER OR EQUAL expressionn");
+ // printf("found GREATER OR EQUAL expressionn");
$$ = make_comp(C_GREATEROREQ,$1,$4);
}|
atom T_GREATER atom {
- printf("found GREATER THAN expressionn");
+ // printf("found GREATER THAN expressionn");
$$ = make_comp(C_GREATERTHAN,$1,$3);
}|
comp_expr T_SPACE {
@@ -250,15 +251,15 @@ comp_expr:
atom:
link_field {
- printf("promoting link_field to atomn");
+ // printf("promoting link_field to atomn");
$$ = $1;
}|
literal {
- printf("promoting literal to atomn");
+ // printf("promoting literal to atomn");
$$ = $1;
}|
paren_expr {
- printf("promoting paren_expr to atomn");
+ // printf("promoting paren_expr to atomn");
$$ = $1;
}|
atom T_SPACE {
@@ -269,45 +270,45 @@ atom:
link_field:
field {
- printf("promoting field to link_fieldn");
+ // printf("promoting field to link_fieldn");
$$ = $1;
}|
link_field T_DOT T_ID {
- printf("found LINK FIELDn");
+ // printf("found LINK FIELDn");
$$ = make_link($1,yytext);
};
field:
T_DOLLAR T_ID {
- printf("found DOLLAR FIELDn");
+ // printf("found DOLLAR FIELDn");
$$ = make_string(yytext,T_OFIELD);
}|
T_WAFFLE T_ID {
- printf("found WAFFLE FIELDn");
+ // printf("found WAFFLE FIELDn");
$$ = make_string(yytext,T_SFIELD);
};
literal:
T_NUMBER {
- printf("found NUMBER %sn",yytext);
+ // printf("found NUMBER %sn",yytext);
$$ = make_number(yytext);
}|
T_STRING {
- printf("found STRING %sn",yytext);
+ // printf("found STRING %sn",yytext);
$$ = make_string(yytext,T_STRING);
}|
T_DATE {
- printf("found DATEn");
+ // printf("found DATEn");
$$ = make_string(yytext,T_DATE);
}|
T_ID {
- printf("found ID %sn",yytext);
+ // printf("found ID %sn",yytext);
$$ = make_string(yytext,T_ID);
};
paren_expr:
T_LPAREN bbool_expr T_RPAREN {
- printf("found PAREN expressionn");
+ // printf("found PAREN expressionn");
$$ = $2;
};
@@ -413,39 +414,45 @@ free_value (value_t *v)
}
}
+#include "qlexer.c"
+
+value_t *
+parse (const char *text)
+{
+ yy_scan_string(text);
+ value_t *result;
+ value_t *r = yyparse (&result) == 0 ? result : NULL;
+ yylex_destroy();
+ return r;
+}
+
+#ifdef PARSER_UNIT_TEST
int
main (int argc, char **argv)
{
- char *data = "#a=="fubar"&&!($b.c.d<3)";
- char *edata = "gobbledy-gook";
-
- yy_scan_string(data);
- yyparse();
- if (cur_val) {
- if (!syntax_error) {
- print_value(cur_val);
- }
- else {
- printf("discarding erroneous parse treen");
- }
- free_value(cur_val);
- cur_val = NULL;
+ unsigned int i;
+ for (i = 1; i < argc; ++i)
+ {
+ value_t *expr = parse (argv[i]);
+ if (!expr)
+ {
+ printf ("could not parse '%s'n", argv[i]);
+ continue;
}
- yylex_destroy();
- yy_scan_string(edata);
- yyparse();
- if (cur_val) {
- if (!syntax_error) {
- print_value(cur_val);
- }
- else {
- printf("discarding erroneous parse treen");
- }
- free_value(cur_val);
- cur_val = NULL;
+ print_value (expr);
+#if 0
+ char *str = string_value (expr, &unit_oget, &unit_sget);
+ if (str)
+ {
+ printf ("s= %sn", str);
+ continue;
}
- yylex_destroy();
+ res = eval (expr, &unit_oget, &unit_sget);
+ printf ("d= %dn", res);
+#endif
+ }
- return 0;
+ return 0;
}
+#endif
diff --git a/query.h b/query.h
index 8189633..f7823e2 100644
--- a/query.h
+++ b/query.h
@@ -19,16 +19,15 @@
extern "C" {
#endif
+#include "iwhd-qparser.h"
+
typedef enum {
C_LESSTHAN, C_LESSOREQ,
C_EQUAL, C_DIFFERENT,
C_GREATEROREQ, C_GREATERTHAN
} comp_t;
-typedef enum {
- T_NUMBER, T_STRING, T_OFIELD, T_SFIELD,
- T_COMP, T_NOT, T_AND, T_OR, T_LINK
-} type_t;
+typedef enum yytokentype type_t;
typedef struct _value {
type_t type;
@@ -50,12 +49,12 @@ typedef struct {
} getter_t;
#define CALL_GETTER(g,x) g->func(g->ctx,x)
-
-value_t *parse (const char *text);
int eval (const value_t *expr, getter_t *oget, getter_t *sget);
void free_value (value_t *);
void print_value (const value_t *);
+value_t *parse (const char *text);
+
#if defined(__CPLUSPLUS__) || defined(__cplusplus)
}
#endif
diff --git a/t/Makefile.am b/t/Makefile.am
index 91f0ad4..c2a0af6 100644
--- a/t/Makefile.am
+++ b/t/Makefile.am
@@ -34,8 +34,8 @@ parser_CPPFLAGS = -I $(top_srcdir)
parser.c: Makefile.am
rm -f $@-t $@
- printf '#define UNIT_TEST 1n' > $@-t
- printf '#include "query.c"n' >> $@-t
+ printf '#define PARSER_UNIT_TEST 1n' > $@-t
+ printf '#include "iwhd-qparser.c"n' >> $@-t
chmod a=r $@-t
mv $@-t $@
http://repo.or.cz/w/iwhd.git/commit/5ed3c7cb77b0d921759f9407dd17dbb9b2b54ba3
commit 5ed3c7cb77b0d921759f9407dd17dbb9b2b54ba3
Author: Jim Meyering <meyering(a)redhat.com>
Date: Thu Oct 14 16:54:58 2010 +0200
remove query.leg and query.c.diff
* query.c.diff: Remove file.
* query.leg: Likewise.
diff --git a/query.c.diff b/query.c.diff
deleted file mode 100644
index 1442652..0000000
--- a/query.c.diff
+++ /dev/null
@@ -1,47 +0,0 @@
---- query-orig.c 2010-10-12 12:32:09.666434835 -0400
-+++ query.c 2010-10-12 12:32:09.692391504 -0400
-@@ -594,7 +594,7 @@ YY_LOCAL(int) yyrefill(void)
- while (yybuflen - yypos < 512)
- {
- yybuflen *= 2;
-- yybuf= realloc(yybuf, yybuflen);
-+ yybuf= xrealloc(yybuf, yybuflen);
- }
- YY_INPUT((yybuf + yypos), yyn, (yybuflen - yypos));
- if (!yyn) return 0;
-@@ -659,7 +659,7 @@ YY_LOCAL(void) yyDo(yyaction action, int
- while (yythunkpos >= yythunkslen)
- {
- yythunkslen *= 2;
-- yythunks= realloc(yythunks, sizeof(yythunk) * yythunkslen);
-+ yythunks= xrealloc(yythunks, sizeof(yythunk) * yythunkslen);
- }
- yythunks[yythunkpos].begin= begin;
- yythunks[yythunkpos].end= end;
-@@ -677,7 +677,7 @@ YY_LOCAL(int) yyText(int begin, int end)
- while (yytextlen < (yyleng - 1))
- {
- yytextlen *= 2;
-- yytext= realloc(yytext, yytextlen);
-+ yytext= xrealloc(yytext, yytextlen);
- }
- memcpy(yytext, yybuf + begin, yyleng);
- }
-@@ -1215,13 +1215,13 @@ YY_PARSE(int) YYPARSEFROM(yyrule yystart
- if (!yybuflen)
- {
- yybuflen= 1024;
-- yybuf= malloc(yybuflen);
-+ yybuf= xmalloc(yybuflen);
- yytextlen= 1024;
-- yytext= malloc(yytextlen);
-+ yytext= xmalloc(yytextlen);
- yythunkslen= 32;
-- yythunks= malloc(sizeof(yythunk) * yythunkslen);
-+ yythunks= xmalloc(sizeof(yythunk) * yythunkslen);
- yyvalslen= 32;
-- yyvals= malloc(sizeof(YYSTYPE) * yyvalslen);
-+ yyvals= xmalloc(sizeof(YYSTYPE) * yyvalslen);
- yybegin= yyend= yypos= yylimit= yythunkpos= 0;
- }
- yybegin= yyend= yypos;
diff --git a/query.leg b/query.leg
deleted file mode 100644
index 403f0d0..0000000
--- a/query.leg
+++ /dev/null
@@ -1,617 +0,0 @@
-%{
-/* Copyright (C) 2010 Red Hat, Inc.
-
- This program 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 of the License, or
- (at your option) any later version.
-
- This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <time.h>
-#include <error.h>
-#include "query.h"
-
-const char *arg_buf;
-int arg_off;
-int arg_len;
-value_t **cur_expr;
-
-static void
-xalloc_die (void)
-{
- error (EXIT_FAILURE, 0, "%s", "memory exhausted");
-
- /* The `noreturn' cannot be given to error, since it may return if
- its first argument is 0. To help compilers understand the
- xalloc_die does not return, call abort. Also, the abort is a
- safety feature if exit_failure is 0 (which shouldn't happen). */
- abort ();
-}
-
-/* Allocate N bytes of memory dynamically, with error checking. */
-static void *
-xmalloc (size_t n)
-{
- void *p = malloc (n);
- if (!p && n != 0)
- xalloc_die ();
- return p;
-}
-
-/* Change the size of an allocated block of memory P to N bytes,
- with error checking. */
-static void *
-xrealloc (void *p, size_t n)
-{
- p = realloc (p, n);
- if (!p && n != 0)
- xalloc_die ();
- return p;
-}
-
-/* Clone an object P of size S, with error checking. There's no need
- for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
- need for an arithmetic overflow check. */
-static void *
-xmemdup (void const *p, size_t s)
-{
- return memcpy (xmalloc (s), p, s);
-}
-
-/* Clone STRING. */
-static char *
-xstrdup (char const *string)
-{
- return xmemdup (string, strlen (string) + 1);
-}
-
-/* TBD: use separate function to parse dates differently */
-value_t *
-make_number (const char *text)
-{
- value_t *tmp = malloc(sizeof(*tmp));
-
- if (tmp) {
- tmp->type = T_NUMBER;
- tmp->as_num = strtoll(text,NULL,10);
- tmp->resolved = NULL;
- }
-
- return tmp;
-}
-
-value_t *
-make_string (const char *text, type_t t)
-{
- value_t *tmp = malloc(sizeof(*tmp));
-
- if (tmp) {
- tmp->type = t;
- tmp->as_str = xstrdup(text);
- tmp->resolved = NULL;
- }
-
- return tmp;
-}
-
-value_t *
-make_tree (type_t t, value_t *left, value_t *right)
-{
- value_t *tmp = malloc(sizeof(*tmp));
-
- if (tmp) {
- tmp->type = t;
- tmp->as_tree.left = left;
- tmp->as_tree.right = right;
- tmp->resolved = NULL;
- }
-
- return tmp;
-}
-
-value_t *
-make_comp (comp_t c, value_t *left, value_t *right)
-{
- value_t *tmp = make_tree(T_COMP,left,right);
-
- if (tmp) {
- tmp->as_tree.op = c;
- }
-
- return tmp;
-}
-
-value_t *
-make_link (value_t *left, value_t *right)
-{
- char *copy;
-
- copy = xstrdup((char *)right);
- if (!copy) {
- return NULL;
- }
-
- return make_tree(T_LINK,left,(value_t *)copy);
-}
-
-#if defined(UNIT_TEST)
-struct { char *name; char *value; } hacked_obj_fields[] = {
- /* Fake object fields for generic unit testing. */
- { "a", "2" }, { "b", "7" }, { "c", "11" },
- /* This one's here to test links (e.g. $template.owner.name). */
- { "template", "templates/the_tmpl" },
- { NULL }
-};
-
-/* Fake out the eval code for unit testing. */
-const char *
-unit_oget_func (void * notused, const char *text)
-{
- int i;
-
- for (i = 0; hacked_obj_fields[i].name; ++i) {
- if (!strcmp(hacked_obj_fields[i].name,text)) {
- return xstrdup(hacked_obj_fields[i].value);
- }
- }
-
- return NULL;
-}
-getter_t unit_oget = { unit_oget_func };
-
-/*
- * Same as above, but the site-field stuff is so similar to the object-field
- * stuff that it's not worth exercising too much separately.
- */
-const char *
-unit_sget_func (void * notused, const char *text)
-{
- return "never";
-}
-getter_t unit_sget = { unit_sget_func };
-
-/* Fake links from an object/key tuple to an object/key string. */
-struct { char *obj; char *key; char *value; } hacked_links[] = {
- { "templates/the_tmpl", "owner", "users/the_user" },
- { "users/the_user", "name", "Jeff Darcy" },
- { NULL }
-};
-
-char *
-follow_link (const char *object, const char *key)
-{
- unsigned int i;
-
- for (i = 0; hacked_links[i].obj; ++i) {
- if (strcmp(object,hacked_links[i].obj)) {
- continue;
- }
- if (strcmp(key,hacked_links[i].key)) {
- continue;
- }
- return hacked_links[i].value;
- }
-
- return NULL;
-}
-#else
-extern char *follow_link (const char *object, const char *key);
-#endif
-
-/*
- * Return the string value of an expression for comparison or display, iff
- * all component parts are string-valued themselves. That excludes numbers
- * and booleans.
- */
-const char *
-string_value (value_t *v, getter_t *oget, getter_t *sget)
-{
- const char *left;
-
- switch (v->type) {
- case T_STRING:
- return v->as_str;
- case T_OFIELD:
- if (!v->resolved) {
- v->resolved = oget
- ? CALL_GETTER(oget,v->as_str) : NULL;
- }
- return v->resolved;
- case T_SFIELD:
- return sget ? CALL_GETTER(sget,v->as_str) : NULL;
- case T_LINK:
- if (!v->resolved) {
- left = string_value(v->as_tree.left,oget,sget);
- if (left) {
- v->resolved = follow_link((char *)left,
- (char *)v->as_tree.right);
- }
- }
- return v->resolved;
- default:
- return NULL;
- }
-}
-
-/*
- * Check whether a string looks like a simple decimal number. There's
- * probably a library function for this somewhere.
- */
-int
-is_ok_number (const char *a_str)
-{
- const char *p;
-
- if (!a_str) {
- return 0;
- }
-
- for (p = a_str; *p; ++p) {
- if (!isdigit(*p)) {
- return 0;
- }
- }
-
- return 1;
-}
-
-/*
- * Comparisons are a bit messy. If both sides are numbers, strings that look
- * like numbers, or expressions that evaluate to numbers (booleans evaluate
- * to 0/1), then we do a numeric comparison. Otherwise, if both sides
- * evaluate to strings, we attempt a string comparison. That's the logic,
- * but the code is actually structured a different way to allow re-use of
- * common operator-specific code at the end for both cases.
- */
-int
-compare (value_t *left, comp_t op, value_t *right,
- getter_t *oget, getter_t *sget)
-{
- const char *lstr;
- const char *rstr;
- int lval = 0; // solely to placate gcc
- int rval;
- int num_ok = 1;
-
- lstr = string_value(left,oget,sget);
- rstr = string_value(right,oget,sget);
-
- if (left->type == T_NUMBER) {
- lval = left->as_num;
- }
- else if (lstr) {
- if (is_ok_number(lstr)) {
- lval = strtoll(lstr,NULL,0);
- }
- else {
- num_ok = 0;
- }
- }
- else {
- lval = eval(left,oget,sget);
- if (lval < 0) {
- return lval;
- }
- }
-
- if (right->type == T_NUMBER) {
- rval = right->as_num;
- }
- else if (rstr) {
- if (is_ok_number(rstr)) {
- rval = strtoll(rstr,NULL,0);
- }
- else {
- num_ok = 0;
- }
- }
- else {
- rval = eval(right,oget,sget);
- if (rval < 0) {
- return rval;
- }
- }
-
- /*
- * Strcmp returns -1/0/1, but -1 for us would mean an error and
- * which of 0/1 we return depends on which comparison operatoer
- * we're dealing with. Therefore, we stick the strcmp result on
- * the left side and let the switch below do an operator-appropriate
- * compare against zero on the right.
- */
- if (!num_ok) {
- if (!lstr || !rstr) {
- return -1;
- }
- lval = strcmp(lstr,rstr);
- rval = 0;
- }
-
- switch (op) {
- case C_LESSTHAN: return (lval < rval);
- case C_LESSOREQ: return (lval <= rval);
- case C_EQUAL: return (lval == rval);
- case C_DIFFERENT: return (lval != rval);
- case C_GREATEROREQ: return (lval >= rval);
- case C_GREATERTHAN: return (lval > rval);
- default:
- return -1;
- }
-}
-
-void
-_print_value (const value_t *v, int level)
-{
- if (!v) {
- printf("%*sNULLn",level,"");
- return;
- }
-
- switch (v->type) {
- case T_NUMBER:
- printf("%*sNUMBER %lldn",level,"",v->as_num);
- break;
- case T_STRING:
- printf("%*sSTRING %sn",level,"",v->as_str);
- break;
- case T_OFIELD:
-#if defined(UNIT_TEST)
- printf("%*sOBJECT FIELD %s (%s)n",level,"",v->as_str,
- unit_oget_func(NULL,v->as_str));
-#else
- printf("%*sOBJECT FIELD %sn",level,"",v->as_str);
-#endif
- break;
- case T_SFIELD:
-#if defined(UNIT_TEST)
- printf("%*sSERVER FIELD %s (%s)n",level,"",v->as_str,
- unit_sget_func(NULL,v->as_str));
-#else
- printf("%*sSERVER FIELD %sn",level,"",v->as_str);
-#endif
- break;
- case T_COMP:
- printf("%*sCOMPARISONn",level,"");
- _print_value(v->as_tree.left,level+2);
- _print_value(v->as_tree.right,level+2);
- break;
- case T_NOT:
- printf("%*sNOTn",level,"");
- _print_value(v->as_tree.left,level+2);
- break;
- case T_AND:
- printf("%*sANDn",level,"");
- _print_value(v->as_tree.left,level+2);
- _print_value(v->as_tree.right,level+2);
- break;
- case T_OR:
- printf("%*sORn",level,"");
- _print_value(v->as_tree.left,level+2);
- _print_value(v->as_tree.right,level+2);
- break;
- case T_LINK:
- printf("%*sLINKn",level,"");
- _print_value(v->as_tree.left,level+2);
- printf("%*sDEST FIELD %sn",level+2,"",
- (char *)v->as_tree.right);
- break;
- default:
- printf("%*sUNKNOWN %dn",level,"",v->type);
- }
-}
-
-void
-print_value (const value_t *v)
-{
- _print_value(v,0);
-}
-
-void
-free_value (value_t *v)
-{
- if (!v) {
- return;
- }
-
- free((char *)v->resolved);
-
- switch (v->type) {
- case T_STRING:
- case T_OFIELD:
- case T_SFIELD:
- free(v->as_str);
- free(v);
- break;
- case T_LINK:
- free_value(v->as_tree.left);
- free(v->as_tree.right);
- free(v);
- break;
- case T_COMP:
- case T_AND:
- case T_OR:
- free_value(v->as_tree.right);
- /* Fall through. */
- case T_NOT:
- free_value(v->as_tree.left);
- /* Fall through. */
- default:
- free(v);
- }
-}
-
-/*
- * Evaluate an AST in the current context to one of:
- * true=1
- * false=0
- * error=-1
- * It's up to the caller whether error is functionally the same as false.
- * Note that even T_NUMBER gets squeezed down to these three values. The
- * only thing numbers are used for is comparing against other numbers to
- * yield a boolean for the query or replication-policy code. If you want
- * something that returns a number, this is the wrong language for it.
- */
-
-int
-eval (const value_t *v, getter_t *oget, getter_t *sget)
-{
- int res;
- const char *str;
-
- switch (v->type) {
- case T_NUMBER:
- return v->as_num != 0;
- case T_STRING:
- return v->as_str && *v->as_str;
- case T_OFIELD:
- str = CALL_GETTER(oget,v->as_str);
- return str && *str;
- case T_SFIELD:
- str = CALL_GETTER(sget,v->as_str);
- return str && *str;
- case T_LINK:
- str = string_value(v->as_tree.left,oget,sget);
- if (str) {
- str = follow_link(str,(char *)v->as_tree.right);
- }
- return str && *str;
- case T_COMP:
- return compare(v->as_tree.left,(comp_t)v->as_tree.op,
- v->as_tree.right, oget, sget);
- case T_NOT:
- res = eval(v->as_tree.left,oget,sget);
- return (res >= 0) ? !res : res;
- case T_AND:
- res = eval(v->as_tree.left,oget,sget);
- if (res > 0) {
- res = eval(v->as_tree.right,oget,sget);
- }
- return res;
- case T_OR:
- res = eval(v->as_tree.left,oget,sget);
- if (res > 0) {
- return res;
- }
- return eval(v->as_tree.right,oget,sget);
- default:
- return -1;
- }
-}
-
-#define YY_INPUT(buf,result,max) { - result = (arg_off < arg_len) ? (*buf = arg_buf[arg_off++], 1) - : (arg_off == arg_len) ? (*buf = 'n', ++arg_off, 1) : 0; -}
-
-#define YYSTYPE value_t *
-%}
-
-Stmt = - BoolExpr - EOL { *cur_expr = $$; }
- | ( !EOL . )* EOL
-
-BoolExpr = l:NotExpr
- ( ( - AND - r:NotExpr )
- { $$ = l = make_tree(T_AND,l,r); }
- | ( - OR - r:NotExpr )
- { $$ = l = make_tree(T_OR,l,r); } )*
-
-NotExpr = CompExpr -
- | NOT - e:CompExpr - { $$ = make_tree(T_NOT,e,NULL); }
-
-CompExpr = l:Atom
- ( ( - LESS - r:Atom { $$ = make_comp(C_LESSTHAN,l,r); } )
- | ( - LESS EQUAL - r:Atom { $$ = make_comp(C_LESSOREQ,l,r); } )
- | ( - EQUAL EQUAL - r:Atom { $$ = make_comp(C_EQUAL,l,r); } )
- | ( - NOT EQUAL - r:Atom { $$ = make_comp(C_DIFFERENT,l,r); } )
- | ( - GREATER EQUAL - r:Atom { $$ = make_comp(C_GREATEROREQ,l,r); } )
- | ( - GREATER - r:Atom { $$ = make_comp(C_GREATERTHAN,l,r); } ) )?
-
-Atom = ( Literal | LinkField | ParenExpr )
-
-Literal = NUMBER | STRING | TIME
-
-LinkField = f:Field ( DOT i:ID { $$ = f = make_link(f,i); } )*
-
-Field = DOLLAR i:ID { $$ = make_string((char *)i,T_OFIELD); }
- | WAFFLE i:ID { $$ = make_string((char *)i,T_SFIELD); }
-
-ParenExpr = OPEN - v:BoolExpr - CLOSE - { $$ = v; }
-
-NUMBER = < [0-9]+ > { $$ = make_number(yytext); }
-STRING = '"' < [^"]* > '"' { $$ = make_string(yytext,T_STRING); }
-TIME = '~' < [^~]* > '~' { $$ = make_number(yytext); }
-ID = < [a-z_]+ > { $$ = (YYSTYPE)yytext; }
-DOLLAR = '$'
-WAFFLE = '#'
-OPEN = '('
-CLOSE = ')'
-LESS = '<'
-GREATER = '>'
-EQUAL = '='
-NOT = '!'
-AND = '&&'
-OR = '||'
-DOT = '.'
-
-- = [ t]*
-EOL = 'n' | 'rn' | 'r' | ';'
-
-%%
-
-/* TBD: This isn't thread safe. */
-value_t *
-parse (const char *text)
-{
- value_t *expr = NULL;
-
- arg_buf = text;
- arg_len = strlen(text);
- arg_off = 0;
- cur_expr = &expr;
-
- while (yyparse()) {
- }
-
- return expr;
-}
-
-#if defined(UNIT_TEST)
-int
-main (int argc, char **argv)
-{
- int i;
- value_t *expr;
- int res;
- const char *str;
- unsigned int failed = 0;
-
- for (i = 1; i < argc; ++i) {
- expr = parse(argv[i]);
- if (!expr) {
- printf("could not parse '%s'n",argv[i]);
- ++failed;
- continue;
- }
- print_value(expr);
- str = string_value(expr,&unit_oget,&unit_sget);
- if (str) {
- printf("s= %sn",str);
- continue;
- }
- res = eval(expr,&unit_oget,&unit_sget);
- printf("d= %dn",res);
- }
-
- return failed;
-}
-#endif
http://repo.or.cz/w/iwhd.git/commit/fd0cbe4410ec2b1ad831e418b472cc46fd4cacaf
commit fd0cbe4410ec2b1ad831e418b472cc46fd4cacaf
Author: Jeff Darcy <jdarcy(a)redhat.com>
Date: Tue Oct 12 17:18:16 2010 +0200
rewrite query parser using Bison, not peg/leg
* qparser.y: New file.
* qparser.l: New file.
diff --git a/qlexer.l b/qlexer.l
new file mode 100644
index 0000000..73e685f
--- /dev/null
+++ b/qlexer.l
@@ -0,0 +1,86 @@
+%{
+#include <stdio.h>
+
+#if defined(UNIT_TEST)
+enum {
+ T_STRING, T_DATE, T_NUMBER, T_ID,
+ T_DOLLAR, T_WAFFLE, T_LPAREN, T_RPAREN,
+ T_LESS, T_GREATER, T_EQUAL, T_NOT,
+ T_AND, T_OR, T_DOT, T_SPACE,
+ T_INVALID
+};
+#else
+#include "qparser.tab.h"
+#endif
+%}
+
+%%
+
+"[^"]*" { return T_STRING; }
+~[^~]*~ { return T_DATE; }
+[0-9]+ { return T_NUMBER; }
+[a-z_]+ { return T_ID; }
+$ { return T_DOLLAR; }
+# { return T_WAFFLE; }
+( { return T_LPAREN; }
+) { return T_RPAREN; }
+< { return T_LESS; }
+> { return T_GREATER; }
+= { return T_EQUAL; }
+! { return T_NOT; }
+& { return T_AND; }
+| { return T_OR; }
+. { return T_DOT; }
+[ tnr]+ { return T_SPACE; }
+. { return T_INVALID; }
+
+%%
+
+int at_eof = 0;
+
+int
+yywrap (void)
+{
+ return ++at_eof;
+}
+
+#if defined(UNIT_TEST)
+static void
+yyerror (char *msg)
+{
+ printf("%s: %sn",__func__,msg);
+}
+
+int
+main (int argc, char **argv)
+{
+ int t;
+
+ yy_scan_string(""!@#" ~xxx~ 123 abc $#()<>=!&|.");
+
+ do {
+ t = yylex();
+ switch (t) {
+ case T_STRING:
+ if (!yytext[0]) {
+ printf("EOFn");
+ break;
+ }
+ case T_DATE:
+ case T_NUMBER:
+ case T_ID:
+ printf("%d %sn",t,yytext);
+ break;
+ case T_SPACE:
+ break;
+ case T_INVALID:
+ printf("INVALID %cn",yytext[0]);
+ break;
+ default:
+ printf("%dn",t);
+ }
+ } while (!at_eof);
+
+ return 0;
+}
+#endif
diff --git a/qparser.y b/qparser.y
new file mode 100644
index 0000000..7df27a1
--- /dev/null
+++ b/qparser.y
@@ -0,0 +1,451 @@
+%{
+#include <config.h>
+#include <error.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "query.h"
+#define YYSTYPE value_t *
+#include "qparser.h"
+
+static void
+xalloc_die (void)
+{
+ error (EXIT_FAILURE, 0, "%s", "memory exhausted");
+
+ /* The `noreturn' cannot be given to error, since it may return if
+ its first argument is 0. To help compilers understand the
+ xalloc_die does not return, call abort. Also, the abort is a
+ safety feature if exit_failure is 0 (which shouldn't happen). */
+ abort ();
+}
+
+/* Allocate N bytes of memory dynamically, with error checking. */
+static void *
+xmalloc (size_t n)
+{
+ void *p = malloc (n);
+ if (!p && n != 0)
+ xalloc_die ();
+ return p;
+}
+
+/* Change the size of an allocated block of memory P to N bytes,
+ with error checking. */
+static void *
+xrealloc (void *p, size_t n)
+{
+ p = realloc (p, n);
+ if (!p && n != 0)
+ xalloc_die ();
+ return p;
+}
+
+/* Clone an object P of size S, with error checking. There's no need
+ for xnmemdup (P, N, S), since xmemdup (P, N * S) works without any
+ need for an arithmetic overflow check. */
+static void *
+xmemdup (void const *p, size_t s)
+{
+ return memcpy (xmalloc (s), p, s);
+}
+
+/* Clone STRING. */
+static char *
+xstrdup (char const *string)
+{
+ return xmemdup (string, strlen (string) + 1);
+}
+
+/* TBD: use separate function to parse dates differently */
+value_t *
+make_number (const char *text)
+{
+ value_t *tmp = malloc(sizeof(*tmp));
+
+ if (tmp) {
+ tmp->type = T_NUMBER;
+ tmp->as_num = strtoll(text,NULL,10);
+ }
+
+ return tmp;
+}
+
+value_t *
+make_string (const char *text, type_t t)
+{
+ value_t *tmp = malloc(sizeof(*tmp));
+
+ if (tmp) {
+ tmp->type = t;
+ tmp->as_str = xstrdup(text);
+ }
+
+ return tmp;
+}
+
+value_t *
+make_tree (type_t t, value_t *left, value_t *right)
+{
+ value_t *tmp = malloc(sizeof(*tmp));
+
+ if (tmp) {
+ tmp->type = t;
+ tmp->as_tree.left = left;
+ tmp->as_tree.right = right;
+ }
+
+ return tmp;
+}
+
+value_t *
+make_comp (comp_t c, value_t *left, value_t *right)
+{
+ value_t *tmp = make_tree(T_COMP,left,right);
+
+ if (tmp) {
+ tmp->as_tree.op = c;
+ }
+
+ return tmp;
+}
+
+value_t *
+make_link (value_t *left, char *right)
+{
+ char *copy;
+
+ copy = strdup(right);
+ if (!copy) {
+ return NULL;
+ }
+
+ return make_tree(T_LINK,left,(value_t *)copy);
+}
+
+/*
+ * For some reason the bison-generated code isn't setting up yysv* properly,
+ * so $n doesn't work with terminals. Be very careful to use this only
+ * when the token we want is the last one in the current rule. If the
+ * syntax ever gets complicated enough that we can't get away with that, we'll
+ * just have to wrap all the terminals in singleton non-terminals just so that
+ * $n will work in the real syntax rules.
+ */
+extern char *yytext;
+
+/* In a sane world, yyparse would return this. */
+value_t *cur_val;
+
+/*
+ * IMO it's wrong for us to get into the bbool_expr=policy rule when there's
+ * a syntax error, but we do. The good news is that it's easy to free the
+ * erroneous tree properly this way. The bad news is that we need to wait
+ * until yyparse is done, then check this flag (which we have to maintain
+ * ourselves) to figure out whether we got a valid tree or not.
+ * No, yynerrs doesn't seem to give the right answer.
+ */
+int syntax_error = 0;
+
+void
+yyerror (char *msg)
+{
+ printf("%s: %sn",__func__,msg);
+ syntax_error = 1;
+}
+
+%}
+
+%token T_STRING T_DATE T_NUMBER T_ID
+%token T_DOLLAR T_WAFFLE T_DOT
+%token T_LPAREN T_RPAREN
+%token T_LESS T_GREATER T_EQUAL
+%token T_NOT T_AND T_OR
+%token T_SPACE T_INVALID
+%token T_OFIELD T_SFIELD T_COMP T_LINK
+
+%start policy
+
+%%
+
+policy:
+ bbool_expr {
+ printf("policy completen");
+ if (syntax_error) {
+ printf("bad policy!n");
+ }
+ else {
+ cur_val = $1;
+ }
+ };
+
+bbool_expr:
+ ubool_expr {
+ printf("promoting ubool_expr to bbool_exprn");
+ $$ = $1;
+ }|
+ bbool_expr T_AND T_AND ubool_expr {
+ printf("found AND expressionn");
+ $$ = make_tree(T_AND,$1,$4);
+ }|
+ bbool_expr T_OR T_OR ubool_expr {
+ printf("found OR expressionn");
+ $$ = make_tree(T_OR,$1,$4);
+ }|
+ bbool_expr T_SPACE {
+ $$ = $1;
+ }| T_SPACE bbool_expr {
+ $$ = $2;
+ };
+
+ubool_expr:
+ comp_expr {
+ printf("promoting comp_expr to ubool_exprn");
+ $$ = $1;
+ }|
+ T_NOT comp_expr {
+ printf("found NOT expressionn");
+ $$ = make_tree(T_NOT,$2,NULL);
+ }|
+ ubool_expr T_SPACE {
+ $$ = $1;
+ }| T_SPACE ubool_expr {
+ $$ = $2;
+ };
+
+
+comp_expr:
+ atom {
+ printf("promoting atom to comp_exprn");
+ $$ = $1;
+ }|
+ atom T_LESS atom {
+ printf("found LESS THAN expressionn");
+ $$ = make_comp(C_LESSTHAN,$1,$3);
+ }|
+ atom T_LESS T_EQUAL atom {
+ printf("found LESS OR EQUAL expressionn");
+ $$ = make_comp(C_LESSOREQ,$1,$4);
+ }|
+ atom T_EQUAL T_EQUAL atom {
+ printf("found EQUAL expressionn");
+ $$ = make_comp(C_EQUAL,$1,$4);
+ }|
+ atom T_NOT T_EQUAL atom {
+ printf("found NOT EQUAL expressionn");
+ $$ = make_comp(C_DIFFERENT,$1,$4);
+ }|
+ atom T_GREATER T_EQUAL atom {
+ printf("found GREATER OR EQUAL expressionn");
+ $$ = make_comp(C_GREATEROREQ,$1,$4);
+ }|
+ atom T_GREATER atom {
+ printf("found GREATER THAN expressionn");
+ $$ = make_comp(C_GREATERTHAN,$1,$3);
+ }|
+ comp_expr T_SPACE {
+ $$ = $1;
+ }| T_SPACE comp_expr {
+ $$ = $2;
+ };
+
+atom:
+ link_field {
+ printf("promoting link_field to atomn");
+ $$ = $1;
+ }|
+ literal {
+ printf("promoting literal to atomn");
+ $$ = $1;
+ }|
+ paren_expr {
+ printf("promoting paren_expr to atomn");
+ $$ = $1;
+ }|
+ atom T_SPACE {
+ $$ = $1;
+ }| T_SPACE atom {
+ $$ = $2;
+ };
+
+link_field:
+ field {
+ printf("promoting field to link_fieldn");
+ $$ = $1;
+ }|
+ link_field T_DOT T_ID {
+ printf("found LINK FIELDn");
+ $$ = make_link($1,yytext);
+ };
+
+field:
+ T_DOLLAR T_ID {
+ printf("found DOLLAR FIELDn");
+ $$ = make_string(yytext,T_OFIELD);
+ }|
+ T_WAFFLE T_ID {
+ printf("found WAFFLE FIELDn");
+ $$ = make_string(yytext,T_SFIELD);
+ };
+
+literal:
+ T_NUMBER {
+ printf("found NUMBER %sn",yytext);
+ $$ = make_number(yytext);
+ }|
+ T_STRING {
+ printf("found STRING %sn",yytext);
+ $$ = make_string(yytext,T_STRING);
+ }|
+ T_DATE {
+ printf("found DATEn");
+ $$ = make_string(yytext,T_DATE);
+ }|
+ T_ID {
+ printf("found ID %sn",yytext);
+ $$ = make_string(yytext,T_ID);
+ };
+
+paren_expr:
+ T_LPAREN bbool_expr T_RPAREN {
+ printf("found PAREN expressionn");
+ $$ = $2;
+ };
+
+%%
+
+void
+_print_value (const value_t *v, int level)
+{
+ if (!v) {
+ printf("%*sNULLn",level,"");
+ return;
+ }
+
+ switch (v->type) {
+ case T_NUMBER:
+ printf("%*sNUMBER %lldn",level,"",v->as_num);
+ break;
+ case T_STRING:
+ printf("%*sSTRING %sn",level,"",v->as_str);
+ break;
+ case T_OFIELD:
+#if defined(UNIT_TEST)
+ printf("%*sOBJECT FIELD %s (%s)n",level,"",v->as_str,
+ unit_oget_func(NULL,v->as_str));
+#else
+ printf("%*sOBJECT FIELD %sn",level,"",v->as_str);
+#endif
+ break;
+ case T_SFIELD:
+#if defined(UNIT_TEST)
+ printf("%*sSERVER FIELD %s (%s)n",level,"",v->as_str,
+ unit_sget_func(NULL,v->as_str));
+#else
+ printf("%*sSERVER FIELD %sn",level,"",v->as_str);
+#endif
+ break;
+ case T_COMP:
+ printf("%*sCOMPARISONn",level,"");
+ _print_value(v->as_tree.left,level+2);
+ _print_value(v->as_tree.right,level+2);
+ break;
+ case T_NOT:
+ printf("%*sNOTn",level,"");
+ _print_value(v->as_tree.left,level+2);
+ break;
+ case T_AND:
+ printf("%*sANDn",level,"");
+ _print_value(v->as_tree.left,level+2);
+ _print_value(v->as_tree.right,level+2);
+ break;
+ case T_OR:
+ printf("%*sORn",level,"");
+ _print_value(v->as_tree.left,level+2);
+ _print_value(v->as_tree.right,level+2);
+ break;
+ case T_LINK:
+ printf("%*sLINKn",level,"");
+ _print_value(v->as_tree.left,level+2);
+ printf("%*sDEST FIELD %sn",level+2,"",
+ (char *)v->as_tree.right);
+ break;
+ default:
+ printf("%*sUNKNOWN %dn",level,"",v->type);
+ }
+}
+
+void
+print_value (const value_t *v)
+{
+ _print_value(v,0);
+}
+
+void
+free_value (value_t *v)
+{
+ if (!v) {
+ return;
+ }
+
+ switch (v->type) {
+ case T_STRING:
+ case T_OFIELD:
+ case T_SFIELD:
+ case T_ID:
+ free(v->as_str);
+ free(v);
+ break;
+ case T_LINK:
+ free_value(v->as_tree.left);
+ free(v->as_tree.right);
+ free(v);
+ break;
+ case T_COMP:
+ case T_AND:
+ case T_OR:
+ free_value(v->as_tree.right);
+ /* Fall through. */
+ case T_NOT:
+ free_value(v->as_tree.left);
+ /* Fall through. */
+ default:
+ free(v);
+ }
+}
+
+int
+main (int argc, char **argv)
+{
+ char *data = "#a=="fubar"&&!($b.c.d<3)";
+ char *edata = "gobbledy-gook";
+
+ yy_scan_string(data);
+ yyparse();
+ if (cur_val) {
+ if (!syntax_error) {
+ print_value(cur_val);
+ }
+ else {
+ printf("discarding erroneous parse treen");
+ }
+ free_value(cur_val);
+ cur_val = NULL;
+ }
+ yylex_destroy();
+
+ yy_scan_string(edata);
+ yyparse();
+ if (cur_val) {
+ if (!syntax_error) {
+ print_value(cur_val);
+ }
+ else {
+ printf("discarding erroneous parse treen");
+ }
+ free_value(cur_val);
+ cur_val = NULL;
+ }
+ yylex_destroy();
+
+ return 0;
+}
-----------------------------------------------------------------------
Summary of changes:
.gitignore | 9 +-
Makefile.am | 27 +--
configure.ac | 6 +-
qlexer.l | 87 +++++++
query.leg => qparser.y | 617 +++++++++++++++++++++++++++++-------------------
query.c.diff | 47 ----
query.h | 50 +++-
t/Makefile.am | 4 +-
8 files changed, 517 insertions(+), 330 deletions(-)
create mode 100644 qlexer.l
rename query.leg => qparser.y (62%)
delete mode 100644 query.c.diff
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months
[repo.or.cz] iwhd.git branch master updated: v0.0-180-g9ca9c3d
by Jim Meyering
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, master has been updated
via 9ca9c3d6bdd3d210b5c58fca4bc9c63aacbea78d (commit)
from d003a5d273b985ea3135cbd34c139191d394d8ac (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/9ca9c3d6bdd3d210b5c58fca4bc9c63aacbea78d
commit 9ca9c3d6bdd3d210b5c58fca4bc9c63aacbea78d
Author: Jim Meyering <meyering(a)redhat.com>
Date: Tue Oct 19 19:24:08 2010 +0200
tests: don't clutter regular output with expected diagnostics
* t/init.cfg (wait_for): Emit common diagnostic to log, not tty.
diff --git a/t/init.cfg b/t/init.cfg
index 90bb390..0b92496 100644
--- a/t/init.cfg
+++ b/t/init.cfg
@@ -31,7 +31,7 @@ wait_for()
esac
local i=0
while :; do
- eval "$cmd" && { warn_ "cmd took $i x ${sleep_seconds}s: '$cmd'"; return 0; }
+ eval "$cmd" && { echo "cmd took $i x ${sleep_seconds}s: '$cmd'"; return 0; }
sleep $sleep_seconds
i=$(expr $i + 1)
test $i = $max_n_sleeps
-----------------------------------------------------------------------
Summary of changes:
t/init.cfg | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months
[repo.or.cz] iwhd.git branch master updated: v0.0-179-gd003a5d
by Jim Meyering
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, master has been updated
via d003a5d273b985ea3135cbd34c139191d394d8ac (commit)
from 5a88451cf5e0e69635a9dc4eacbb7f2606256fcc (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/d003a5d273b985ea3135cbd34c139191d394d8ac
commit d003a5d273b985ea3135cbd34c139191d394d8ac
Author: Jim Meyering <meyering(a)redhat.com>
Date: Tue Oct 19 19:02:08 2010 +0200
clean-up: move file-scoped global into "main"
* rest.c (main): Move "autostart" into main.
diff --git a/rest.c b/rest.c
index 9023be2..d09e7c1 100644
--- a/rest.c
+++ b/rest.c
@@ -66,7 +66,6 @@ typedef struct {
} rule;
static unsigned short my_port = MY_PORT;
-static int autostart = 0;
const char *program_name;
char *cfg_file = NULL;
@@ -1907,6 +1906,7 @@ main (int argc, char **argv)
sem_t the_sem;
char *stctx = NULL;
char *port_tmp;
+ int autostart = 0;
program_name = argv[0];
-----------------------------------------------------------------------
Summary of changes:
rest.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months
[repo.or.cz] iwhd.git branch master updated: v0.0-178-g5a88451
by Jim Meyering
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, master has been updated
via 5a88451cf5e0e69635a9dc4eacbb7f2606256fcc (commit)
from 32a041e25d2c1c9d6e4c353ce8db6649aed62954 (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/5a88451cf5e0e69635a9dc4eacbb7f2606256fcc
commit 5a88451cf5e0e69635a9dc4eacbb7f2606256fcc
Author: Jim Meyering <meyering(a)redhat.com>
Date: Tue Oct 19 16:52:17 2010 +0200
tests: avoid using a temp file in wait_for_repl utility
* t/replication (wait_for_repl): Use a variable rather than a
temporary file.
diff --git a/t/replication b/t/replication
index 902d340..78911cc 100644
--- a/t/replication
+++ b/t/replication
@@ -45,9 +45,11 @@ cleanup_() { kill -9 $mongo_pid; kill $iwhd_pid $iwhd_d_pid; }
api=http://localhost:$port
wait_for_repl() {
- curl -d op=rep_status $api > repl.out || return 1
- test "$(cat repl.out)" = "0 requests" || return 1
- return 0
+ local n_req=$(curl -d op=rep_status $api) || return 1
+ case $n_req in
+ '0 requests') return 1 ;;
+ *) return 0 ;;
+ esac
}
bkt=$api/rbucket
-----------------------------------------------------------------------
Summary of changes:
t/replication | 8 +++++---
1 files changed, 5 insertions(+), 3 deletions(-)
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months
[repo.or.cz] iwhd.git branch master updated: v0.0-177-g32a041e
by Jim Meyering
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, master has been updated
via 32a041e25d2c1c9d6e4c353ce8db6649aed62954 (commit)
from 5372c8c2f472846e480b44c498aae3177038949a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/32a041e25d2c1c9d6e4c353ce8db6649aed62954
commit 32a041e25d2c1c9d6e4c353ce8db6649aed62954
Author: Jim Meyering <meyering(a)redhat.com>
Date: Tue Oct 19 16:50:57 2010 +0200
tests: wait_for: report how long we waited, or that timeout expired
* t/init.cfg (wait_for): Tell how long we wait.
diff --git a/t/init.cfg b/t/init.cfg
index bffe669..90bb390 100644
--- a/t/init.cfg
+++ b/t/init.cfg
@@ -31,9 +31,10 @@ wait_for()
esac
local i=0
while :; do
- eval "$cmd" && return 0
+ eval "$cmd" && { warn_ "cmd took $i x ${sleep_seconds}s: '$cmd'"; return 0; }
sleep $sleep_seconds
i=$(expr $i + 1)
- test $i = $max_n_sleeps && return 1
+ test $i = $max_n_sleeps + && { warn_ "EXPIRED: $i x ${sleep_seconds}s: '$cmd'"; return 1; }
done
}
-----------------------------------------------------------------------
Summary of changes:
t/init.cfg | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months
[repo.or.cz] iwhd.git branch master updated: v0.0-176-g5372c8c
by Jim Meyering
This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project iwhd.git.
The branch, master has been updated
via 5372c8c2f472846e480b44c498aae3177038949a (commit)
via a10711d0124f8130ea0339dbc34d0bfd06cbb815 (commit)
from 5f3562c3efe50314a708094b19641ba282b35b6a (commit)
Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.
- Log -----------------------------------------------------------------
http://repo.or.cz/w/iwhd.git/commit/5372c8c2f472846e480b44c498aae3177038949a
commit 5372c8c2f472846e480b44c498aae3177038949a
Author: Jim Meyering <meyering(a)redhat.com>
Date: Tue Oct 19 16:17:13 2010 +0200
fflush debugging output when writing to stdout
* iwh.h (DPRINTF): Call fflush.
diff --git a/iwh.h b/iwh.h
index 4586b27..a97322d 100644
--- a/iwh.h
+++ b/iwh.h
@@ -31,6 +31,7 @@ GLOBAL(const char *, me, "here");
#define DPRINTF(fmt,args...) do { if (verbose) { printf(fmt,##args); + fflush(stdout); } } while (0)
http://repo.or.cz/w/iwhd.git/commit/a10711d0124f8130ea0339dbc34d0bfd06cbb815
commit a10711d0124f8130ea0339dbc34d0bfd06cbb815
Author: Jim Meyering <meyering(a)redhat.com>
Date: Tue Oct 19 16:11:45 2010 +0200
replica: don't say we're "deleting" when creating a bucket
* replica.c: Include "replica.h".
Correct a misleading debug print statement.
diff --git a/replica.c b/replica.c
index d7a796f..6170a83 100644
--- a/replica.c
+++ b/replica.c
@@ -37,6 +37,7 @@
#include "setup.h"
#include "query.h"
#include "meta.h"
+#include "replica.h"
/* Sizes for internal string buffers. */
#define ADDR_SIZE 1024
@@ -379,7 +380,9 @@ replicate_namespace_action (const char *name, repl_t action, my_state *ms)
if (!strcmp(key,me)) {
continue;
}
- DPRINTF("replicating delete(%s) on %sn",name,
+ DPRINTF("replicating %s(%s) on %sn",
+ (action == REPL_ODELETE ? "delete" : "create"),
+ name,
((provider_t *)value)->name);
item = malloc(sizeof(*item));
if (!item) {
-----------------------------------------------------------------------
Summary of changes:
iwh.h | 1 +
replica.c | 5 ++++-
2 files changed, 5 insertions(+), 1 deletions(-)
repo.or.cz automatic notification. Contact project admin jim(a)meyering.net
if you want to unsubscribe, or site admin admin(a)repo.or.cz if you receive
no reply.
--
iwhd.git ("image warehouse daemon")
13 years, 6 months