Version:  2.0.40 2.2.26 2.4.37 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1 4.2 4.3 4.4 4.5 4.6 4.7 4.8 4.9 4.10

Linux/scripts/cleanpatch

  1 #!/usr/bin/perl -w
  2 #
  3 # Clean a patch file -- or directory of patch files -- of stealth whitespace.
  4 # WARNING: this can be a highly destructive operation.  Use with caution.
  5 #
  6 
  7 use bytes;
  8 use File::Basename;
  9 
 10 # Default options
 11 $max_width = 79;
 12 
 13 # Clean up space-tab sequences, either by removing spaces or
 14 # replacing them with tabs.
 15 sub clean_space_tabs($)
 16 {
 17     no bytes;                   # Tab alignment depends on characters
 18 
 19     my($li) = @_;
 20     my($lo) = '';
 21     my $pos = 0;
 22     my $nsp = 0;
 23     my($i, $c);
 24 
 25     for ($i = 0; $i < length($li); $i++) {
 26         $c = substr($li, $i, 1);
 27         if ($c eq "\t") {
 28             my $npos = ($pos+$nsp+8) & ~7;
 29             my $ntab = ($npos >> 3) - ($pos >> 3);
 30             $lo .= "\t" x $ntab;
 31             $pos = $npos;
 32             $nsp = 0;
 33         } elsif ($c eq "\n" || $c eq "\r") {
 34             $lo .= " " x $nsp;
 35             $pos += $nsp;
 36             $nsp = 0;
 37             $lo .= $c;
 38             $pos = 0;
 39         } elsif ($c eq " ") {
 40             $nsp++;
 41         } else {
 42             $lo .= " " x $nsp;
 43             $pos += $nsp;
 44             $nsp = 0;
 45             $lo .= $c;
 46             $pos++;
 47         }
 48     }
 49     $lo .= " " x $nsp;
 50     return $lo;
 51 }
 52 
 53 # Compute the visual width of a string
 54 sub strwidth($) {
 55     no bytes;                   # Tab alignment depends on characters
 56 
 57     my($li) = @_;
 58     my($c, $i);
 59     my $pos = 0;
 60     my $mlen = 0;
 61 
 62     for ($i = 0; $i < length($li); $i++) {
 63         $c = substr($li,$i,1);
 64         if ($c eq "\t") {
 65             $pos = ($pos+8) & ~7;
 66         } elsif ($c eq "\n") {
 67             $mlen = $pos if ($pos > $mlen);
 68             $pos = 0;
 69         } else {
 70             $pos++;
 71         }
 72     }
 73 
 74     $mlen = $pos if ($pos > $mlen);
 75     return $mlen;
 76 }
 77 
 78 $name = basename($0);
 79 
 80 @files = ();
 81 
 82 while (defined($a = shift(@ARGV))) {
 83     if ($a =~ /^-/) {
 84         if ($a eq '-width' || $a eq '-w') {
 85             $max_width = shift(@ARGV)+0;
 86         } else {
 87             print STDERR "Usage: $name [-width #] files...\n";
 88             exit 1;
 89         }
 90     } else {
 91         push(@files, $a);
 92     }
 93 }
 94 
 95 foreach $f ( @files ) {
 96     print STDERR "$name: $f\n";
 97 
 98     if (! -f $f) {
 99         print STDERR "$f: not a file\n";
100         next;
101     }
102 
103     if (!open(FILE, '+<', $f)) {
104         print STDERR "$name: Cannot open file: $f: $!\n";
105         next;
106     }
107 
108     binmode FILE;
109 
110     # First, verify that it is not a binary file; consider any file
111     # with a zero byte to be a binary file.  Is there any better, or
112     # additional, heuristic that should be applied?
113     $is_binary = 0;
114 
115     while (read(FILE, $data, 65536) > 0) {
116         if ($data =~ /\0/) {
117             $is_binary = 1;
118             last;
119         }
120     }
121 
122     if ($is_binary) {
123         print STDERR "$name: $f: binary file\n";
124         next;
125     }
126 
127     seek(FILE, 0, 0);
128 
129     $in_bytes = 0;
130     $out_bytes = 0;
131     $lineno = 0;
132 
133     @lines  = ();
134 
135     $in_hunk = 0;
136     $err = 0;
137 
138     while ( defined($line = <FILE>) ) {
139         $lineno++;
140         $in_bytes += length($line);
141 
142         if (!$in_hunk) {
143             if ($line =~
144                 /^\@\@\s+\-([0-9]+),([0-9]+)\s+\+([0-9]+),([0-9]+)\s\@\@/) {
145                 $minus_lines = $2;
146                 $plus_lines = $4;
147                 if ($minus_lines || $plus_lines) {
148                     $in_hunk = 1;
149                     @hunk_lines = ($line);
150                 }
151             } else {
152                 push(@lines, $line);
153                 $out_bytes += length($line);
154             }
155         } else {
156             # We're in a hunk
157 
158             if ($line =~ /^\+/) {
159                 $plus_lines--;
160 
161                 $text = substr($line, 1);
162                 $text =~ s/[ \t\r]*$//;         # Remove trailing spaces
163                 $text = clean_space_tabs($text);
164 
165                 $l_width = strwidth($text);
166                 if ($max_width && $l_width > $max_width) {
167                     print STDERR
168                         "$f:$lineno: adds line exceeds $max_width ",
169                         "characters ($l_width)\n";
170                 }
171 
172                 push(@hunk_lines, '+'.$text);
173             } elsif ($line =~ /^\-/) {
174                 $minus_lines--;
175                 push(@hunk_lines, $line);
176             } elsif ($line =~ /^ /) {
177                 $plus_lines--;
178                 $minus_lines--;
179                 push(@hunk_lines, $line);
180             } else {
181                 print STDERR "$name: $f: malformed patch\n";
182                 $err = 1;
183                 last;
184             }
185 
186             if ($plus_lines < 0 || $minus_lines < 0) {
187                 print STDERR "$name: $f: malformed patch\n";
188                 $err = 1;
189                 last;
190             } elsif ($plus_lines == 0 && $minus_lines == 0) {
191                 # End of a hunk.  Process this hunk.
192                 my $i;
193                 my $l;
194                 my @h = ();
195                 my $adj = 0;
196                 my $done = 0;
197 
198                 for ($i = scalar(@hunk_lines)-1; $i > 0; $i--) {
199                     $l = $hunk_lines[$i];
200                     if (!$done && $l eq "+\n") {
201                         $adj++; # Skip this line
202                     } elsif ($l =~ /^[ +]/) {
203                         $done = 1;
204                         unshift(@h, $l);
205                     } else {
206                         unshift(@h, $l);
207                     }
208                 }
209 
210                 $l = $hunk_lines[0];  # Hunk header
211                 undef @hunk_lines;    # Free memory
212 
213                 if ($adj) {
214                     die unless
215                         ($l =~ /^\@\@\s+\-([0-9]+),([0-9]+)\s+\+([0-9]+),([0-9]+)\s\@\@(.*)$/);
216                     my $mstart = $1;
217                     my $mlin = $2;
218                     my $pstart = $3;
219                     my $plin = $4;
220                     my $tail = $5; # doesn't include the final newline
221 
222                     $l = sprintf("@@ -%d,%d +%d,%d @@%s\n",
223                                  $mstart, $mlin, $pstart, $plin-$adj,
224                                  $tail);
225                 }
226                 unshift(@h, $l);
227 
228                 # Transfer to the output array
229                 foreach $l (@h) {
230                     $out_bytes += length($l);
231                     push(@lines, $l);
232                 }
233 
234                 $in_hunk = 0;
235             }
236         }
237     }
238 
239     if ($in_hunk) {
240         print STDERR "$name: $f: malformed patch\n";
241         $err = 1;
242     }
243 
244     if (!$err) {
245         if ($in_bytes != $out_bytes) {
246             # Only write to the file if changed
247             seek(FILE, 0, 0);
248             print FILE @lines;
249 
250             if ( !defined($where = tell(FILE)) ||
251                  !truncate(FILE, $where) ) {
252                 die "$name: Failed to truncate modified file: $f: $!\n";
253             }
254         }
255     }
256 
257     close(FILE);
258 }

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us