Make assorted quality-of-life improvements in gen_node_support.pl.
authorTom Lane <[email protected]>
Sat, 9 Jul 2022 19:15:05 +0000 (15:15 -0400)
committerTom Lane <[email protected]>
Sat, 9 Jul 2022 19:15:05 +0000 (15:15 -0400)
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

src/backend/nodes/gen_node_support.pl

index dca5819f95142bbf46cbf13c838b70ad54b776bc..4a7902e6bfb7b5d6f59cad76e11f725d78d06870 100644 (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;
+}