summaryrefslogtreecommitdiffstats
path: root/src/interfaces/ecpg/preproc/check_rules.pl
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:15:05 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-04 12:15:05 +0000
commit46651ce6fe013220ed397add242004d764fc0153 (patch)
tree6e5299f990f88e60174a1d3ae6e48eedd2688b2b /src/interfaces/ecpg/preproc/check_rules.pl
parentInitial commit. (diff)
downloadpostgresql-14-upstream.tar.xz
postgresql-14-upstream.zip
Adding upstream version 14.5.upstream/14.5upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/interfaces/ecpg/preproc/check_rules.pl')
-rw-r--r--src/interfaces/ecpg/preproc/check_rules.pl191
1 files changed, 191 insertions, 0 deletions
diff --git a/src/interfaces/ecpg/preproc/check_rules.pl b/src/interfaces/ecpg/preproc/check_rules.pl
new file mode 100644
index 0000000..c0b5d19
--- /dev/null
+++ b/src/interfaces/ecpg/preproc/check_rules.pl
@@ -0,0 +1,191 @@
+#!/usr/bin/perl
+# src/interfaces/ecpg/preproc/check_rules.pl
+# test parser generator for ecpg
+# call with backend grammar as stdin
+#
+# Copyright (c) 2009-2021, 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
+
+use strict;
+use warnings;
+no warnings 'uninitialized';
+
+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";
+}
+
+my %replace_line = (
+ 'ExecuteStmtEXECUTEnameexecute_param_clause' =>
+ 'EXECUTE prepared_name execute_param_clause execute_rest',
+
+ 'ExecuteStmtCREATEOptTempTABLEcreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data'
+ => 'CREATE OptTemp TABLE create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest',
+
+ 'ExecuteStmtCREATEOptTempTABLEIF_PNOTEXISTScreate_as_targetASEXECUTEnameexecute_param_clauseopt_with_data'
+ => 'CREATE OptTemp TABLE IF_P NOT EXISTS create_as_target AS EXECUTE prepared_name execute_param_clause opt_with_data execute_rest',
+
+ 'PrepareStmtPREPAREnameprep_type_clauseASPreparableStmt' =>
+ 'PREPARE prepared_name prep_type_clause AS PreparableStmt');
+
+my $block = '';
+my $yaccmode = 0;
+my $in_rule = 0;
+my $brace_indent = 0;
+my (@arr, %found);
+my $comment = 0;
+my $non_term_id = '';
+my $cc = 0;
+
+open my $parser_fh, '<', $parser or die $!;
+while (<$parser_fh>)
+{
+ if (/^%%/)
+ {
+ $yaccmode++;
+ }
+
+ if ($yaccmode != 1)
+ {
+ next;
+ }
+
+ chomp; # strip record separator
+
+ next if ($_ eq '');
+
+ # Make sure any braces are split
+ s/{/ { /g;
+ s/}/ } /g;
+
+ # Any comments are split
+ s|\/\*| /* |g;
+ s|\*\/| */ |g;
+
+ # Now split the line into individual fields
+ my $n = (@arr = split(' '));
+
+ # Go through each field in turn
+ for (my $fieldIndexer = 0; $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 = $non_term_id . $replace_line{$block};
+ $block =~ tr/ |//d;
+ }
+ $found{$block} = 1;
+ $cc++;
+ $block = '';
+ $in_rule = 0 if $arr[$fieldIndexer] eq ';';
+ }
+ elsif (($arr[$fieldIndexer] =~ '[A-Za-z0-9]+:')
+ || $arr[ $fieldIndexer + 1 ] eq ':')
+ {
+ die "unterminated rule at grammar line $.\n"
+ if $in_rule;
+ $in_rule = 1;
+ $non_term_id = $arr[$fieldIndexer];
+ $non_term_id =~ tr/://d;
+ }
+ else
+ {
+ $block = $block . $arr[$fieldIndexer];
+ }
+ }
+}
+
+die "unterminated rule at end of grammar\n"
+ if $in_rule;
+
+close $parser_fh;
+if ($verbose)
+{
+ print "$cc rules loaded\n";
+}
+
+my $ret = 0;
+$cc = 0;
+
+open my $ecpg_fh, '<', $filename or die $!;
+while (<$ecpg_fh>)
+{
+ if (!/^ECPG:/)
+ {
+ next;
+ }
+
+ 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_fh;
+
+if ($verbose)
+{
+ print "$cc rules checked\n";
+}
+
+exit $ret;