#! /usr/bin/perl -w #------------------------------------------------------------------------- # # Gen_fmgrtab.pl # Perl equivalent of Gen_fmgrtab.sh # # Usage: perl Gen_fmgrtab.pl path-to-pg_proc.h # # The reason for implementing this functionality twice is that we don't # require people to have perl to build from a tarball, but on the other # hand Windows can't deal with shell scripts. # # Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group # Portions Copyright (c) 1994, Regents of the University of California # # # IDENTIFICATION # $PostgreSQL: pgsql/src/backend/utils/Gen_fmgrtab.pl,v 1.3 2010/01/02 16:57:53 momjian Exp $ # #------------------------------------------------------------------------- use strict; use warnings; # Collect arguments my $infile = shift; defined($infile) || die "$0: missing required argument: pg_proc.h\n"; # Note: see Gen_fmgrtab.sh for detailed commentary on what this is doing # Collect column numbers for pg_proc columns we need my ($proname, $prolang, $proisstrict, $proretset, $pronargs, $prosrc); open(I, $infile) || die "Could not open $infile: $!"; while () { if (m/#define Anum_pg_proc_proname\s+(\d+)/) { $proname = $1; } if (m/#define Anum_pg_proc_prolang\s+(\d+)/) { $prolang = $1; } if (m/#define Anum_pg_proc_proisstrict\s+(\d+)/) { $proisstrict = $1; } if (m/#define Anum_pg_proc_proretset\s+(\d+)/) { $proretset = $1; } if (m/#define Anum_pg_proc_pronargs\s+(\d+)/) { $pronargs = $1; } if (m/#define Anum_pg_proc_prosrc\s+(\d+)/) { $prosrc = $1; } } close(I); # Collect the raw data my @fmgr = (); open(I, $infile) || die "Could not open $infile: $!"; while () { next unless (/^DATA/); s/^[^O]*OID[^=]*=[ \t]*//; s/\(//; s/"[^"]*"/"xxx"/g; my @p = split; next if ($p[$prolang] ne "12"); push @fmgr, { oid => $p[0], proname => $p[$proname], strict => $p[$proisstrict], retset => $p[$proretset], nargs => $p[$pronargs], prosrc => $p[$prosrc], }; } close(I); # Emit headers for both files open(H, '>', "$$-fmgroids.h") || die "Could not open $$-fmgroids.h: $!"; print H 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-2010, 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. */ |; open(T, '>', "$$-fmgrtab.c") || die "Could not open $$-fmgrtab.c: $!"; print T qq|/*------------------------------------------------------------------------- * * fmgrtab.c * The function manager's table of internal functions. * * Portions Copyright (c) 1996-2010, 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" |; # 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 H "#define F_" . uc $s->{prosrc} . " $s->{oid}\n"; print T "extern Datum $s->{prosrc} (PG_FUNCTION_ARGS);\n"; } # Create the fmgr_builtins table print T "\nconst FmgrBuiltin fmgr_builtins[] = {\n"; my %bmap; $bmap{'t'} = 'true'; $bmap{'f'} = 'false'; foreach my $s (sort {$a->{oid} <=> $b->{oid}} @fmgr) { print T " { $s->{oid}, \"$s->{prosrc}\", $s->{nargs}, $bmap{$s->{strict}}, $bmap{$s->{retset}}, $s->{prosrc} },\n"; } # And add the file footers. print H "\n#endif /* FMGROIDS_H */\n"; close(H); print T 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(T); # Finally, rename the completed files into place. rename "$$-fmgroids.h", "fmgroids.h" || die "Could not rename $$-fmgroids.h to fmgroids.h: $!"; rename "$$-fmgrtab.c", "fmgrtab.c" || die "Could not rename $$-fmgrtab.c to fmgrtab.c: $!"; exit 0;