Make assorted quality-of-life improvements in gen_node_support.pl.

Fix incorrect reporting of the location of errors (such as bogus
node attributes).  Add header comments to the generated files,
containing copyright notices and reminders that they are generated
files, as we do in other file-generating scripts.  Arrange to not
leave a clutter of temporary files when the script detects an error.

Discussion: https://postgr.es/m/3843645.1657385930@sss.pgh.pa.us
This commit is contained in:
Tom Lane 2022-07-09 15:15:05 -04:00
parent 3cd0ac9878
commit 8eccaf6525
1 changed files with 101 additions and 23 deletions

View File

@ -34,6 +34,8 @@ sub elem
return grep { $_ eq $x } @_;
}
# output file names
my @output_files;
# collect node names
my @node_types = qw(Node);
@ -124,19 +126,31 @@ foreach my $infile (@ARGV)
my $supertype_field;
my $node_attrs = '';
my $node_attrs_lineno;
my @my_fields;
my %my_field_types;
my %my_field_attrs;
open my $ifh, '<', $infile or die "could not open \"$infile\": $!";
my $file_content = do { local $/; <$ifh> };
my $raw_file_content = do { local $/; <$ifh> };
# strip C comments
$file_content =~ s{/\*.*?\*/}{}gs;
# strip C comments, preserving newlines so we can count lines correctly
my $file_content = '';
while ($raw_file_content =~ m{^(.*?)(/\*.*?\*/)(.*)$}s)
{
$file_content .= $1;
my $comment = $2;
$raw_file_content = $3;
$comment =~ tr/\n//cd;
$file_content .= $comment;
}
$file_content .= $raw_file_content;
my $lineno = 0;
foreach my $line (split /\n/, $file_content)
{
$lineno++;
chomp $line;
$line =~ s/\s*$//;
next if $line eq '';
@ -153,13 +167,14 @@ foreach my $infile (@ARGV)
$is_node_struct = 0;
$supertype = undef;
next if $line eq '{';
die "$infile:$.: expected opening brace\n";
die "$infile:$lineno: expected opening brace\n";
}
# second line could be node attributes
elsif ($subline == 2
&& $line =~ /^\s*pg_node_attr\(([\w(), ]*)\)$/)
{
$node_attrs = $1;
$node_attrs = $1;
$node_attrs_lineno = $lineno;
# hack: don't count the line
$subline--;
next;
@ -236,7 +251,7 @@ foreach my $infile (@ARGV)
else
{
die
"$infile:$.: unrecognized attribute \"$attr\"\n";
"$infile:$node_attrs_lineno: unrecognized attribute \"$attr\"\n";
}
}
@ -330,7 +345,9 @@ foreach my $infile (@ARGV)
# strip space between type and "*" (pointer) */
$type =~ s/\s+\*$/*/;
die if $type eq '';
die
"$infile:$lineno: cannot parse data type in \"$line\"\n"
if $type eq '';
my @attrs;
if ($attrs)
@ -347,7 +364,7 @@ foreach my $infile (@ARGV)
)
{
die
"$infile:$.: unrecognized attribute \"$attr\"\n";
"$infile:$lineno: unrecognized attribute \"$attr\"\n";
}
}
}
@ -362,7 +379,7 @@ foreach my $infile (@ARGV)
{
if ($is_node_struct)
{
#warn "$infile:$.: could not parse \"$line\"\n";
#warn "$infile:$lineno: could not parse \"$line\"\n";
}
}
}
@ -411,10 +428,35 @@ foreach my $infile (@ARGV)
my $tmpext = ".tmp$$";
# opening boilerplate for output files
my $header_comment =
'/*-------------------------------------------------------------------------
*
* %s
* Generated node infrastructure code
*
* Portions Copyright (c) 1996-2022, 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 src/backend/nodes/gen_node_support.pl
*
*-------------------------------------------------------------------------
*/
';
# nodetags.h
push @output_files, 'nodetags.h';
open my $nt, '>', 'nodetags.h' . $tmpext or die $!;
printf $nt $header_comment, 'nodetags.h';
my $i = 1;
foreach my $n (@node_types, @extra_tags)
{
@ -437,11 +479,20 @@ foreach my $infile (sort @ARGV)
# copyfuncs.c, equalfuncs.c
open my $cff, '>', 'copyfuncs.funcs.c' . $tmpext or die $!;
open my $eff, '>', 'equalfuncs.funcs.c' . $tmpext or die $!;
open my $cfs, '>', 'copyfuncs.switch.c' . $tmpext or die $!;
push @output_files, 'copyfuncs.funcs.c';
open my $cff, '>', 'copyfuncs.funcs.c' . $tmpext or die $!;
push @output_files, 'equalfuncs.funcs.c';
open my $eff, '>', 'equalfuncs.funcs.c' . $tmpext or die $!;
push @output_files, 'copyfuncs.switch.c';
open my $cfs, '>', 'copyfuncs.switch.c' . $tmpext or die $!;
push @output_files, 'equalfuncs.switch.c';
open my $efs, '>', 'equalfuncs.switch.c' . $tmpext or die $!;
printf $cff $header_comment, 'copyfuncs.funcs.c';
printf $eff $header_comment, 'equalfuncs.funcs.c';
printf $cfs $header_comment, 'copyfuncs.switch.c';
printf $efs $header_comment, 'equalfuncs.switch.c';
# add required #include lines to each file set
print $cff $node_includes;
print $eff $node_includes;
@ -552,7 +603,7 @@ _equal${n}(const $n *a, const $n *b)
my $tt = $1;
if (!defined $array_size_field)
{
die "no array size defined for $n.$f of type $t";
die "no array size defined for $n.$f of type $t\n";
}
if ($node_type_info{$n}->{field_types}{$array_size_field} eq
'List*')
@ -597,7 +648,8 @@ _equal${n}(const $n *a, const $n *b)
}
else
{
die "could not handle type \"$t\" in struct \"$n\" field \"$f\"";
die
"could not handle type \"$t\" in struct \"$n\" field \"$f\"\n";
}
}
@ -619,11 +671,20 @@ close $efs;
# outfuncs.c, readfuncs.c
open my $off, '>', 'outfuncs.funcs.c' . $tmpext or die $!;
open my $rff, '>', 'readfuncs.funcs.c' . $tmpext or die $!;
open my $ofs, '>', 'outfuncs.switch.c' . $tmpext or die $!;
push @output_files, 'outfuncs.funcs.c';
open my $off, '>', 'outfuncs.funcs.c' . $tmpext or die $!;
push @output_files, 'readfuncs.funcs.c';
open my $rff, '>', 'readfuncs.funcs.c' . $tmpext or die $!;
push @output_files, 'outfuncs.switch.c';
open my $ofs, '>', 'outfuncs.switch.c' . $tmpext or die $!;
push @output_files, 'readfuncs.switch.c';
open my $rfs, '>', 'readfuncs.switch.c' . $tmpext or die $!;
printf $off $header_comment, 'outfuncs.funcs.c';
printf $rff $header_comment, 'readfuncs.funcs.c';
printf $ofs $header_comment, 'outfuncs.switch.c';
printf $rfs $header_comment, 'readfuncs.switch.c';
print $off $node_includes;
print $rff $node_includes;
@ -814,7 +875,7 @@ _read${n}(void)
}
if (!defined $array_size_field)
{
die "no array size defined for $n.$f of type $t";
die "no array size defined for $n.$f of type $t\n";
}
if ($node_type_info{$n}->{field_types}{$array_size_field} eq
'List*')
@ -886,7 +947,8 @@ _read${n}(void)
}
else
{
die "could not handle type \"$t\" in struct \"$n\" field \"$f\"";
die
"could not handle type \"$t\" in struct \"$n\" field \"$f\"\n";
}
# for read_as() without read_write_ignore, we have to read the value
@ -911,10 +973,26 @@ close $ofs;
close $rfs;
# now rename the temporary files to their final name
foreach my $file (
qw(nodetags.h copyfuncs.funcs.c copyfuncs.switch.c equalfuncs.funcs.c equalfuncs.switch.c outfuncs.funcs.c outfuncs.switch.c readfuncs.funcs.c readfuncs.switch.c)
)
# now rename the temporary files to their final names
foreach my $file (@output_files)
{
Catalog::RenameTempFile($file, $tmpext);
}
# Automatically clean up any temp files if the script fails.
END
{
# take care not to change the script's exit value
my $exit_code = $?;
if ($exit_code != 0)
{
foreach my $file (@output_files)
{
unlink($file . $tmpext);
}
}
$? = $exit_code;
}