I wrote:
> Michael Paquier <mich...@paquier.xyz> writes:
>> It looks like %replace_line expects all its elements to have one space
>> between each token, still this is not enforced with a check across its
>> hardcoded elements?

> Yeah, I was wondering about that.  I wouldn't do it exactly like
> that, but with a check that the entry gets matched somewhere.

Here's a patch for that (again based on the other patch series).
This did not turn up anything interesting, but it's probably
worth keeping.

                        regards, tom lane

diff --git a/src/interfaces/ecpg/preproc/parse.pl b/src/interfaces/ecpg/preproc/parse.pl
index 98d44d4bf2..998822ce73 100644
--- a/src/interfaces/ecpg/preproc/parse.pl
+++ b/src/interfaces/ecpg/preproc/parse.pl
@@ -33,7 +33,9 @@ GetOptions(
 
 
 # These hash tables define additional transformations to apply to
-# grammar rules.
+# grammar rules.  For bug-detection purposes, we count usages of
+# each hash table entry in a second hash table, and verify that
+# all the entries get used.
 
 # Substitutions to apply to tokens whenever they are seen in a rule.
 my %replace_token = (
@@ -44,6 +46,8 @@ my %replace_token = (
 	'IDENT' => 'ecpg_ident',
 	'PARAM' => 'ecpg_param',);
 
+my %replace_token_used;
+
 # This hash can provide a result type to override "void" for nonterminals
 # that need that, or it can specify 'ignore' to cause us to skip the rule
 # for that nonterminal.  (In either case, ecpg.trailer had better provide
@@ -68,6 +72,8 @@ my %replace_types = (
 	'plassign_target' => 'ignore',
 	'plassign_equals' => 'ignore',);
 
+my %replace_types_used;
+
 # This hash provides an "ignore" option or substitute expansion for any
 # rule or rule alternative.  The hash key is the same "concattokens" tag
 # used for lookup in ecpg.addons.
@@ -111,6 +117,8 @@ my %replace_line = (
 	  'PREPARE prepared_name prep_type_clause AS PreparableStmt',
 	'var_nameColId' => 'ECPGColId');
 
+my %replace_line_used;
+
 
 # Declare assorted state variables.
 
@@ -198,6 +206,30 @@ foreach (keys %addons)
 	die "addon rule $_ was matched multiple times\n" if $addons{$_}{used} > 1;
 }
 
+# Likewise cross-check that entries in our internal hash tables match something.
+foreach (keys %replace_token)
+{
+	die "replace_token entry $_ was never used\n"
+	  if !defined($replace_token_used{$_});
+	# multiple use of a replace_token entry is fine
+}
+
+foreach (keys %replace_types)
+{
+	die "replace_types entry $_ was never used\n"
+	  if !defined($replace_types_used{$_});
+	die "replace_types entry $_ was matched multiple times\n"
+	  if $replace_types_used{$_} > 1;
+}
+
+foreach (keys %replace_line)
+{
+	die "replace_line entry $_ was never used\n"
+	  if !defined($replace_line_used{$_});
+	die "replace_line entry $_ was matched multiple times\n"
+	  if $replace_line_used{$_} > 1;
+}
+
 
 # Read the backend grammar.
 sub main
@@ -400,6 +432,7 @@ sub main
 			# Apply replace_token substitution if we have one.
 			if (exists $replace_token{ $arr[$fieldIndexer] })
 			{
+				$replace_token_used{ $arr[$fieldIndexer] }++;
 				$arr[$fieldIndexer] = $replace_token{ $arr[$fieldIndexer] };
 			}
 
@@ -425,6 +458,7 @@ sub main
 					&& $replace_types{$non_term_id} eq 'ignore')
 				{
 					# We'll ignore this nonterminal and rule altogether.
+					$replace_types_used{$non_term_id}++;
 					$copymode = 0;
 					next line;
 				}
@@ -451,6 +485,7 @@ sub main
 					  . $replace_types{$non_term_id} . ' '
 					  . $non_term_id;
 					add_to_buffer('types', $tstr);
+					$replace_types_used{$non_term_id}++;
 				}
 
 				# Emit the target part of the rule.
@@ -616,8 +651,10 @@ sub emit_rule
 
 	# apply replace_line substitution if any
 	my $rep = $replace_line{$tag};
-	if ($rep)
+	if (defined $rep)
 	{
+		$replace_line_used{$tag}++;
+
 		if ($rep eq 'ignore')
 		{
 			return 0;

Reply via email to