#!/usr/bin/perl # Transform for-loop variable declarations from: # for (int i = 0; i < n; i++) # to: # int i; # for (i = 0; i < n; i++) # # Tracks declared variables per-scope (approximated by function boundaries) # to avoid duplicate declarations. use strict; use warnings; my %declared; # Track declared variables in current scope while (<>) { # Reset scope tracking when we see a function definition start # Pattern 1: identifier followed by ( ... ) { at end of line (single line) # Pattern 2: standalone { on a line (for K&R style function defs) if ((/^\w.*\)\s*(const)?\s*\{\s*$/ && !/^\s*(for|if|while|switch|else)\b/) || /^\{\s*$/) { %declared = (); } # Skip lines that are comments if (/^\s*\/\//) { print; next; } # Skip problematic patterns where we can't simply insert a declaration before if (/\}\s*for\s*\(/ || /else\s*\{?\s*for\s*\(/) { print; next; } # Pattern: for (TYPE WHITESPACE [*] VAR = INIT; ...) if (/^(\s*)(.*?)\bfor\s*\(\s*(const\s+)?(unsigned\s+)?(\w+)(\s*\*{1,2}\s*|\s+)(\w+)\s*=\s*/) { my $indent = $1; my $prefix = $2; my $const = $3 // ''; my $unsigned = $4 // ''; my $type = $5; my $starsep = $6; my $var = $7; # Skip if already transformed or invalid next if $type eq $var; # Skip if prefix contains control flow if ($prefix =~ /\b(if|else|while|switch)\s*\(.*\)\s*$/ || $prefix =~ /\belse\s*$/) { print; next; } # Extract stars from starsep my $stars = ''; if ($starsep =~ /(\*+)/) { $stars = $1; } # Build full type string my $fulltype = "${const}${unsigned}${type} ${stars}"; $fulltype =~ s/\s+/ /g; # Check if this exact variable (by name) was already declared in this scope my $key = $var; if (!exists $declared{$key}) { # First occurrence - add declaration print "${indent}${fulltype}${var};\n"; $declared{$key} = 1; } # Always modify the for loop if ($prefix ne '') { s/\bfor\s*\(\s*(const\s+)?(unsigned\s+)?(\w+)(\s*\*{1,2}\s*|\s+)(\w+)\s*=/for (${var} =/; } else { s/^(\s*)for\s*\(\s*(const\s+)?(unsigned\s+)?(\w+)(\s*\*{1,2}\s*|\s+)(\w+)\s*=/${1}for (${var} =/; } } print; }