Skip to content

Commit

Permalink
Add script to unroll C++11 range based for loops
Browse files Browse the repository at this point in the history
  • Loading branch information
mgreter committed Oct 15, 2017
1 parent 531a5c0 commit a45228d
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 0 deletions.
48 changes: 48 additions & 0 deletions script/replace-range-for-loops.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
## Unroll C++11 range-based for loops for GCC 4.4 compatibility

By [Marcel Greter](@mgreter)

LibSass needs a pretty recent compiler in order to support
C++11. We only use a small subset of C++11 features, so most
of our code is still compatible with C++98. GCC added more
C++ features over time, so chances are that even versions that
do not have full C++11 support can compile LibSass (--gnu++11)

https://github.com/sass/libsass/pull/1623

I created a few small patches to make our use of the random number
generator compatible with older GCC versions. The only thing left
is our use of range-based for loops, which is not available on
GCC 4.4. Since I like that syntax very much, I decided to keep it
in the source and use a script to automatically unroll them.

`cd script && perl replace-range-for-loops.pl && cd ..`

### Verifying the resulting code base

I've come up with the following recipe to verify compilation:

```cmd
mkdir libsass-gcc-4.4
cd libsass-gcc-4.4
wget -c http://strawberryperl.com/download/5.12.3.0/strawberry-perl-5.12.3.0-portable.zip
mkdir perl
cd perl
unzip ..\strawberry-perl-5.12.3.0-portable.zip
portableshell.bat
git clone https://github.com/sass/perl-libsass.git
cd perl-libsass
git submodule update --init
cd libsass
git remote add mgreter https://github.com/mgreter/libsass.git
git fetch mgreter
git checkout -b compat/gcc-4.4 mgreter/compat/gcc-4.4
perl script\replace-range-for-loops.pl
cd ..
cpan ExtUtils::CppGuess
cpan Test::Differences
cpan Encode::Locale
gcc -v
cpan .
```
57 changes: 57 additions & 0 deletions script/replace-range-for-loops.pl
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# this script may be used to replace `for(auto : xyz)` loops
# with a more std compliant form that also compiles on gcc 4.4
# albeit completely unsupported by libsass, you may use it
# if there is no way to upgrade your local compiler. Mileage
# may vary, and I want to stress again that this is unsupported.

use strict;
use warnings;

use File::Slurp;
use File::Basename;
use File::Spec::Functions;

warn "YOU ARE ENTERING UNSUPPORTED LAND !!!!\n";
warn "DON'T POST BUGS WHEN USING GCC 4.4 !!!!\n";

my $root = $ENV{'SASS_LIBSASS_PATH'} || catfile(dirname($0), '..');

sub process($)
{

my $count = 0;
my ($file) = @_;

my $cpp = read_file($file, { binmode => ':raw' });

my $org = $cpp;

my $re_decl = qr/(?:const\s*)?\w+(?:\:\:\w+)*(?:\s*[\*\&])?/;
my $re_val = qr/\w+(?:\(\))?(?:(?:->|\.)\w+(?:\(\))?)*/;

$cpp =~ s/for\s*\(\s*($re_decl)\s*(\w+)\s*:\s*(\(\*?$re_val\)|\*?$re_val)\s*\)\s*{/
$count ++;
"for (auto __$2 = ($3).begin(); __$2 != ($3).end(); ++__$2) { $1 $2 = *(__$2);";
/gex;

return if $org eq $cpp || $count == 0;

warn sprintf "made %02d replacements in %s\n", $count, $file;

write_file($file, { binmode => ':raw' }, $cpp);

}

sub processdir($)
{
my $rv = opendir(my $dh, $_[0]);
die "not found ", $_[0] unless $rv;
while (my $entry = readdir($dh)) {
next if $entry eq "." || $entry eq "..";
next unless $entry =~ m/\.[hc]pp$/;
if (-d $_[0]) { process(catfile($_[0], $entry)); }
elsif (-f $_[0]) { process(catfile($_[0], $entry)); }
}
}

processdir catfile($root, "src");

0 comments on commit a45228d

Please sign in to comment.