return grep { $_ eq $x } @_;
}
+# output file names
+my @output_files;
# collect node names
my @node_types = qw(Node);
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 '';
$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;
else
{
die
- "$infile:$.: unrecognized attribute \"$attr\"\n";
+ "$infile:$node_attrs_lineno: unrecognized attribute \"$attr\"\n";
}
}
# 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)
)
{
die
- "$infile:$.: unrecognized attribute \"$attr\"\n";
+ "$infile:$lineno: unrecognized attribute \"$attr\"\n";
}
}
}
{
if ($is_node_struct)
{
- #warn "$infile:$.: could not parse \"$line\"\n";
+ #warn "$infile:$lineno: could not parse \"$line\"\n";
}
}
}
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)
{
# 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;
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*')
}
else
{
- die "could not handle type \"$t\" in struct \"$n\" field \"$f\"";
+ die
+ "could not handle type \"$t\" in struct \"$n\" field \"$f\"\n";
}
}
# 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;
}
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*')
}
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
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;
+}