]> granicus.if.org Git - postgresql/blob - src/backend/utils/Gen_fmgrtab.pl
Update copyright for 2014
[postgresql] / src / backend / utils / Gen_fmgrtab.pl
1 #! /usr/bin/perl -w
2 #-------------------------------------------------------------------------
3 #
4 # Gen_fmgrtab.pl
5 #    Perl script that generates fmgroids.h and fmgrtab.c from pg_proc.h
6 #
7 # Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
8 # Portions Copyright (c) 1994, Regents of the University of California
9 #
10 #
11 # IDENTIFICATION
12 #    src/backend/utils/Gen_fmgrtab.pl
13 #
14 #-------------------------------------------------------------------------
15
16 use Catalog;
17
18 use strict;
19 use warnings;
20
21 # Collect arguments
22 my $infile;    # pg_proc.h
23 my $output_path = '';
24 while (@ARGV)
25 {
26         my $arg = shift @ARGV;
27         if ($arg !~ /^-/)
28         {
29                 $infile = $arg;
30         }
31         elsif ($arg =~ /^-o/)
32         {
33                 $output_path = length($arg) > 2 ? substr($arg, 2) : shift @ARGV;
34         }
35         else
36         {
37                 usage();
38         }
39 }
40
41 # Make sure output_path ends in a slash.
42 if ($output_path ne '' && substr($output_path, -1) ne '/')
43 {
44         $output_path .= '/';
45 }
46
47 # Read all the data from the include/catalog files.
48 my $catalogs = Catalog::Catalogs($infile);
49
50 # Collect the raw data from pg_proc.h.
51 my @fmgr = ();
52 my @attnames;
53 foreach my $column (@{ $catalogs->{pg_proc}->{columns} })
54 {
55         push @attnames, keys %$column;
56 }
57
58 my $data = $catalogs->{pg_proc}->{data};
59 foreach my $row (@$data)
60 {
61
62         # To construct fmgroids.h and fmgrtab.c, we need to inspect some
63         # of the individual data fields.  Just splitting on whitespace
64         # won't work, because some quoted fields might contain internal
65         # whitespace.  We handle this by folding them all to a simple
66         # "xxx". Fortunately, this script doesn't need to look at any
67         # fields that might need quoting, so this simple hack is
68         # sufficient.
69         $row->{bki_values} =~ s/"[^"]*"/"xxx"/g;
70         @{$row}{@attnames} = split /\s+/, $row->{bki_values};
71
72         # Select out just the rows for internal-language procedures.
73         # Note assumption here that INTERNALlanguageId is 12.
74         next if $row->{prolang} ne '12';
75
76         push @fmgr,
77           { oid    => $row->{oid},
78                 strict => $row->{proisstrict},
79                 retset => $row->{proretset},
80                 nargs  => $row->{pronargs},
81                 prosrc => $row->{prosrc}, };
82
83         # Hack to work around memory leak in some versions of Perl
84         $row = undef;
85 }
86
87 # Emit headers for both files
88 my $tmpext   = ".tmp$$";
89 my $oidsfile = $output_path . 'fmgroids.h';
90 my $tabfile  = $output_path . 'fmgrtab.c';
91
92 open H, '>', $oidsfile . $tmpext or die "Could not open $oidsfile$tmpext: $!";
93 open T, '>', $tabfile . $tmpext  or die "Could not open $tabfile$tmpext: $!";
94
95 print H
96 qq|/*-------------------------------------------------------------------------
97  *
98  * fmgroids.h
99  *    Macros that define the OIDs of built-in functions.
100  *
101  * These macros can be used to avoid a catalog lookup when a specific
102  * fmgr-callable function needs to be referenced.
103  *
104  * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
105  * Portions Copyright (c) 1994, Regents of the University of California
106  *
107  * NOTES
108  *      ******************************
109  *      *** DO NOT EDIT THIS FILE! ***
110  *      ******************************
111  *
112  *      It has been GENERATED by $0
113  *      from $infile
114  *
115  *-------------------------------------------------------------------------
116  */
117 #ifndef FMGROIDS_H
118 #define FMGROIDS_H
119
120 /*
121  *      Constant macros for the OIDs of entries in pg_proc.
122  *
123  *      NOTE: macros are named after the prosrc value, ie the actual C name
124  *      of the implementing function, not the proname which may be overloaded.
125  *      For example, we want to be able to assign different macro names to both
126  *      char_text() and name_text() even though these both appear with proname
127  *      'text'.  If the same C function appears in more than one pg_proc entry,
128  *      its equivalent macro will be defined with the lowest OID among those
129  *      entries.
130  */
131 |;
132
133 print T
134 qq|/*-------------------------------------------------------------------------
135  *
136  * fmgrtab.c
137  *    The function manager's table of internal functions.
138  *
139  * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
140  * Portions Copyright (c) 1994, Regents of the University of California
141  *
142  * NOTES
143  *
144  *      ******************************
145  *      *** DO NOT EDIT THIS FILE! ***
146  *      ******************************
147  *
148  *      It has been GENERATED by $0
149  *      from $infile
150  *
151  *-------------------------------------------------------------------------
152  */
153
154 #include "postgres.h"
155
156 #include "utils/fmgrtab.h"
157
158 |;
159
160 # Emit #define's and extern's -- only one per prosrc value
161 my %seenit;
162 foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr)
163 {
164         next if $seenit{ $s->{prosrc} };
165         $seenit{ $s->{prosrc} } = 1;
166         print H "#define F_" . uc $s->{prosrc} . " $s->{oid}\n";
167         print T "extern Datum $s->{prosrc} (PG_FUNCTION_ARGS);\n";
168 }
169
170 # Create the fmgr_builtins table
171 print T "\nconst FmgrBuiltin fmgr_builtins[] = {\n";
172 my %bmap;
173 $bmap{'t'} = 'true';
174 $bmap{'f'} = 'false';
175 foreach my $s (sort { $a->{oid} <=> $b->{oid} } @fmgr)
176 {
177         print T
178 "  { $s->{oid}, \"$s->{prosrc}\", $s->{nargs}, $bmap{$s->{strict}}, $bmap{$s->{retset}}, $s->{prosrc} },\n";
179 }
180
181 # And add the file footers.
182 print H "\n#endif /* FMGROIDS_H */\n";
183
184 print T
185 qq|  /* dummy entry is easier than getting rid of comma after last real one */
186   /* (not that there has ever been anything wrong with *having* a
187      comma after the last field in an array initializer) */
188   { 0, NULL, 0, false, false, NULL }
189 };
190
191 /* Note fmgr_nbuiltins excludes the dummy entry */
192 const int fmgr_nbuiltins = (sizeof(fmgr_builtins) / sizeof(FmgrBuiltin)) - 1;
193 |;
194
195 close(H);
196 close(T);
197
198 # Finally, rename the completed files into place.
199 Catalog::RenameTempFile($oidsfile, $tmpext);
200 Catalog::RenameTempFile($tabfile,  $tmpext);
201
202 sub usage
203 {
204         die <<EOM;
205 Usage: perl -I [directory of Catalog.pm] Gen_fmgrtab.pl [path to pg_proc.h]
206
207 Gen_fmgrtab.pl generates fmgroids.h and fmgrtab.c from pg_proc.h
208
209 Report bugs to <pgsql-bugs\@postgresql.org>.
210 EOM
211 }
212
213 exit 0;