#! /usr/bin/perl -w #------------------------------------------------------------------------- # # Gen_fmgrtab.pl # Perl script that generates fmgroids.h and fmgrtab.c from pg_proc.h # # Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # # IDENTIFICATION # src/backend/utils/Gen_fmgrtab.pl # #------------------------------------------------------------------------- use Catalog; use strict; use warnings; # Collect arguments my $infile; # pg_proc.h my $output_path = ''; while (@ARGV) { my $arg = shift @ARGV; if ($arg !~ /^-/) { $infile = $arg; } elsif ($arg =~ /^-o/) { $output_path = length($arg) > 2 ? substr($arg, 2) : shift @ARGV; } else { usage(); } } # Make sure output_path ends in a slash. if ($output_path ne '' && substr($output_path, -1) ne '/') { $output_path .= '/'; } # Read all the data from the include/catalog files. my $catalogs = Catalog::Catalogs($infile); # Collect the raw data from pg_proc.h. my @fmgr = (); my @attnames; foreach my $column (@{ $catalogs->{pg_proc}->{columns} }) { push @attnames, $column->{name}; } my $data = $catalogs->{pg_proc}->{data}; foreach my $row (@$data) { # Split line into tokens without interpreting their meaning. my %bki_values; @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}, strict => $bki_values{proisstrict}, retset => $bki_values{proretset}, nargs => $bki_values{pronargs}, prosrc => $bki_values{prosrc}, }; } # Emit headers for both files my $tmpext = ".tmp$$"; my $oidsfile = $output_path . 'fmgroids.h'; my $protosfile = $output_path . 'fmgrprotos.h'; my $tabfile = $output_path . 'fmgrtab.c'; open my $ofh, '>', $oidsfile . $tmpext or die "Could not open $oidsfile$tmpext: $!"; open my $pfh, '>', $protosfile . $tmpext or die "Could not open $protosfile$tmpext: $!"; open my $tfh, '>', $tabfile . $tmpext or die "Could not open $tabfile$tmpext: $!"; print $ofh qq|/*------------------------------------------------------------------------- * * fmgroids.h * Macros that define the OIDs of built-in functions. * * These macros can be used to avoid a catalog lookup when a specific * fmgr-callable function needs to be referenced. * * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES * ****************************** * *** DO NOT EDIT THIS FILE! *** * ****************************** * * It has been GENERATED by $0 * from $infile * *------------------------------------------------------------------------- */ #ifndef FMGROIDS_H #define FMGROIDS_H /* * Constant macros for the OIDs of entries in pg_proc. * * NOTE: macros are named after the prosrc value, ie the actual C name * of the implementing function, not the proname which may be overloaded. * For example, we want to be able to assign different macro names to both * char_text() and name_text() even though these both appear with proname * 'text'. If the same C function appears in more than one pg_proc entry, * its equivalent macro will be defined with the lowest OID among those * entries. */ |; print $pfh qq|/*------------------------------------------------------------------------- * * fmgrprotos.h * Prototypes for built-in functions. * * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES * ****************************** * *** DO NOT EDIT THIS FILE! *** * ****************************** * * It has been GENERATED by $0 * from $infile * *------------------------------------------------------------------------- */ #ifndef FMGRPROTOS_H #define FMGRPROTOS_H #include "fmgr.h" |; print $tfh qq|/*------------------------------------------------------------------------- * * fmgrtab.c * The function manager's table of internal functions. * * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * NOTES * * ****************************** * *** DO NOT EDIT THIS FILE! *** * ****************************** * * It has been GENERATED by $0 * from $infile * *------------------------------------------------------------------------- */ #include "postgres.h" #include "utils/fmgrtab.h" #include "utils/fmgrprotos.h" |; # Emit #define's and extern's -- only one per prosrc value my %seenit; foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr) { next if $seenit{ $s->{prosrc} }; $seenit{ $s->{prosrc} } = 1; print $ofh "#define F_" . uc $s->{prosrc} . " $s->{oid}\n"; print $pfh "extern Datum $s->{prosrc}(PG_FUNCTION_ARGS);\n"; } # Create the fmgr_builtins table print $tfh "\nconst FmgrBuiltin fmgr_builtins[] = {\n"; my %bmap; $bmap{'t'} = 'true'; $bmap{'f'} = 'false'; foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr) { print $tfh " { $s->{oid}, \"$s->{prosrc}\", $s->{nargs}, $bmap{$s->{strict}}, $bmap{$s->{retset}}, $s->{prosrc} },\n"; } # And add the file footers. print $ofh "\n#endif /* FMGROIDS_H */\n"; print $pfh "\n#endif /* FMGRPROTOS_H */\n"; print $tfh qq| /* dummy entry is easier than getting rid of comma after last real one */ /* (not that there has ever been anything wrong with *having* a comma after the last field in an array initializer) */ { 0, NULL, 0, false, false, NULL } }; /* Note fmgr_nbuiltins excludes the dummy entry */ const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1; |; close($ofh); close($pfh); close($tfh); # Finally, rename the completed files into place. Catalog::RenameTempFile($oidsfile, $tmpext); Catalog::RenameTempFile($protosfile, $tmpext); Catalog::RenameTempFile($tabfile, $tmpext); sub usage { die <. EOM } exit 0;