summaryrefslogtreecommitdiff
path: root/fix_for_loops.pl
blob: 200867e170ce6ad3dd4d6d210cfc6ed9f9b2ce2e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#!/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;
}