From ccc3d135322993391bfb659eabf2a25cee62f74d Mon Sep 17 00:00:00 2001
From: Marcel Greter <marcel.greter@ocbnet.ch>
Date: Mon, 9 Jan 2017 17:51:08 +0100
Subject: [PATCH 01/12] Add script to unroll C++11 range based for loops

---
 script/replace-range-for-loops.md | 48 ++++++++++++++++++++++++++
 script/replace-range-for-loops.pl | 57 +++++++++++++++++++++++++++++++
 2 files changed, 105 insertions(+)
 create mode 100644 script/replace-range-for-loops.md
 create mode 100644 script/replace-range-for-loops.pl

diff --git a/script/replace-range-for-loops.md b/script/replace-range-for-loops.md
new file mode 100644
index 00000000..66101656
--- /dev/null
+++ b/script/replace-range-for-loops.md
@@ -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 .
+```
diff --git a/script/replace-range-for-loops.pl b/script/replace-range-for-loops.pl
new file mode 100644
index 00000000..07f47024
--- /dev/null
+++ b/script/replace-range-for-loops.pl
@@ -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");
-- 
2.21.0.windows.1