1313#include " utf8_string.hpp"
1414#include " utf8.h"
1515
16- #include < atomic>
1716#include < cstdlib>
17+ #include < climits>
1818#include < cmath>
1919#include < cctype>
2020#include < sstream>
2929#include " wincrypt.h"
3030#endif
3131
32+ #if defined __GNUC__ && ! defined __llvm__
33+ #define GCC_VERSION (__GNUC__ * 10000 \
34+ + __GNUC_MINOR__ * 100 \
35+ + __GNUC_PATCHLEVEL__)
36+ #if GCC_VERSION < 40500
37+ #include < tr1/random>
38+ #define IMPLEMENT_TR1
39+ #define tr1ns std::tr1
40+ #define uniform_real_distribution uniform_real
41+ #else
42+ #include < random>
43+ #define tr1ns std
44+ #endif
45+ #else
46+ #include < random>
47+ #define tr1ns std
48+ #endif
49+
3250#define ARG (argname, argtype ) get_arg<argtype>(argname, env, sig, pstate, backtrace)
3351#define ARGR (argname, argtype, lo, hi ) get_arg_r(argname, env, sig, pstate, lo, hi, backtrace)
3452#define ARGM (argname, argtype, ctx ) get_arg_m(argname, env, sig, pstate, backtrace, ctx)
@@ -211,7 +229,7 @@ namespace Sass {
211229 return seed;
212230 }
213231 #else
214- static std ::random_device rd;
232+ static tr1ns ::random_device rd;
215233 uint64_t GetSeed ()
216234 {
217235 return rd ();
@@ -222,9 +240,42 @@ namespace Sass {
222240 // random_device degrades sharply once the entropy pool
223241 // is exhausted. For practical use, random_device is
224242 // generally only used to seed a PRNG such as mt19937.
225- static std::mt19937 rand (static_cast <unsigned int >(GetSeed()));
243+ static tr1ns::mt19937 rand (static_cast <unsigned int >(GetSeed()));
244+
245+ tr1ns::uniform_real_distribution<> std_dist (0 , 1 );
246+ #ifdef IMPLEMENT_TR1
247+ tr1ns::variate_generator <
248+ tr1ns::mt19937,
249+ tr1ns::uniform_real_distribution <double >
250+ > gen_std_dist (rand, std_dist);
251+ #endif
252+
253+ tr1ns::uniform_real_distribution<> full_dist (0 , ULONG_MAX);
254+ #ifdef IMPLEMENT_TR1
255+ tr1ns::variate_generator <
256+ tr1ns::mt19937,
257+ tr1ns::uniform_real_distribution <double >
258+ > gen_full_dist (rand, full_dist);
259+ #endif
226260
227- // features
261+ // helper function to retrieve a random number in interval
262+ // works around some compiler issues with older gcc versions
263+ static double random (double min, double max)
264+ {
265+ tr1ns::uniform_real_distribution<> distributor (min, max);
266+ #ifdef IMPLEMENT_TR1
267+ tr1ns::variate_generator <
268+ tr1ns::mt19937,
269+ tr1ns::uniform_real_distribution <>
270+ > gen (rand, distributor);
271+ distributor (rand);
272+ return gen ();
273+ #else
274+ return distributor (rand);
275+ #endif
276+ }
277+
278+ // supported features lookup table
228279 static std::set<std::string> features {
229280 " global-variable-shadowing" ,
230281 " extend-selector-pseudoclass" ,
@@ -1170,13 +1221,15 @@ namespace Sass {
11701221 err << " Expected $limit to be an integer but got `" << v << " ` for `random`" ;
11711222 error (err.str (), pstate);
11721223 }
1173- std::uniform_real_distribution<> distributor (1 , v + 1 );
1174- uint_fast32_t distributed = static_cast <uint_fast32_t >(distributor (rand));
1175- return SASS_MEMORY_NEW (ctx.mem , Number, pstate, (double )distributed);
1224+ uint_fast32_t distributed = random (1 , v + 1 );
1225+ return SASS_MEMORY_NEW (ctx.mem , Number, pstate, distributed);
11761226 }
11771227 else {
1178- std::uniform_real_distribution<> distributor (0 , 1 );
1179- double distributed = static_cast <double >(distributor (rand));
1228+ #ifdef IMPLEMENT_TR1
1229+ double distributed = gen_std_dist ();
1230+ #else
1231+ double distributed = std_dist (rand);
1232+ #endif
11801233 return SASS_MEMORY_NEW (ctx.mem , Number, pstate, distributed);
11811234 }
11821235 }
@@ -1906,8 +1959,11 @@ namespace Sass {
19061959 BUILT_IN (unique_id)
19071960 {
19081961 std::stringstream ss;
1909- std::uniform_real_distribution<> distributor (0 , 4294967296 ); // 16^8
1910- uint_fast32_t distributed = static_cast <uint_fast32_t >(distributor (rand));
1962+ #ifdef IMPLEMENT_TR1
1963+ uint_fast32_t distributed = gen_full_dist ();
1964+ #else
1965+ uint_fast32_t distributed = full_dist (rand);
1966+ #endif
19111967 ss << " u" << std::setfill (' 0' ) << std::setw (8 ) << std::hex << distributed;
19121968 return SASS_MEMORY_NEW (ctx.mem , String_Quoted, pstate, ss.str ());
19131969 }
0 commit comments