diff --git a/src/interfaces/ecpg/preproc/Makefile b/src/interfaces/ecpg/preproc/Makefile index e33c0e9c32..493e095544 100644 --- a/src/interfaces/ecpg/preproc/Makefile +++ b/src/interfaces/ecpg/preproc/Makefile @@ -4,7 +4,7 @@ # # Copyright (c) 1998-2009, PostgreSQL Global Development Group # -# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.146 2009/09/02 19:14:14 mha Exp $ +# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/Makefile,v 1.147 2009/11/27 10:00:40 meskes Exp $ # #------------------------------------------------------------------------- @@ -54,6 +54,7 @@ endif preproc.y: ../../../backend/parser/gram.y parse.pl ecpg.addons ecpg.header ecpg.tokens ecpg.trailer ecpg.type $(PERL) $(srcdir)/parse.pl $(srcdir) < $< > $@ + $(PERL) $(srcdir)/check_rules.pl $(srcdir) $< ecpg_keywords.o c_keywords.o keywords.o preproc.o parser.o: preproc.h diff --git a/src/interfaces/ecpg/preproc/check_rules.pl b/src/interfaces/ecpg/preproc/check_rules.pl new file mode 100755 index 0000000000..73f4486f85 --- /dev/null +++ b/src/interfaces/ecpg/preproc/check_rules.pl @@ -0,0 +1,136 @@ +#!/usr/bin/perl +# $PostgreSQL: pgsql/src/interfaces/ecpg/preproc/check_rules.pl,v 1.1 2009/11/27 10:00:40 meskes Exp $ +# test parser generater for ecpg +# call with backend parser as stdin +# +# Copyright (c) 2009, PostgreSQL Global Development Group +# +# Written by Michael Meskes +# +# Placed under the same license as PostgreSQL. +# + +if (@ARGV) { + $path = $ARGV[0]; + $parser = $ARGV[1]; +} + +$[ = 1; # set array base to 1 + +if ($path eq '') { $path = "."; } +$filename = $path . "/ecpg.addons"; + +if ($parser eq '') { $parser = "../../../backend/parser/gram.y"; } + +$replace_line{'ExecuteStmtEXECUTEnameexecute_param_clause'} = 'EXECUTE prepared_name execute_param_clause execute_rest'; +$replace_line{'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clause'} = 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause'; +$replace_line{'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt'} = 'PREPARE prepared_name prep_type_clause AS PreparableStmt'; + +$block = ''; +$ret = 0; +$yaccmod = 0; +$brace_indent = 0; + +open GRAM, $parser or die $!; +while () { + chomp; # strip record separator + + if (/^%%/) { + $yaccmode++; + } + + if ($yaccmode != 1) { + next; + } + + $S = $_; + $prec = 0; + + # Make sure any braces are split + $S =~ s/{/ { /g; + $S =~ s/}/ } /g; + # Any comments are split + $S =~ s#[/][*]# /* #g; + $S =~ s#[*][/]# */ #g; + + # Now split the line into individual fields + $n = (@arr = split(' ', $S)); + + # Go through each field in turn + for ($fieldIndexer = 1; $fieldIndexer <= $n; $fieldIndexer++) { + if ($arr[$fieldIndexer] eq '*/' && $comment) { + $comment = 0; + next; + } + elsif ($comment) { + next; + } + elsif ($arr[$fieldIndexer] eq '/*') { + # start of a multiline comment + $comment = 1; + next; + } + elsif ($arr[$fieldIndexer] eq '//') { + next; + } + elsif ($arr[$fieldIndexer] eq '}') { + $brace_indent--; + next; + } + elsif ($arr[$fieldIndexer] eq '{') { + $brace_indent++; + next; + } + + if ($brace_indent > 0) { + next; + } + + if ($arr[$fieldIndexer] eq ';' || $arr[$fieldIndexer] eq '|') { + $block = $non_term_id . $block; + if ($replace_line{$block}) { + $block = &generate_block($replace_line{$block}); + } + $found{$block} = 'found'; + $block = ''; + } + elsif (($arr[$fieldIndexer] =~ '[A-Za-z0-9]+:') || $arr[$fieldIndexer + 1] eq ':') { + $non_term_id = $arr[$fieldIndexer]; + $non_term_id =~ s/://g; + } + else { + $block = $block . $arr[$fieldIndexer]; + } + } +} + +close GRAM; + +open ECPG, $filename or die $!; + +line: while () { + chomp; # strip record separator + @Fld = split(' ', $_, -1); + + if (!/^ECPG:/) { + next line; + } + + if ($found{$Fld[2]} ne 'found') { + printf $Fld[2] . " is not used for building parser!\n"; + $ret = 1; + } +} + +close ECPG; + +exit $ret; + +sub generate_block { + local($line) = @_; + $block = $non_term_id . $line; + $block =~ s/ //g; + $s = "\\|", $block =~ s/$s//g; + return $block; +} +