mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-30 00:04:49 -04:00 
			
		
		
		
	Fix Gen_fmgrtab.sh to not rely on hard-wired knowledge of the column numbers
in pg_proc. Also make it not emit duplicate extern declarations, and make it a bit more bulletproof in some other small ways. Likewise fix the equally hard-wired, and utterly undocumented, knowledge in the MSVC build scripts. For testing purposes and perhaps other uses in future, pull out that portion of the MSVC scripts into a standalone perl script equivalent to Gen_fmgrtab.sh, and make it generate actually identical output, rather than just more-or-less-the-same output. Motivated by looking at Pavel's variadic function patch. Whether or not that gets accepted, we can be sure that pg_proc's column set will change again in the future; it's time to not have to deal with this gotcha.
This commit is contained in:
		
							parent
							
								
									dab421d2f0
								
							
						
					
					
						commit
						eeee06919f
					
				
							
								
								
									
										194
									
								
								src/backend/utils/Gen_fmgrtab.pl
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										194
									
								
								src/backend/utils/Gen_fmgrtab.pl
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,194 @@ | ||||
| #! /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; | ||||
| @ -4,12 +4,14 @@ | ||||
| # 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 $ | ||||
| # | ||||
| #------------------------------------------------------------------------- | ||||
| 
 | ||||
| @ -70,20 +72,35 @@ TABLEFILE=fmgrtab.c | ||||
| 
 | ||||
| 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 | ||||
| @ -120,7 +137,7 @@ cat > "$$-$OIDSFILE" <<FuNkYfMgRsTuFf | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| #ifndef	$cpp_define | ||||
| #ifndef $cpp_define | ||||
| #define $cpp_define | ||||
| 
 | ||||
| /* | ||||
| @ -136,12 +153,9 @@ cat > "$$-$OIDSFILE" <<FuNkYfMgRsTuFf | ||||
|  */ | ||||
| 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 | ||||
| @ -151,7 +165,7 @@ fi | ||||
| 
 | ||||
| cat >> "$$-$OIDSFILE" <<FuNkYfMgRsTuFf | ||||
| 
 | ||||
| #endif	/* $cpp_define */ | ||||
| #endif /* $cpp_define */ | ||||
| FuNkYfMgRsTuFf | ||||
| 
 | ||||
| # | ||||
| @ -186,9 +200,8 @@ cat > "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF | ||||
| 
 | ||||
| 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 | ||||
| @ -205,17 +218,14 @@ FuNkYfMgRtAbStUfF | ||||
| # 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 | ||||
| @ -232,7 +242,6 @@ cat >> "$$-$TABLEFILE" <<FuNkYfMgRtAbStUfF | ||||
| 
 | ||||
| /* 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 | ||||
|  | ||||
| @ -3,7 +3,7 @@ package Solution; | ||||
| # | ||||
| # 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; | ||||
| @ -198,61 +198,12 @@ s{PG_VERSION_STR "[^"]+"}{__STRINGIFY(x) #x\n#define __STRINGIFY2(z) __STRINGIFY | ||||
|     $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')) | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user