r5170 | ntrel | 2010-08-16 17:54:59 +0100 (Mon, 16 Aug 2010) | 2 lines
[geany-mirror.git] / scripts / fix-alignment.pl
blob584ecb98048ee85fd063f4d0f9c3e62dc0331d75
1 #!/usr/bin/env perl
2 # Copyright: 2009-2010, Nick Treleaven
3 # License: GNU GPL V2 or later, as published by the Free Software Foundation, USA.
4 # Warranty: NONE
6 # Re-align C source code for Geany.
7 # Doesn't handle indents/blank lines/anything complicated ;-)
9 use strict;
10 use warnings;
12 use Getopt::Std;
14 my %args = ();
15 getopts('w', \%args);
16 my $opt_write = $args{'w'};
18 my $argc = $#ARGV + 1;
19 my $scriptname = $0;
21 (($argc == 1) or ($argc >= 1 and $opt_write)) or die <<END;
22 Usage:
23 $scriptname sourcefile [>outfile]
24 Print formatted output to STDOUT or outfile.
25 Warning: do not use the same file for outfile.
27 $scriptname -w sourcefile(s)
28 Writes to the file(s) in-place.
29 Warning: backup your file(s) first or use clean version control files.
30 END
33 sub parse($)
35 my ($infile) = @_;
36 my @lines;
38 open(INPUT, $infile) or die "Couldn't open $infile for reading: $!\n";
40 while (<INPUT>) {
41 my $line = $_; # read a line, including \n char
43 # strip trailing space & newline
44 $line =~ s/\s+$//g;
46 # for now, don't process lines with comments, strings, preproc non-defines, overflowed lines or chars
47 # multi-line comment internal lines are skipped only if they start with '* '.
48 if (!($line =~ m,/\*|\*/|//|"|\\$|',) and !($line =~ m/^\s*(\*\s|#[^d])/)) {
49 # make binary operators have *one* space each side
50 # operators must have longer variants first otherwise trailing operators can be broken e.g. "+ ="
51 # '*' ignored as could be pointer
52 my $ops = '<<=,<<,>>=,>>,<=,>=,<,>,||,|=,|,&&,&=,-=,+=,+,*=,/=,/,==,!=,%=,%,^=,^,=';
53 $ops =~ s/([|*+])/\\$1/g; # escape regex chars
54 $ops =~ s/,/|/g;
55 $line =~ s/([\w)\]]) ?($ops) ?([\w(]|$)/$1 $2 $3/g;
57 # space binary operators that can conflict with unaries with cast and/or 'return -1/&foo'
58 # '-' could be unary "(gint)-j"
59 # '&' could be address-of "(type*)&foo"
60 $line =~ s/([\w\]])(-|&) ?([\w(]|$)/$1 $2 $3/g;
62 # space ternary conditional operator
63 $line =~ s/ ?\? ?(.+?) ?: ?/ ? $1 : /g;
65 # space comma operator (allowing for possible alignment space afterwards)
66 $line =~ s/ ?,(\S)/, $1/g;
68 # space after statements
69 my $statements = 'for|if|while|switch';
70 $line =~ s/\b($statements)\b\s*/$1 /g;
72 # no space on inside of brackets
73 $line =~ s/\(\s+/(/g;
74 $line =~ s/(\S)\s+\)/$1)/g;
76 # enforce 'fn(void);' in prototypes
77 $line =~ s/^(\w.+\w\()\);$/$1void);/;
79 # strip trailing space again (e.g. a trailing operator now has space afterwards)
80 $line =~ s/\s+$//g;
82 push(@lines, $line);
84 close(INPUT);
86 my $text = join("\n", @lines);
87 undef @lines; # free memory
88 $text .= "\n";
90 # 1+ newline -> 2 newlines after function
91 $text =~ s/^}\n\n+([^\n])/}\n\n\n$1/gm;
93 if (!$opt_write) {
94 print $text;
96 else {
97 open(OUTPUT, ">$infile") or die "Couldn't open $infile for writing: $!\n";
98 print OUTPUT $text;
99 close(OUTPUT);
104 foreach my $infile (@ARGV)
106 parse($infile);