Skip to content

Commit a45228d

Browse files
committed
Add script to unroll C++11 range based for loops
1 parent 531a5c0 commit a45228d

File tree

2 files changed

+105
-0
lines changed

2 files changed

+105
-0
lines changed

script/replace-range-for-loops.md

+48
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
## Unroll C++11 range-based for loops for GCC 4.4 compatibility
2+
3+
By [Marcel Greter](@mgreter)
4+
5+
LibSass needs a pretty recent compiler in order to support
6+
C++11. We only use a small subset of C++11 features, so most
7+
of our code is still compatible with C++98. GCC added more
8+
C++ features over time, so chances are that even versions that
9+
do not have full C++11 support can compile LibSass (--gnu++11)
10+
11+
https://github.com/sass/libsass/pull/1623
12+
13+
I created a few small patches to make our use of the random number
14+
generator compatible with older GCC versions. The only thing left
15+
is our use of range-based for loops, which is not available on
16+
GCC 4.4. Since I like that syntax very much, I decided to keep it
17+
in the source and use a script to automatically unroll them.
18+
19+
`cd script && perl replace-range-for-loops.pl && cd ..`
20+
21+
### Verifying the resulting code base
22+
23+
I've come up with the following recipe to verify compilation:
24+
25+
```cmd
26+
mkdir libsass-gcc-4.4
27+
cd libsass-gcc-4.4
28+
wget -c http://strawberryperl.com/download/5.12.3.0/strawberry-perl-5.12.3.0-portable.zip
29+
mkdir perl
30+
cd perl
31+
unzip ..\strawberry-perl-5.12.3.0-portable.zip
32+
portableshell.bat
33+
34+
git clone https://github.com/sass/perl-libsass.git
35+
cd perl-libsass
36+
git submodule update --init
37+
cd libsass
38+
git remote add mgreter https://github.com/mgreter/libsass.git
39+
git fetch mgreter
40+
git checkout -b compat/gcc-4.4 mgreter/compat/gcc-4.4
41+
perl script\replace-range-for-loops.pl
42+
cd ..
43+
cpan ExtUtils::CppGuess
44+
cpan Test::Differences
45+
cpan Encode::Locale
46+
gcc -v
47+
cpan .
48+
```

script/replace-range-for-loops.pl

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# this script may be used to replace `for(auto : xyz)` loops
2+
# with a more std compliant form that also compiles on gcc 4.4
3+
# albeit completely unsupported by libsass, you may use it
4+
# if there is no way to upgrade your local compiler. Mileage
5+
# may vary, and I want to stress again that this is unsupported.
6+
7+
use strict;
8+
use warnings;
9+
10+
use File::Slurp;
11+
use File::Basename;
12+
use File::Spec::Functions;
13+
14+
warn "YOU ARE ENTERING UNSUPPORTED LAND !!!!\n";
15+
warn "DON'T POST BUGS WHEN USING GCC 4.4 !!!!\n";
16+
17+
my $root = $ENV{'SASS_LIBSASS_PATH'} || catfile(dirname($0), '..');
18+
19+
sub process($)
20+
{
21+
22+
my $count = 0;
23+
my ($file) = @_;
24+
25+
my $cpp = read_file($file, { binmode => ':raw' });
26+
27+
my $org = $cpp;
28+
29+
my $re_decl = qr/(?:const\s*)?\w+(?:\:\:\w+)*(?:\s*[\*\&])?/;
30+
my $re_val = qr/\w+(?:\(\))?(?:(?:->|\.)\w+(?:\(\))?)*/;
31+
32+
$cpp =~ s/for\s*\(\s*($re_decl)\s*(\w+)\s*:\s*(\(\*?$re_val\)|\*?$re_val)\s*\)\s*{/
33+
$count ++;
34+
"for (auto __$2 = ($3).begin(); __$2 != ($3).end(); ++__$2) { $1 $2 = *(__$2);";
35+
/gex;
36+
37+
return if $org eq $cpp || $count == 0;
38+
39+
warn sprintf "made %02d replacements in %s\n", $count, $file;
40+
41+
write_file($file, { binmode => ':raw' }, $cpp);
42+
43+
}
44+
45+
sub processdir($)
46+
{
47+
my $rv = opendir(my $dh, $_[0]);
48+
die "not found ", $_[0] unless $rv;
49+
while (my $entry = readdir($dh)) {
50+
next if $entry eq "." || $entry eq "..";
51+
next unless $entry =~ m/\.[hc]pp$/;
52+
if (-d $_[0]) { process(catfile($_[0], $entry)); }
53+
elsif (-f $_[0]) { process(catfile($_[0], $entry)); }
54+
}
55+
}
56+
57+
processdir catfile($root, "src");

0 commit comments

Comments
 (0)