 src/backend/catalog/Catalog.pm   | 14 +++++++-------
 src/backend/catalog/genbki.pl    | 38 +++++++++++++++++++++-----------------
 src/backend/utils/Gen_fmgrtab.pl |  5 +++--
 3 files changed, 31 insertions(+), 26 deletions(-)

diff --git a/src/backend/catalog/Catalog.pm b/src/backend/catalog/Catalog.pm
new file mode 100644
index 0b260ec..6bc14d2
*** a/src/backend/catalog/Catalog.pm
--- b/src/backend/catalog/Catalog.pm
*************** sub Catalogs
*** 163,169 ****
  				  /BKI_WITHOUT_OIDS/ ? ' without_oids' : '';
  				$catalog{rowtype_oid} =
  				  /BKI_ROWTYPE_OID\((\d+)\)/ ? " rowtype_oid $1" : '';
! 				$catalog{schema_macro} = /BKI_SCHEMA_MACRO/ ? 'True' : '';
  				$declaring_attributes = 1;
  			}
  			elsif ($declaring_attributes)
--- 163,169 ----
  				  /BKI_WITHOUT_OIDS/ ? ' without_oids' : '';
  				$catalog{rowtype_oid} =
  				  /BKI_ROWTYPE_OID\((\d+)\)/ ? " rowtype_oid $1" : '';
! 				$catalog{schema_macro} = /BKI_SCHEMA_MACRO/ ? 1 : 0;
  				$declaring_attributes = 1;
  			}
  			elsif ($declaring_attributes)
*************** sub Catalogs
*** 176,182 ****
  				}
  				else
  				{
! 					my %row;
  					my ($atttype, $attname, $attopt) = split /\s+/, $_;
  					die "parse error ($input_file)" unless $attname;
  					if (exists $RENAME_ATTTYPE{$atttype})
--- 176,182 ----
  				}
  				else
  				{
! 					my %column;
  					my ($atttype, $attname, $attopt) = split /\s+/, $_;
  					die "parse error ($input_file)" unless $attname;
  					if (exists $RENAME_ATTTYPE{$atttype})
*************** sub Catalogs
*** 189,206 ****
  						$atttype .= '[]';            # variable-length only
  					}
  
! 					$row{'type'} = $atttype;
! 					$row{'name'} = $attname;
  
  					if (defined $attopt)
  					{
  						if ($attopt eq 'BKI_FORCE_NULL')
  						{
! 							$row{'forcenull'} = 1;
  						}
  						elsif ($attopt eq 'BKI_FORCE_NOT_NULL')
  						{
! 							$row{'forcenotnull'} = 1;
  						}
  						else
  						{
--- 189,206 ----
  						$atttype .= '[]';            # variable-length only
  					}
  
! 					$column{type} = $atttype;
! 					$column{name} = $attname;
  
  					if (defined $attopt)
  					{
  						if ($attopt eq 'BKI_FORCE_NULL')
  						{
! 							$column{forcenull} = 1;
  						}
  						elsif ($attopt eq 'BKI_FORCE_NOT_NULL')
  						{
! 							$column{forcenotnull} = 1;
  						}
  						else
  						{
*************** sub Catalogs
*** 208,214 ****
  "unknown column option $attopt on column $attname";
  						}
  					}
! 					push @{ $catalog{columns} }, \%row;
  				}
  			}
  		}
--- 208,214 ----
  "unknown column option $attopt on column $attname";
  						}
  					}
! 					push @{ $catalog{columns} }, \%column;
  				}
  			}
  		}
diff --git a/src/backend/catalog/genbki.pl b/src/backend/catalog/genbki.pl
new file mode 100644
index 256a9c9..4bd614f
*** a/src/backend/catalog/genbki.pl
--- b/src/backend/catalog/genbki.pl
*************** use strict;
*** 20,26 ****
  use warnings;
  
  my @input_files;
! our @include_path;
  my $output_path = '';
  my $major_version;
  
--- 20,26 ----
  use warnings;
  
  my @input_files;
! my @include_path;
  my $output_path = '';
  my $major_version;
  
*************** print $bki "# PostgreSQL $major_version\
*** 105,111 ****
  my %schemapg_entries;
  my @tables_needing_macros;
  my %regprocoids;
