# Copyright (c) 2009-2011, PostgreSQL Global Development Group
#
# Written by Michael Meskes <meskes@postgresql.org>
+# Andy Colson <andy@squeakycode.net>
#
# Placed under the same license as PostgreSQL.
#
+# Command line: [-v] [path only to ecpg.addons] [full filename of gram.y]
+# -v enables verbose mode... show's some stats... thought it might be interesting
+#
+# This script loads rule names from gram.y and sets $found{rule} = 1 for each.
+# Then it checks to make sure each rule in ecpg.addons was found in gram.y
-if (@ARGV) {
- $path = $ARGV[0];
- $parser = $ARGV[1];
-}
+use strict;
+use warnings;
+no warnings 'uninitialized';
-$[ = 1; # set array base to 1
+my $verbose = 0;
+if ($ARGV[0] eq '-v')
+{
+ $verbose = shift;
+}
+my $path = shift || '.';
+my $parser = shift || '../../../backend/parser/gram.y';
+
+my $filename = $path . "/ecpg.addons";
+if ($verbose)
+{
+ print "parser: $parser\n";
+ print "addons: $filename\n";
+}
-if ($path eq '') { $path = "."; }
-$filename = $path . "/ecpg.addons";
+my %replace_line = (
+ 'ExecuteStmtEXECUTEnameexecute_param_clause' =>
+ 'EXECUTE prepared_name execute_param_clause execute_rest',
-if ($parser eq '') { $parser = "../../../backend/parser/gram.y"; }
+ 'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clause' =>
+ 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause',
-$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';
+ 'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt' =>
+ 'PREPARE prepared_name prep_type_clause AS PreparableStmt'
+);
-$block = '';
-$ret = 0;
-$yaccmod = 0;
-$brace_indent = 0;
+my $block = '';
+my $yaccmode = 0;
+my $brace_indent = 0;
+my (@arr, %found);
+my $comment = 0;
+my $non_term_id = '';
+my $cc = 0;
open GRAM, $parser or die $!;
-while (<GRAM>) {
- chomp; # strip record separator
+while (<GRAM>)
+{
+ if (/^%%/)
+ {
+ $yaccmode++;
+ }
- if (/^%%/) {
- $yaccmode++;
+ if ( $yaccmode != 1 )
+ {
+ next;
}
- if ($yaccmode != 1) {
- next;
- }
+ chomp; # strip record separator
- $S = $_;
- $prec = 0;
+ next if ($_ eq '');
# Make sure any braces are split
- $S =~ s/{/ { /g;
- $S =~ s/}/ } /g;
+ s/{/ { /g;
+ s/}/ } /g;
+
# Any comments are split
- $S =~ s#[/][*]# /* #g;
- $S =~ s#[*][/]# */ #g;
+ s|\/\*| /* |g;
+ s|\*\/| */ |g;
# Now split the line into individual fields
- $n = (@arr = split(' ', $S));
+ my $n = ( @arr = split( ' ' ) );
# Go through each field in turn
- for ($fieldIndexer = 1; $fieldIndexer <= $n; $fieldIndexer++) {
- if ($arr[$fieldIndexer] eq '*/' && $comment) {
- $comment = 0;
- next;
+ for ( my $fieldIndexer = 0 ; $fieldIndexer < $n ; $fieldIndexer++ )
+ {
+ if ( $arr[$fieldIndexer] eq '*/' && $comment )
+ {
+ $comment = 0;
+ next;
}
- elsif ($comment) {
- next;
+ elsif ($comment)
+ {
+ next;
}
- elsif ($arr[$fieldIndexer] eq '/*') {
- # start of a multiline comment
- $comment = 1;
- next;
+ elsif ( $arr[$fieldIndexer] eq '/*' )
+ {
+ # start of a multiline comment
+ $comment = 1;
+ next;
}
- elsif ($arr[$fieldIndexer] eq '//') {
- next;
+ elsif ( $arr[$fieldIndexer] eq '//' )
+ {
+ next;
}
- elsif ($arr[$fieldIndexer] eq '}') {
- $brace_indent--;
- next;
+ elsif ( $arr[$fieldIndexer] eq '}' )
+ {
+ $brace_indent--;
+ next;
}
- elsif ($arr[$fieldIndexer] eq '{') {
- $brace_indent++;
- next;
+ elsif ( $arr[$fieldIndexer] eq '{' )
+ {
+ $brace_indent++;
+ next;
}
- if ($brace_indent > 0) {
- next;
+ if ( $brace_indent > 0 )
+ {
+ next;
}
- if ($arr[$fieldIndexer] eq ';' || $arr[$fieldIndexer] eq '|') {
+ if ( $arr[$fieldIndexer] eq ';' || $arr[$fieldIndexer] eq '|' )
+ {
$block = $non_term_id . $block;
- if ($replace_line{$block}) {
- $block = &generate_block($replace_line{$block});
+ if ( $replace_line{$block} )
+ {
+ $block = $non_term_id . $replace_line{$block};
+ $block =~ tr/ |//d;
}
- $found{$block} = 'found';
+ $found{$block} = 1;
+ $cc++;
$block = '';
}
- elsif (($arr[$fieldIndexer] =~ '[A-Za-z0-9]+:') || $arr[$fieldIndexer + 1] eq ':') {
+ elsif ( ( $arr[$fieldIndexer] =~ '[A-Za-z0-9]+:' )
+ || $arr[ $fieldIndexer + 1 ] eq ':' )
+ {
$non_term_id = $arr[$fieldIndexer];
- $non_term_id =~ s/://g;
+ $non_term_id =~ tr/://d;
}
- else {
+ else
+ {
$block = $block . $arr[$fieldIndexer];
}
}
}
close GRAM;
+if ($verbose)
+{
+ print "$cc rules loaded\n";
+}
-open ECPG, $filename or die $!;
-
-line: while (<ECPG>) {
- chomp; # strip record separator
- @Fld = split(' ', $_, -1);
+my $ret = 0;
+$cc = 0;
- if (!/^ECPG:/) {
- next line;
- }
+open ECPG, $filename or die $!;
+while (<ECPG>)
+{
+ if ( !/^ECPG:/ )
+ {
+ next;
+ }
- if ($found{$Fld[2]} ne 'found') {
- printf $Fld[2] . " is not used for building parser!\n";
- $ret = 1;
- }
+ my @Fld = split( ' ', $_, 3 );
+ $cc++;
+ if ( not exists $found{ $Fld[1] } )
+ {
+ print $Fld[1], " is not used for building parser!\n";
+ $ret = 1;
+ }
}
-
close ECPG;
+if ($verbose)
+{
+ print "$cc rules checked\n";
+}
+
exit $ret;
-sub generate_block {
- local($line) = @_;
- $block = $non_term_id . $line;
- $block =~ s/ //g;
- $s = "\\|", $block =~ s/$s//g;
- return $block;
-}