--- /dev/null
+#! /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-2008, 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.1 2008/06/23 17:54:29 tgl 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 (<I>)
+{
+ 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 (<I>)
+{
+ 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-2008, 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-2008, 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;
# Gen_fmgrtab.sh
# shell script to generate fmgroids.h and fmgrtab.c from pg_proc.h
#
+# NOTE: if you change this, you need to fix Gen_fmgrtab.pl too!
+#
# Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
# Portions Copyright (c) 1994, Regents of the University of California
#
#
# IDENTIFICATION
-# $PostgreSQL: pgsql/src/backend/utils/Gen_fmgrtab.sh,v 1.39 2008/05/02 14:16:24 petere Exp $
+# $PostgreSQL: pgsql/src/backend/utils/Gen_fmgrtab.sh,v 1.40 2008/06/23 17:54:29 tgl Exp $
#
#-------------------------------------------------------------------------
trap 'echo "Caught signal." ; cleanup ; exit 1' 1 2 15
+#
+# Collect the column numbers of the pg_proc columns we need. Because we will
+# be looking at data that includes the OID as the first column, add one to
+# each column number.
+#
+proname=`egrep '^#define Anum_pg_proc_proname[ ]' $INFILE | $AWK '{print $3+1}'`
+prolang=`egrep '^#define Anum_pg_proc_prolang[ ]' $INFILE | $AWK '{print $3+1}'`
+proisstrict=`egrep '^#define Anum_pg_proc_proisstrict[ ]' $INFILE | $AWK '{print $3+1}'`
+proretset=`egrep '^#define Anum_pg_proc_proretset[ ]' $INFILE | $AWK '{print $3+1}'`
+pronargs=`egrep '^#define Anum_pg_proc_pronargs[ ]' $INFILE | $AWK '{print $3+1}'`
+prosrc=`egrep '^#define Anum_pg_proc_prosrc[ ]' $INFILE | $AWK '{print $3+1}'`
#
-# Generate the file containing raw pg_proc tuple data
-# (but only for "internal" language procedures...).
-# Basically we strip off the DATA macro call, leaving procedure OID as $1
+# Generate the file containing raw pg_proc data. We do three things here:
+# 1. Strip off the DATA macro call, leaving procedure OID as $1
# and all the pg_proc field values as $2, $3, etc on each line.
+# 2. Fold quoted fields to simple "xxx". We need this because such fields
+# may contain whitespace, which would confuse awk's counting of fields.
+# Fortunately, this script doesn't need to look at any fields that might
+# need quoting, so this simple hack is sufficient.
+# 3. Select out just the rows for internal-language procedures.
#
-# Note assumption here that prolang == $5 and INTERNALlanguageId == 12.
+# Note assumption here that INTERNALlanguageId == 12.
#
egrep '^DATA' $INFILE | \
-sed -e 's/^.*OID[^=]*=[^0-9]*//' \
- -e 's/(//g' \
- -e 's/[ ]*).*$//' | \
-$AWK '$5 == "12" { print }' | \
+sed -e 's/^[^O]*OID[^=]*=[ ]*//' \
+ -e 's/(//' \
+ -e 's/"[^"]*"/"xxx"/g' | \
+$AWK "\$$prolang == \"12\" { print }" | \
sort -n > $SORTEDFILE
if [ $? -ne 0 ]; then
*
*-------------------------------------------------------------------------
*/
-#ifndef $cpp_define
+#ifndef $cpp_define
#define $cpp_define
/*
*/
FuNkYfMgRsTuFf
-# Note assumption here that prosrc == $(NF-3).
-
tr 'abcdefghijklmnopqrstuvwxyz' 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' < $SORTEDFILE | \
-$AWK '
-BEGIN { OFS = ""; }
- { if (seenit[$(NF-3)]++ == 0) print "#define F_", $(NF-3), " ", $1; }' >> "$$-$OIDSFILE"
+$AWK "{ if (seenit[\$$prosrc]++ == 0)
+ printf \"#define F_%s %s\\n\", \$$prosrc, \$1; }" >> "$$-$OIDSFILE"
if [ $? -ne 0 ]; then
cleanup
cat >> "$$-$OIDSFILE" <<FuNkYfMgRsTuFf
-#endif /* $cpp_define */
+#endif /* $cpp_define */
FuNkYfMgRsTuFf
#
FuNkYfMgRtAbStUfF
-# Note assumption here that prosrc == $(NF-3).
-
-$AWK '{ print "extern Datum", $(NF-3), "(PG_FUNCTION_ARGS);"; }' $SORTEDFILE >> "$$-$TABLEFILE"
+$AWK "{ if (seenit[\$$prosrc]++ == 0)
+ print \"extern Datum\", \$$prosrc, \"(PG_FUNCTION_ARGS);\"; }" $SORTEDFILE >> "$$-$TABLEFILE"
if [ $? -ne 0 ]; then
cleanup
# Note: using awk arrays to translate from pg_proc values to fmgrtab values
# may seem tedious, but avoid the temptation to write a quick x?y:z
# conditional expression instead. Not all awks have conditional expressions.
-#
-# Note assumptions here that prosrc == $(NF-3), pronargs == $13,
-# proisstrict == $10, proretset == $11
-$AWK 'BEGIN {
- Bool["t"] = "true"
- Bool["f"] = "false"
+$AWK "BEGIN {
+ Bool[\"t\"] = \"true\";
+ Bool[\"f\"] = \"false\";
}
-{ printf (" { %d, \"%s\", %d, %s, %s, %s },\n"), \
- $1, $(NF-3), $13, Bool[$10], Bool[$11], $(NF-3)
-}' $SORTEDFILE >> "$$-$TABLEFILE"
+{ printf (\" { %d, \\\"%s\\\", %d, %s, %s, %s },\\n\"),
+ \$1, \$$prosrc, \$$pronargs, Bool[\$$proisstrict], Bool[\$$proretset], \$$prosrc ;
+}" $SORTEDFILE >> "$$-$TABLEFILE"
if [ $? -ne 0 ]; then
cleanup
/* Note fmgr_nbuiltins excludes the dummy entry */
const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1;
-
FuNkYfMgRtAbStUfF
# We use the temporary files to avoid problems with concurrent runs
#
# Package that encapsulates a Visual C++ solution file generation
#
-# $PostgreSQL: pgsql/src/tools/msvc/Solution.pm,v 1.41 2008/05/03 00:24:06 adunstan Exp $
+# $PostgreSQL: pgsql/src/tools/msvc/Solution.pm,v 1.42 2008/06/23 17:54:30 tgl Exp $
#
use Carp;
use strict;
$self->GenerateDefFile("src\\interfaces\\ecpg\\compatlib\\compatlib.def","src\\interfaces\\ecpg\\compatlib\\exports.txt","LIBECPG_COMPAT");
$self->GenerateDefFile("src\\interfaces\\ecpg\\pgtypeslib\\pgtypeslib.def","src\\interfaces\\ecpg\\pgtypeslib\\exports.txt","LIBPGTYPES");
- if (IsNewer("src\\backend\\utils\\fmgrtab.c","src\\include\\catalog\\pg_proc.h"))
+ if (IsNewer('src\backend\utils\fmgrtab.c','src\include\catalog\pg_proc.h'))
{
print "Generating fmgrtab.c and fmgroids.h...\n";
- open(I,"src\\include\\catalog\\pg_proc.h") || confess "Could not open pg_proc.h";
- my @fmgr = ();
- my %seenit;
- while (<I>)
- {
- next unless (/^DATA/);
- s/^.*OID[^=]*=[^0-9]*//;
- s/\(//g;
- s/[ \t]*\).*$//;
- my @p = split;
- next if ($p[4] ne "12");
- push @fmgr,
- {
- oid => $p[0],
- proname => $p[1],
- prosrc => $p[$#p-3],
- nargs => $p[12],
- strict => $p[9],
- retset => $p[10],
- };
- }
- close(I);
-
- open(H,'>', 'src\include\utils\fmgroids.h')
- ||confess "Could not open fmgroids.h";
- print H
- "/* fmgroids.h generated for Visual C++ */\n#ifndef FMGROIDS_H\n#define FMGROIDS_H\n\n";
- open(T,">src\\backend\\utils\\fmgrtab.c") || confess "Could not open fmgrtab.c";
- print T
-"/* fmgrtab.c generated for Visual C++ */\n#include \"postgres.h\"\n#include \"utils/fmgrtab.h\"\n\n";
- 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";
- }
- print H "\n#endif\n /* FMGROIDS_H */\n";
- close(H);
- print T "const 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";
- }
-
- print T
-" { 0, NULL, 0, false, false, NULL }\n};\n\nconst int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1;\n";
- close(T);
+ chdir('src\backend\utils');
+ system("perl Gen_fmgrtab.pl ../../../src/include/catalog/pg_proc.h");
+ chdir('..\..\..');
}
if (IsNewer('src\include\utils\probes.h','src\backend\utils\pg_trace.d'))