! our @types;
  
  # produce output, one catalog at a time
  foreach my $catname (@{ $catalogs->{names} })
--- 105,111 ----
  my %schemapg_entries;
  my @tables_needing_macros;
  my %regprocoids;
! my @types;
  
  # produce output, one catalog at a time
  foreach my $catname (@{ $catalogs->{names} })
*************** foreach my $catname (@{ $catalogs->{name
*** 124,130 ****
  	my $first = 1;
  
  	print $bki " (\n";
! 	foreach my $column (@{ $catalog->{columns} })
  	{
  		my $attname = $column->{name};
  		my $atttype = $column->{type};
--- 124,131 ----
  	my $first = 1;
  
  	print $bki " (\n";
! 	my $schema = $catalog->{columns};
! 	foreach my $column (@$schema)
  	{
  		my $attname = $column->{name};
  		my $atttype = $column->{type};
*************** foreach my $catname (@{ $catalogs->{name
*** 150,157 ****
  	}
  	print $bki "\n )\n";
  
!    # open it, unless bootstrap case (create bootstrap does this automatically)
! 	if ($catalog->{bootstrap} eq '')
  	{
  		print $bki "open $catname\n";
  	}
--- 151,159 ----
  	}
  	print $bki "\n )\n";
  
! 	# Open it, unless bootstrap case (create bootstrap does this
! 	# automatically)
! 	if (!$catalog->{bootstrap})
  	{
  		print $bki "open $catname\n";
  	}
*************** foreach my $catname (@{ $catalogs->{name
*** 169,189 ****
  			  Catalog::SplitDataLine($row->{bki_values});
  
  			# Perform required substitutions on fields
! 			foreach my $att (keys %bki_values)
  			{
  
  				# Substitute constant values we acquired above.
  				# (It's intentional that this can apply to parts of a field).
! 				$bki_values{$att} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g;
! 				$bki_values{$att} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g;
  
  				# Replace regproc columns' values with OIDs.
  				# If we don't have a unique value to substitute,
  				# just do nothing (regprocin will complain).
! 				if ($bki_attr{$att}->{type} eq 'regproc')
  				{
! 					my $procoid = $regprocoids{ $bki_values{$att} };
! 					$bki_values{$att} = $procoid
  					  if defined($procoid) && $procoid ne 'MULTIPLE';
  				}
  			}
--- 171,193 ----
  			  Catalog::SplitDataLine($row->{bki_values});
  
  			# Perform required substitutions on fields
! 			foreach my $column (@$schema)
  			{
+ 				my $attname = $column->{name};
+ 				my $atttype = $column->{type};
  
  				# Substitute constant values we acquired above.
  				# (It's intentional that this can apply to parts of a field).
! 				$bki_values{$attname} =~ s/\bPGUID\b/$BOOTSTRAP_SUPERUSERID/g;
! 				$bki_values{$attname} =~ s/\bPGNSP\b/$PG_CATALOG_NAMESPACE/g;
  
  				# Replace regproc columns' values with OIDs.
  				# If we don't have a unique value to substitute,
  				# just do nothing (regprocin will complain).
! 				if ($atttype eq 'regproc')
  				{
! 					my $procoid = $regprocoids{ $bki_values{$attname} };
! 					$bki_values{$attname} = $procoid
  					  if defined($procoid) && $procoid ne 'MULTIPLE';
  				}
  			}
*************** foreach my $catname (@{ $catalogs->{name
*** 215,221 ****
  			printf $bki "insert %s( %s )\n", $oid,
  			  join(' ', @bki_values{@attnames});
  
! 		   # Write comments to postgres.description and postgres.shdescription
  			if (defined $row->{descr})
  			{
  				printf $descr "%s\t%s\t0\t%s\n", $row->{oid}, $catname,
--- 219,226 ----
  			printf $bki "insert %s( %s )\n", $oid,
  			  join(' ', @bki_values{@attnames});
  
! 			# Write comments to postgres.description and
! 			# postgres.shdescription
  			if (defined $row->{descr})
  			{
  				printf $descr "%s\t%s\t0\t%s\n", $row->{oid}, $catname,
*************** foreach my $catname (@{ $catalogs->{name
*** 240,250 ****
  
  			# Currently, all bootstrapped relations also need schemapg.h
  			# entries, so skip if the relation isn't to be in schemapg.h.
! 			next if $table->{schema_macro} ne 'True';
  
  			$schemapg_entries{$table_name} = [];
  			push @tables_needing_macros, $table_name;
- 			my $is_bootstrap = $table->{bootstrap};
  
  			# Generate entries for user attributes.
  			my $attnum       = 0;
--- 245,254 ----
  
  			# Currently, all bootstrapped relations also need schemapg.h
  			# entries, so skip if the relation isn't to be in schemapg.h.
! 			next if !$table->{schema_macro};
  
  			$schemapg_entries{$table_name} = [];
  			push @tables_needing_macros, $table_name;
  
  			# Generate entries for user attributes.
  			my $attnum       = 0;
*************** foreach my $catname (@{ $catalogs->{name
*** 259,265 ****
  				$priornotnull &= ($row->{attnotnull} eq 't');
  
  				# If it's bootstrapped, put an entry in postgres.bki.
! 				if ($is_bootstrap eq ' bootstrap')
  				{
  					bki_insert($row, @attnames);
  				}
--- 263,269 ----
  				$priornotnull &= ($row->{attnotnull} eq 't');
  
  				# If it's bootstrapped, put an entry in postgres.bki.
! 				if ($table->{bootstrap})
  				{
  					bki_insert($row, @attnames);
  				}
*************** foreach my $catname (@{ $catalogs->{name
*** 276,282 ****
  
  			# Generate entries for system attributes.
  			# We only need postgres.bki entries, not schemapg.h entries.
! 			if ($is_bootstrap eq ' bootstrap')
  			{
  				$attnum = 0;
  				my @SYS_ATTRS = (
--- 280,286 ----
  
  			# Generate entries for system attributes.
  			# We only need postgres.bki entries, not schemapg.h entries.
! 			if ($table->{bootstrap})
  			{
  				$attnum = 0;
  				my @SYS_ATTRS = (
*************** foreach my $catname (@{ $catalogs->{name
*** 296,302 ****
  
  					# some catalogs don't have oids
  					next
! 					  if $table->{without_oids} eq ' without_oids'
  						  && $row->{attname} eq 'oid';
  
  					bki_insert($row, @attnames);
--- 300,306 ----
  
  					# some catalogs don't have oids
  					next
! 					  if $table->{without_oids}
  						  && $row->{attname} eq 'oid';
  
  					bki_insert($row, @attnames);
diff --git a/src/backend/utils/Gen_fmgrtab.pl b/src/backend/utils/Gen_fmgrtab.pl
new file mode 100644
index c0efc07..a51a755
*** a/src/backend/utils/Gen_fmgrtab.pl
--- b/src/backend/utils/Gen_fmgrtab.pl
*************** die "No include path; you must specify -
*** 57,62 ****
--- 57,64 ----
  
  my $FirstBootstrapObjectId =
  	Catalog::FindDefinedSymbol('access/transam.h', \@include_path, 'FirstBootstrapObjectId');
+ my $INTERNALlanguageId =
+ 	Catalog::FindDefinedSymbol('catalog/pg_language.h', \@include_path, 'INTERNALlanguageId');
  
  # Read all the data from the include/catalog files.
  my $catalogs = Catalog::Catalogs($infile);
*************** foreach my $row (@$data)
*** 78,85 ****
  	@bki_values{@attnames} = Catalog::SplitDataLine($row->{bki_values});
  
  	# Select out just the rows for internal-language procedures.
! 	# Note assumption here that INTERNALlanguageId is 12.
! 	next if $bki_values{prolang} ne '12';
  
  	push @fmgr,
  	  { oid    => $row->{oid},
--- 80,86 ----
  	@bki_values{@attnames} = Catalog::SplitDataLine($row->{bki_values});
  
  	# Select out just the rows for internal-language procedures.
! 	next if $bki_values{prolang} ne $INTERNALlanguageId;
  
  	push @fmgr,
  	  { oid    => $row->{oid},
