#!/usr/bin/perl # # Generate lwlocknames.h from lwlocklist.h # Copyright (c) 2000-2025, PostgreSQL Global Development Group use strict; use warnings FATAL => 'all'; use Getopt::Long; my $output_path = '.'; my $lastlockidx = -1; my $continue = "\n"; GetOptions('outdir:s' => \$output_path); open my $lwlocklist, '<', $ARGV[0] or die; open my $wait_event_names, '<', $ARGV[1] or die; # Include PID in suffix in case parallel make runs this multiple times. my $htmp = "$output_path/lwlocknames.h.tmp$$"; open my $h, '>', $htmp or die "Could not open $htmp: $!"; my $autogen = "/* autogenerated from src/include/storage/lwlocklist.h, do not edit */\n"; print $h $autogen; print $h "/* there is deliberately not an #ifndef LWLOCKNAMES_H here */\n\n"; # # First, record the predefined LWLocks listed in wait_event_names.txt. We'll # cross-check those with the ones in lwlocklist.h. # my @wait_event_lwlocks; my $record_lwlocks = 0; while (<$wait_event_names>) { chomp; # Check for end marker. last if /^# END OF PREDEFINED LWLOCKS/; # Skip comments and empty lines. next if /^#/; next if /^\s*$/; # Start recording LWLocks when we find the WaitEventLWLock section. if (/^Section: ClassName - WaitEventLWLock$/) { $record_lwlocks = 1; next; } # Go to the next line if we are not yet recording LWLocks. next if not $record_lwlocks; # Record the LWLock. (my $waiteventname, my $waitevendocsentence) = split(/\t/, $_); push(@wait_event_lwlocks, $waiteventname); } my $in_comment = 0; my $i = 0; while (<$lwlocklist>) { chomp; # Skip single-line C comments and empty lines next if m{^\s*/\*.*\*/$}; next if /^\s*$/; # skip multiline C comments if ($in_comment == 1) { $in_comment = 0 if m{\*/}; next; } elsif (m{^\s*/\*}) { $in_comment = 1; next; } die "unable to parse lwlocklist.h line \"$_\"" unless /^PG_LWLOCK\((\d+),\s+(\w+)\)$/; (my $lockidx, my $lockname) = ($1, $2); die "lwlocklist.h not in order" if $lockidx < $lastlockidx; die "lwlocklist.h has duplicates" if $lockidx == $lastlockidx; die "$lockname defined in lwlocklist.h but missing from " . "wait_event_names.txt" if $i >= scalar @wait_event_lwlocks; die "lists of predefined LWLocks do not match (first mismatch at " . "$wait_event_lwlocks[$i] in wait_event_names.txt and $lockname in " . "lwlocklist.h)" if $wait_event_lwlocks[$i] ne $lockname; $i++; while ($lastlockidx < $lockidx - 1) { ++$lastlockidx; $continue = ",\n"; } $lastlockidx = $lockidx; $continue = ",\n"; # Add a "Lock" suffix to each lock name, as the C code depends on that printf $h "#define %-32s (&MainLWLockArray[$lockidx].lock)\n", $lockname . "Lock"; } die "$wait_event_lwlocks[$i] defined in wait_event_names.txt but missing from " . "lwlocklist.h" if $i < scalar @wait_event_lwlocks; print $h "\n"; printf $h "#define NUM_INDIVIDUAL_LWLOCKS %s\n", $lastlockidx + 1; close $h; rename($htmp, "$output_path/lwlocknames.h") || die "rename: $htmp to $output_path/lwlocknames.h: $!"; close $lwlocklist;