sassc 2.0.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.gitmodules +1 -1
  4. data/.travis.yml +9 -3
  5. data/CHANGELOG.md +36 -0
  6. data/CODE_OF_CONDUCT.md +1 -1
  7. data/README.md +1 -1
  8. data/Rakefile +43 -7
  9. data/ext/depend +4 -0
  10. data/ext/extconf.rb +92 -0
  11. data/ext/libsass/VERSION +1 -0
  12. data/ext/libsass/include/sass/base.h +9 -1
  13. data/ext/libsass/include/sass/context.h +5 -1
  14. data/ext/libsass/src/MurmurHash2.hpp +91 -0
  15. data/ext/libsass/src/ast.cpp +755 -2028
  16. data/ext/libsass/src/ast.hpp +492 -2477
  17. data/ext/libsass/src/{to_c.cpp → ast2c.cpp} +22 -16
  18. data/ext/libsass/src/ast2c.hpp +39 -0
  19. data/ext/libsass/src/ast_def_macros.hpp +70 -10
  20. data/ext/libsass/src/ast_fwd_decl.cpp +5 -3
  21. data/ext/libsass/src/ast_fwd_decl.hpp +107 -296
  22. data/ext/libsass/src/ast_helpers.hpp +292 -0
  23. data/ext/libsass/src/ast_sel_cmp.cpp +396 -0
  24. data/ext/libsass/src/ast_sel_super.cpp +539 -0
  25. data/ext/libsass/src/ast_sel_unify.cpp +275 -0
  26. data/ext/libsass/src/ast_sel_weave.cpp +616 -0
  27. data/ext/libsass/src/ast_selectors.cpp +1043 -0
  28. data/ext/libsass/src/ast_selectors.hpp +522 -0
  29. data/ext/libsass/src/ast_supports.cpp +114 -0
  30. data/ext/libsass/src/ast_supports.hpp +121 -0
  31. data/ext/libsass/src/ast_values.cpp +1154 -0
  32. data/ext/libsass/src/ast_values.hpp +498 -0
  33. data/ext/libsass/src/backtrace.cpp +11 -7
  34. data/ext/libsass/src/backtrace.hpp +5 -5
  35. data/ext/libsass/src/base64vlq.cpp +5 -2
  36. data/ext/libsass/src/base64vlq.hpp +1 -1
  37. data/ext/libsass/src/bind.cpp +35 -34
  38. data/ext/libsass/src/bind.hpp +3 -1
  39. data/ext/libsass/src/c2ast.cpp +64 -0
  40. data/ext/libsass/src/c2ast.hpp +14 -0
  41. data/ext/libsass/src/cencode.c +4 -6
  42. data/ext/libsass/src/check_nesting.cpp +83 -88
  43. data/ext/libsass/src/check_nesting.hpp +39 -34
  44. data/ext/libsass/src/color_maps.cpp +168 -164
  45. data/ext/libsass/src/color_maps.hpp +152 -160
  46. data/ext/libsass/src/constants.cpp +20 -0
  47. data/ext/libsass/src/constants.hpp +19 -0
  48. data/ext/libsass/src/context.cpp +104 -121
  49. data/ext/libsass/src/context.hpp +43 -55
  50. data/ext/libsass/src/cssize.cpp +103 -188
  51. data/ext/libsass/src/cssize.hpp +45 -51
  52. data/ext/libsass/src/dart_helpers.hpp +199 -0
  53. data/ext/libsass/src/debugger.hpp +524 -361
  54. data/ext/libsass/src/emitter.cpp +26 -26
  55. data/ext/libsass/src/emitter.hpp +20 -18
  56. data/ext/libsass/src/environment.cpp +41 -27
  57. data/ext/libsass/src/environment.hpp +33 -22
  58. data/ext/libsass/src/error_handling.cpp +92 -94
  59. data/ext/libsass/src/error_handling.hpp +73 -50
  60. data/ext/libsass/src/eval.cpp +380 -515
  61. data/ext/libsass/src/eval.hpp +64 -57
  62. data/ext/libsass/src/eval_selectors.cpp +75 -0
  63. data/ext/libsass/src/expand.cpp +322 -263
  64. data/ext/libsass/src/expand.hpp +55 -39
  65. data/ext/libsass/src/extender.cpp +1188 -0
  66. data/ext/libsass/src/extender.hpp +399 -0
  67. data/ext/libsass/src/extension.cpp +43 -0
  68. data/ext/libsass/src/extension.hpp +89 -0
  69. data/ext/libsass/src/file.cpp +134 -88
  70. data/ext/libsass/src/file.hpp +28 -37
  71. data/ext/libsass/src/fn_colors.cpp +596 -0
  72. data/ext/libsass/src/fn_colors.hpp +85 -0
  73. data/ext/libsass/src/fn_lists.cpp +285 -0
  74. data/ext/libsass/src/fn_lists.hpp +34 -0
  75. data/ext/libsass/src/fn_maps.cpp +94 -0
  76. data/ext/libsass/src/fn_maps.hpp +30 -0
  77. data/ext/libsass/src/fn_miscs.cpp +244 -0
  78. data/ext/libsass/src/fn_miscs.hpp +40 -0
  79. data/ext/libsass/src/fn_numbers.cpp +227 -0
  80. data/ext/libsass/src/fn_numbers.hpp +45 -0
  81. data/ext/libsass/src/fn_selectors.cpp +205 -0
  82. data/ext/libsass/src/fn_selectors.hpp +35 -0
  83. data/ext/libsass/src/fn_strings.cpp +268 -0
  84. data/ext/libsass/src/fn_strings.hpp +34 -0
  85. data/ext/libsass/src/fn_utils.cpp +158 -0
  86. data/ext/libsass/src/fn_utils.hpp +62 -0
  87. data/ext/libsass/src/inspect.cpp +253 -266
  88. data/ext/libsass/src/inspect.hpp +72 -74
  89. data/ext/libsass/src/json.cpp +2 -2
  90. data/ext/libsass/src/lexer.cpp +25 -84
  91. data/ext/libsass/src/lexer.hpp +5 -16
  92. data/ext/libsass/src/listize.cpp +27 -43
  93. data/ext/libsass/src/listize.hpp +14 -11
  94. data/ext/libsass/src/mapping.hpp +1 -0
  95. data/ext/libsass/src/memory.hpp +12 -0
  96. data/ext/libsass/src/memory/allocator.cpp +48 -0
  97. data/ext/libsass/src/memory/allocator.hpp +138 -0
  98. data/ext/libsass/src/memory/config.hpp +20 -0
  99. data/ext/libsass/src/memory/memory_pool.hpp +186 -0
  100. data/ext/libsass/src/memory/shared_ptr.cpp +33 -0
  101. data/ext/libsass/src/memory/shared_ptr.hpp +332 -0
  102. data/ext/libsass/src/operation.hpp +193 -143
  103. data/ext/libsass/src/operators.cpp +56 -29
  104. data/ext/libsass/src/operators.hpp +11 -11
  105. data/ext/libsass/src/ordered_map.hpp +112 -0
  106. data/ext/libsass/src/output.cpp +59 -75
  107. data/ext/libsass/src/output.hpp +15 -22
  108. data/ext/libsass/src/parser.cpp +662 -818
  109. data/ext/libsass/src/parser.hpp +96 -100
  110. data/ext/libsass/src/parser_selectors.cpp +189 -0
  111. data/ext/libsass/src/permutate.hpp +164 -0
  112. data/ext/libsass/src/plugins.cpp +12 -8
  113. data/ext/libsass/src/plugins.hpp +8 -8
  114. data/ext/libsass/src/position.cpp +10 -26
  115. data/ext/libsass/src/position.hpp +44 -21
  116. data/ext/libsass/src/prelexer.cpp +14 -8
  117. data/ext/libsass/src/prelexer.hpp +9 -9
  118. data/ext/libsass/src/remove_placeholders.cpp +59 -57
  119. data/ext/libsass/src/remove_placeholders.hpp +20 -18
  120. data/ext/libsass/src/sass.cpp +25 -18
  121. data/ext/libsass/src/sass.hpp +22 -14
  122. data/ext/libsass/src/sass2scss.cpp +49 -18
  123. data/ext/libsass/src/sass_context.cpp +104 -132
  124. data/ext/libsass/src/sass_context.hpp +2 -2
  125. data/ext/libsass/src/sass_functions.cpp +7 -4
  126. data/ext/libsass/src/sass_functions.hpp +1 -1
  127. data/ext/libsass/src/sass_values.cpp +26 -21
  128. data/ext/libsass/src/settings.hpp +19 -0
  129. data/ext/libsass/src/source.cpp +69 -0
  130. data/ext/libsass/src/source.hpp +95 -0
  131. data/ext/libsass/src/source_data.hpp +32 -0
  132. data/ext/libsass/src/source_map.cpp +27 -20
  133. data/ext/libsass/src/source_map.hpp +14 -11
  134. data/ext/libsass/src/stylesheet.cpp +22 -0
  135. data/ext/libsass/src/stylesheet.hpp +57 -0
  136. data/ext/libsass/src/to_value.cpp +24 -22
  137. data/ext/libsass/src/to_value.hpp +18 -22
  138. data/ext/libsass/src/units.cpp +28 -22
  139. data/ext/libsass/src/units.hpp +9 -8
  140. data/ext/libsass/src/utf8/checked.h +12 -10
  141. data/ext/libsass/src/utf8/core.h +3 -0
  142. data/ext/libsass/src/utf8_string.cpp +12 -10
  143. data/ext/libsass/src/utf8_string.hpp +7 -6
  144. data/ext/libsass/src/util.cpp +97 -107
  145. data/ext/libsass/src/util.hpp +74 -30
  146. data/ext/libsass/src/util_string.cpp +125 -0
  147. data/ext/libsass/src/util_string.hpp +73 -0
  148. data/ext/libsass/src/values.cpp +33 -24
  149. data/ext/libsass/src/values.hpp +2 -2
  150. data/lib/sassc.rb +24 -0
  151. data/lib/sassc/engine.rb +7 -5
  152. data/lib/sassc/functions_handler.rb +11 -13
  153. data/lib/sassc/native.rb +10 -9
  154. data/lib/sassc/native/native_functions_api.rb +0 -5
  155. data/lib/sassc/script.rb +4 -6
  156. data/lib/sassc/version.rb +1 -1
  157. data/sassc.gemspec +32 -12
  158. data/test/engine_test.rb +32 -2
  159. data/test/functions_test.rb +38 -1
  160. data/test/native_test.rb +4 -4
  161. metadata +95 -109
  162. data/ext/Rakefile +0 -3
  163. data/ext/libsass/.editorconfig +0 -15
  164. data/ext/libsass/.gitattributes +0 -2
  165. data/ext/libsass/.github/CONTRIBUTING.md +0 -65
  166. data/ext/libsass/.github/ISSUE_TEMPLATE.md +0 -54
  167. data/ext/libsass/.gitignore +0 -85
  168. data/ext/libsass/.travis.yml +0 -64
  169. data/ext/libsass/COPYING +0 -25
  170. data/ext/libsass/GNUmakefile.am +0 -88
  171. data/ext/libsass/INSTALL +0 -1
  172. data/ext/libsass/LICENSE +0 -25
  173. data/ext/libsass/Makefile +0 -351
  174. data/ext/libsass/Makefile.conf +0 -55
  175. data/ext/libsass/Readme.md +0 -104
  176. data/ext/libsass/SECURITY.md +0 -10
  177. data/ext/libsass/appveyor.yml +0 -91
  178. data/ext/libsass/configure.ac +0 -138
  179. data/ext/libsass/contrib/libsass.spec +0 -66
  180. data/ext/libsass/docs/README.md +0 -20
  181. data/ext/libsass/docs/api-context-example.md +0 -45
  182. data/ext/libsass/docs/api-context-internal.md +0 -163
  183. data/ext/libsass/docs/api-context.md +0 -295
  184. data/ext/libsass/docs/api-doc.md +0 -215
  185. data/ext/libsass/docs/api-function-example.md +0 -67
  186. data/ext/libsass/docs/api-function-internal.md +0 -8
  187. data/ext/libsass/docs/api-function.md +0 -74
  188. data/ext/libsass/docs/api-importer-example.md +0 -112
  189. data/ext/libsass/docs/api-importer-internal.md +0 -20
  190. data/ext/libsass/docs/api-importer.md +0 -86
  191. data/ext/libsass/docs/api-value-example.md +0 -55
  192. data/ext/libsass/docs/api-value-internal.md +0 -76
  193. data/ext/libsass/docs/api-value.md +0 -154
  194. data/ext/libsass/docs/build-on-darwin.md +0 -27
  195. data/ext/libsass/docs/build-on-gentoo.md +0 -55
  196. data/ext/libsass/docs/build-on-windows.md +0 -139
  197. data/ext/libsass/docs/build-shared-library.md +0 -35
  198. data/ext/libsass/docs/build-with-autotools.md +0 -78
  199. data/ext/libsass/docs/build-with-makefiles.md +0 -68
  200. data/ext/libsass/docs/build-with-mingw.md +0 -107
  201. data/ext/libsass/docs/build-with-visual-studio.md +0 -90
  202. data/ext/libsass/docs/build.md +0 -97
  203. data/ext/libsass/docs/compatibility-plan.md +0 -48
  204. data/ext/libsass/docs/contributing.md +0 -17
  205. data/ext/libsass/docs/custom-functions-internal.md +0 -122
  206. data/ext/libsass/docs/dev-ast-memory.md +0 -223
  207. data/ext/libsass/docs/implementations.md +0 -56
  208. data/ext/libsass/docs/plugins.md +0 -47
  209. data/ext/libsass/docs/setup-environment.md +0 -68
  210. data/ext/libsass/docs/source-map-internals.md +0 -51
  211. data/ext/libsass/docs/trace.md +0 -26
  212. data/ext/libsass/docs/triage.md +0 -17
  213. data/ext/libsass/docs/unicode.md +0 -39
  214. data/ext/libsass/extconf.rb +0 -6
  215. data/ext/libsass/include/sass/version.h.in +0 -12
  216. data/ext/libsass/m4/.gitkeep +0 -0
  217. data/ext/libsass/m4/m4-ax_cxx_compile_stdcxx_11.m4 +0 -167
  218. data/ext/libsass/res/resource.rc +0 -35
  219. data/ext/libsass/script/bootstrap +0 -13
  220. data/ext/libsass/script/branding +0 -10
  221. data/ext/libsass/script/ci-build-libsass +0 -134
  222. data/ext/libsass/script/ci-build-plugin +0 -62
  223. data/ext/libsass/script/ci-install-compiler +0 -6
  224. data/ext/libsass/script/ci-install-deps +0 -20
  225. data/ext/libsass/script/ci-report-coverage +0 -42
  226. data/ext/libsass/script/spec +0 -5
  227. data/ext/libsass/script/tap-driver +0 -652
  228. data/ext/libsass/script/tap-runner +0 -1
  229. data/ext/libsass/script/test-leaks.pl +0 -103
  230. data/ext/libsass/src/GNUmakefile.am +0 -54
  231. data/ext/libsass/src/extend.cpp +0 -2130
  232. data/ext/libsass/src/extend.hpp +0 -86
  233. data/ext/libsass/src/functions.cpp +0 -2234
  234. data/ext/libsass/src/functions.hpp +0 -198
  235. data/ext/libsass/src/memory/SharedPtr.cpp +0 -114
  236. data/ext/libsass/src/memory/SharedPtr.hpp +0 -206
  237. data/ext/libsass/src/node.cpp +0 -319
  238. data/ext/libsass/src/node.hpp +0 -118
  239. data/ext/libsass/src/paths.hpp +0 -71
  240. data/ext/libsass/src/sass_util.cpp +0 -149
  241. data/ext/libsass/src/sass_util.hpp +0 -256
  242. data/ext/libsass/src/subset_map.cpp +0 -55
  243. data/ext/libsass/src/subset_map.hpp +0 -76
  244. data/ext/libsass/src/support/libsass.pc.in +0 -11
  245. data/ext/libsass/src/to_c.hpp +0 -39
  246. data/ext/libsass/test/test_node.cpp +0 -94
  247. data/ext/libsass/test/test_paths.cpp +0 -28
  248. data/ext/libsass/test/test_selector_difference.cpp +0 -25
  249. data/ext/libsass/test/test_specificity.cpp +0 -25
  250. data/ext/libsass/test/test_subset_map.cpp +0 -472
  251. data/ext/libsass/test/test_superselector.cpp +0 -69
  252. data/ext/libsass/test/test_unification.cpp +0 -31
  253. data/ext/libsass/version.sh +0 -10
  254. data/ext/libsass/win/libsass.sln +0 -39
  255. data/ext/libsass/win/libsass.sln.DotSettings +0 -9
  256. data/ext/libsass/win/libsass.targets +0 -118
  257. data/ext/libsass/win/libsass.vcxproj +0 -188
  258. data/ext/libsass/win/libsass.vcxproj.filters +0 -357
  259. data/lib/sassc/native/lib_c.rb +0 -21
  260. data/lib/tasks/libsass.rb +0 -33
@@ -1,4 +1,7 @@
1
+ // sass.hpp must go before all system headers to get the
2
+ // __EXTENSIONS__ fix on Solaris.
1
3
  #include "sass.hpp"
4
+
2
5
  #ifdef _WIN32
3
6
  # ifdef __MINGW32__
4
7
  # ifndef off64_t
@@ -10,9 +13,7 @@
10
13
  #else
11
14
  # include <unistd.h>
12
15
  #endif
13
- #include <iostream>
14
- #include <fstream>
15
- #include <cctype>
16
+ #include <cstdio>
16
17
  #include <vector>
17
18
  #include <algorithm>
18
19
  #include <sys/stat.h>
@@ -21,6 +22,9 @@
21
22
  #include "prelexer.hpp"
22
23
  #include "utf8_string.hpp"
23
24
  #include "sass_functions.hpp"
25
+ #include "error_handling.hpp"
26
+ #include "util.hpp"
27
+ #include "util_string.hpp"
24
28
  #include "sass2scss.h"
25
29
 
26
30
  #ifdef _WIN32
@@ -28,16 +32,16 @@
28
32
 
29
33
  # ifdef _MSC_VER
30
34
  # include <codecvt>
31
- inline static std::string wstring_to_string(const std::wstring& wstr)
35
+ inline static Sass::sass::string wstring_to_string(const std::wstring& wstr)
32
36
  {
33
37
  std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> wchar_converter;
34
38
  return wchar_converter.to_bytes(wstr);
35
39
  }
36
40
  # else // mingw(/gcc) does not support C++11's codecvt yet.
37
- inline static std::string wstring_to_string(const std::wstring &wstr)
41
+ inline static Sass::sass::string wstring_to_string(const std::wstring &wstr)
38
42
  {
39
43
  int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
40
- std::string strTo(size_needed, 0);
44
+ Sass::sass::string strTo(size_needed, 0);
41
45
  WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
42
46
  return strTo;
43
47
  }
@@ -50,7 +54,7 @@ namespace Sass {
50
54
  // return the current directory
51
55
  // always with forward slashes
52
56
  // always with trailing slash
53
- std::string get_cwd()
57
+ sass::string get_cwd()
54
58
  {
55
59
  const size_t wd_len = 4096;
56
60
  #ifndef _WIN32
@@ -59,12 +63,12 @@ namespace Sass {
59
63
  // we should check error for more detailed info (e.g. ENOENT)
60
64
  // http://man7.org/linux/man-pages/man2/getcwd.2.html#ERRORS
61
65
  if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
62
- std::string cwd = pwd;
66
+ sass::string cwd = pwd;
63
67
  #else
64
68
  wchar_t wd[wd_len];
65
69
  wchar_t* pwd = _wgetcwd(wd, wd_len);
66
70
  if (pwd == NULL) throw Exception::OperationError("cwd gone missing");
67
- std::string cwd = wstring_to_string(pwd);
71
+ sass::string cwd = wstring_to_string(pwd);
68
72
  //convert backslashes to forward slashes
69
73
  replace(cwd.begin(), cwd.end(), '\\', '/');
70
74
  #endif
@@ -73,13 +77,16 @@ namespace Sass {
73
77
  }
74
78
 
75
79
  // test if path exists and is a file
76
- bool file_exists(const std::string& path)
80
+ bool file_exists(const sass::string& path)
77
81
  {
78
82
  #ifdef _WIN32
79
83
  wchar_t resolved[32768];
80
84
  // windows unicode filepaths are encoded in utf16
81
- std::string abspath(join_paths(get_cwd(), path));
82
- std::wstring wpath(UTF_8::convert_to_utf16("\\\\?\\" + abspath));
85
+ sass::string abspath(join_paths(get_cwd(), path));
86
+ if (!(abspath[0] == '/' && abspath[1] == '/')) {
87
+ abspath = "//?/" + abspath;
88
+ }
89
+ std::wstring wpath(UTF_8::convert_to_utf16(abspath));
83
90
  std::replace(wpath.begin(), wpath.end(), '/', '\\');
84
91
  DWORD rv = GetFullPathNameW(wpath.c_str(), 32767, resolved, NULL);
85
92
  if (rv > 32767) throw Exception::OperationError("Path is too long");
@@ -96,35 +103,35 @@ namespace Sass {
96
103
 
97
104
  // return if given path is absolute
98
105
  // works with *nix and windows paths
99
- bool is_absolute_path(const std::string& path)
106
+ bool is_absolute_path(const sass::string& path)
100
107
  {
101
108
  #ifdef _WIN32
102
- if (path.length() >= 2 && isalpha(path[0]) && path[1] == ':') return true;
109
+ if (path.length() >= 2 && Util::ascii_isalpha(path[0]) && path[1] == ':') return true;
103
110
  #endif
104
111
  size_t i = 0;
105
112
  // check if we have a protocol
106
- if (path[i] && Prelexer::is_alpha(path[i])) {
113
+ if (path[i] && Util::ascii_isalpha(static_cast<unsigned char>(path[i]))) {
107
114
  // skip over all alphanumeric characters
108
- while (path[i] && Prelexer::is_alnum(path[i])) ++i;
115
+ while (path[i] && Util::ascii_isalnum(static_cast<unsigned char>(path[i]))) ++i;
109
116
  i = i && path[i] == ':' ? i + 1 : 0;
110
117
  }
111
118
  return path[i] == '/';
112
119
  }
113
120
 
114
- // helper function to find the last directory seperator
115
- inline size_t find_last_folder_separator(const std::string& path, size_t limit = std::string::npos)
121
+ // helper function to find the last directory separator
122
+ inline size_t find_last_folder_separator(const sass::string& path, size_t limit = sass::string::npos)
116
123
  {
117
124
  size_t pos;
118
125
  size_t pos_p = path.find_last_of('/', limit);
119
126
  #ifdef _WIN32
120
127
  size_t pos_w = path.find_last_of('\\', limit);
121
128
  #else
122
- size_t pos_w = std::string::npos;
129
+ size_t pos_w = sass::string::npos;
123
130
  #endif
124
- if (pos_p != std::string::npos && pos_w != std::string::npos) {
131
+ if (pos_p != sass::string::npos && pos_w != sass::string::npos) {
125
132
  pos = std::max(pos_p, pos_w);
126
133
  }
127
- else if (pos_p != std::string::npos) {
134
+ else if (pos_p != sass::string::npos) {
128
135
  pos = pos_p;
129
136
  }
130
137
  else {
@@ -134,24 +141,24 @@ namespace Sass {
134
141
  }
135
142
 
136
143
  // return only the directory part of path
137
- std::string dir_name(const std::string& path)
144
+ sass::string dir_name(const sass::string& path)
138
145
  {
139
146
  size_t pos = find_last_folder_separator(path);
140
- if (pos == std::string::npos) return "";
147
+ if (pos == sass::string::npos) return "";
141
148
  else return path.substr(0, pos+1);
142
149
  }
143
150
 
144
151
  // return only the filename part of path
145
- std::string base_name(const std::string& path)
152
+ sass::string base_name(const sass::string& path)
146
153
  {
147
154
  size_t pos = find_last_folder_separator(path);
148
- if (pos == std::string::npos) return path;
155
+ if (pos == sass::string::npos) return path;
149
156
  else return path.substr(pos+1);
150
157
  }
151
158
 
152
159
  // do a logical clean up of the path
153
160
  // no physical check on the filesystem
154
- std::string make_canonical_path (std::string path)
161
+ sass::string make_canonical_path (sass::string path)
155
162
  {
156
163
 
157
164
  // declarations
@@ -163,18 +170,18 @@ namespace Sass {
163
170
  #endif
164
171
 
165
172
  pos = 0; // remove all self references inside the path string
166
- while((pos = path.find("/./", pos)) != std::string::npos) path.erase(pos, 2);
173
+ while((pos = path.find("/./", pos)) != sass::string::npos) path.erase(pos, 2);
167
174
 
168
175
  // remove all leading and trailing self references
169
- while(path.length() > 1 && path.substr(0, 2) == "./") path.erase(0, 2);
170
- while((pos = path.length()) > 1 && path.substr(pos - 2) == "/.") path.erase(pos - 2);
176
+ while(path.size() >= 2 && path[0] == '.' && path[1] == '/') path.erase(0, 2);
177
+ while((pos = path.length()) > 1 && path[pos - 2] == '/' && path[pos - 1] == '.') path.erase(pos - 2);
171
178
 
172
179
 
173
180
  size_t proto = 0;
174
181
  // check if we have a protocol
175
- if (path[proto] && Prelexer::is_alpha(path[proto])) {
182
+ if (path[proto] && Util::ascii_isalpha(static_cast<unsigned char>(path[proto]))) {
176
183
  // skip over all alphanumeric characters
177
- while (path[proto] && Prelexer::is_alnum(path[proto++])) {}
184
+ while (path[proto] && Util::ascii_isalnum(static_cast<unsigned char>(path[proto++]))) {}
178
185
  // then skip over the mandatory colon
179
186
  if (proto && path[proto] == ':') ++ proto;
180
187
  }
@@ -183,7 +190,7 @@ namespace Sass {
183
190
  while (path[proto++] == '/') {}
184
191
 
185
192
  pos = proto; // collapse multiple delimiters into a single one
186
- while((pos = path.find("//", pos)) != std::string::npos) path.erase(pos, 1);
193
+ while((pos = path.find("//", pos)) != sass::string::npos) path.erase(pos, 1);
187
194
 
188
195
  return path;
189
196
 
@@ -191,7 +198,7 @@ namespace Sass {
191
198
 
192
199
  // join two path segments cleanly together
193
200
  // but only if right side is not absolute yet
194
- std::string join_paths(std::string l, std::string r)
201
+ sass::string join_paths(sass::string l, sass::string r)
195
202
  {
196
203
 
197
204
  #ifdef _WIN32
@@ -218,16 +225,16 @@ namespace Sass {
218
225
  bool is_slash = pos + 2 == L && (l[pos+1] == '/' || l[pos+1] == '\\');
219
226
  bool is_self = pos + 3 == L && (l[pos+1] == '.');
220
227
  if (!is_self && !is_slash) r = r.substr(3);
221
- else if (pos == std::string::npos) break;
222
- l = l.substr(0, pos == std::string::npos ? pos : pos + 1);
228
+ else if (pos == sass::string::npos) break;
229
+ l = l.substr(0, pos == sass::string::npos ? pos : pos + 1);
223
230
  }
224
231
 
225
232
  return l + r;
226
233
  }
227
234
 
228
- std::string path_for_console(const std::string& rel_path, const std::string& abs_path, const std::string& orig_path)
235
+ sass::string path_for_console(const sass::string& rel_path, const sass::string& abs_path, const sass::string& orig_path)
229
236
  {
230
- // magic algorith goes here!!
237
+ // magic algorithm goes here!!
231
238
 
232
239
  // if the file is outside this directory show the absolute path
233
240
  if (rel_path.substr(0, 3) == "../") {
@@ -238,24 +245,32 @@ namespace Sass {
238
245
  }
239
246
 
240
247
  // create an absolute path by resolving relative paths with cwd
241
- std::string rel2abs(const std::string& path, const std::string& base, const std::string& cwd)
248
+ sass::string rel2abs(const sass::string& path, const sass::string& base, const sass::string& cwd)
242
249
  {
243
- return make_canonical_path(join_paths(join_paths(cwd + "/", base + "/"), path));
250
+ sass::string rv = make_canonical_path(join_paths(join_paths(cwd + "/", base + "/"), path));
251
+ #ifdef _WIN32
252
+ // On windows we may get an absolute path without directory
253
+ // In that case we should prepend the directory from the root
254
+ if (rv[0] == '/' && rv[1] != '/') {
255
+ rv.insert(0, cwd, 0, 2);
256
+ }
257
+ #endif
258
+ return rv;
244
259
  }
245
260
 
246
261
  // create a path that is relative to the given base directory
247
262
  // path and base will first be resolved against cwd to make them absolute
248
- std::string abs2rel(const std::string& path, const std::string& base, const std::string& cwd)
263
+ sass::string abs2rel(const sass::string& path, const sass::string& base, const sass::string& cwd)
249
264
  {
250
265
 
251
- std::string abs_path = rel2abs(path, cwd);
252
- std::string abs_base = rel2abs(base, cwd);
266
+ sass::string abs_path = rel2abs(path, cwd);
267
+ sass::string abs_base = rel2abs(base, cwd);
253
268
 
254
269
  size_t proto = 0;
255
270
  // check if we have a protocol
256
- if (path[proto] && Prelexer::is_alpha(path[proto])) {
271
+ if (path[proto] && Util::ascii_isalpha(static_cast<unsigned char>(path[proto]))) {
257
272
  // skip over all alphanumeric characters
258
- while (path[proto] && Prelexer::is_alnum(path[proto++])) {}
273
+ while (path[proto] && Util::ascii_isalnum(static_cast<unsigned char>(path[proto++]))) {}
259
274
  // then skip over the mandatory colon
260
275
  if (proto && path[proto] == ':') ++ proto;
261
276
  }
@@ -270,8 +285,8 @@ namespace Sass {
270
285
  if (abs_base[0] != abs_path[0]) return abs_path;
271
286
  #endif
272
287
 
273
- std::string stripped_uri = "";
274
- std::string stripped_base = "";
288
+ sass::string stripped_uri = "";
289
+ sass::string stripped_base = "";
275
290
 
276
291
  size_t index = 0;
277
292
  size_t minSize = std::min(abs_path.size(), abs_base.size());
@@ -281,7 +296,8 @@ namespace Sass {
281
296
  #else
282
297
  // compare the charactes in a case insensitive manner
283
298
  // windows fs is only case insensitive in ascii ranges
284
- if (tolower(abs_path[i]) != tolower(abs_base[i])) break;
299
+ if (Util::ascii_tolower(static_cast<unsigned char>(abs_path[i])) !=
300
+ Util::ascii_tolower(static_cast<unsigned char>(abs_base[i]))) break;
285
301
  #endif
286
302
  if (abs_path[i] == '/') index = i + 1;
287
303
  }
@@ -309,7 +325,7 @@ namespace Sass {
309
325
  }
310
326
  }
311
327
 
312
- std::string result = "";
328
+ sass::string result = "";
313
329
  for (size_t i = 0; i < directories; ++i) {
314
330
  result += "../";
315
331
  }
@@ -323,16 +339,18 @@ namespace Sass {
323
339
  // (2) underscore + given
324
340
  // (3) underscore + given + extension
325
341
  // (4) given + extension
326
- std::vector<Include> resolve_includes(const std::string& root, const std::string& file, const std::vector<std::string>& exts)
342
+ // (5) given + _index.scss
343
+ // (6) given + _index.sass
344
+ sass::vector<Include> resolve_includes(const sass::string& root, const sass::string& file, const sass::vector<sass::string>& exts)
327
345
  {
328
- std::string filename = join_paths(root, file);
346
+ sass::string filename = join_paths(root, file);
329
347
  // split the filename
330
- std::string base(dir_name(file));
331
- std::string name(base_name(file));
332
- std::vector<Include> includes;
348
+ sass::string base(dir_name(file));
349
+ sass::string name(base_name(file));
350
+ sass::vector<Include> includes;
333
351
  // create full path (maybe relative)
334
- std::string rel_path(join_paths(base, name));
335
- std::string abs_path(join_paths(root, rel_path));
352
+ sass::string rel_path(join_paths(base, name));
353
+ sass::string abs_path(join_paths(root, rel_path));
336
354
  if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
337
355
  // next test variation with underscore
338
356
  rel_path = join_paths(base, "_" + name);
@@ -350,28 +368,47 @@ namespace Sass {
350
368
  abs_path = join_paths(root, rel_path);
351
369
  if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
352
370
  }
371
+ // index files
372
+ if (includes.size() == 0) {
373
+ // ignore directories that look like @import'able filename
374
+ for(auto ext : exts) {
375
+ if (ends_with(name, ext)) return includes;
376
+ }
377
+ // next test underscore index exts
378
+ for(auto ext : exts) {
379
+ rel_path = join_paths(base, join_paths(name, "_index" + ext));
380
+ abs_path = join_paths(root, rel_path);
381
+ if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
382
+ }
383
+ // next test plain index exts
384
+ for(auto ext : exts) {
385
+ rel_path = join_paths(base, join_paths(name, "index" + ext));
386
+ abs_path = join_paths(root, rel_path);
387
+ if (file_exists(abs_path)) includes.push_back({{ rel_path, root }, abs_path });
388
+ }
389
+ }
353
390
  // nothing found
354
391
  return includes;
355
392
  }
356
393
 
357
- std::vector<std::string> find_files(const std::string& file, const std::vector<std::string> paths)
394
+ sass::vector<sass::string> find_files(const sass::string& file, const sass::vector<sass::string> paths)
358
395
  {
359
- std::vector<std::string> includes;
360
- for (std::string path : paths) {
361
- std::string abs_path(join_paths(path, file));
396
+ sass::vector<sass::string> includes;
397
+ for (sass::string path : paths) {
398
+ sass::string abs_path(join_paths(path, file));
362
399
  if (file_exists(abs_path)) includes.push_back(abs_path);
363
400
  }
364
401
  return includes;
365
402
  }
366
403
 
367
- std::vector<std::string> find_files(const std::string& file, struct Sass_Compiler* compiler)
404
+ sass::vector<sass::string> find_files(const sass::string& file, struct Sass_Compiler* compiler)
368
405
  {
369
406
  // get the last import entry to get current base directory
370
407
  // struct Sass_Options* options = sass_compiler_get_options(compiler);
371
408
  Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
372
- const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
409
+ const sass::vector<sass::string>& incs = compiler->cpp_ctx->include_paths;
373
410
  // create the vector with paths to lookup
374
- std::vector<std::string> paths(1 + incs.size());
411
+ sass::vector<sass::string> paths(1 + incs.size());
375
412
  paths.push_back(dir_name(import->abs_path));
376
413
  paths.insert(paths.end(), incs.begin(), incs.end());
377
414
  // dispatch to find files in paths
@@ -380,7 +417,7 @@ namespace Sass {
380
417
 
381
418
  // helper function to search one file in all include paths
382
419
  // this is normally not used internally by libsass (C-API sugar)
383
- std::string find_file(const std::string& file, const std::vector<std::string> paths)
420
+ sass::string find_file(const sass::string& file, const sass::vector<sass::string> paths)
384
421
  {
385
422
  if (file.empty()) return file;
386
423
  auto res = find_files(file, paths);
@@ -388,30 +425,33 @@ namespace Sass {
388
425
  }
389
426
 
390
427
  // helper function to resolve a filename
391
- std::string find_include(const std::string& file, const std::vector<std::string> paths)
428
+ sass::string find_include(const sass::string& file, const sass::vector<sass::string> paths)
392
429
  {
393
430
  // search in every include path for a match
394
431
  for (size_t i = 0, S = paths.size(); i < S; ++i)
395
432
  {
396
- std::vector<Include> resolved(resolve_includes(paths[i], file));
433
+ sass::vector<Include> resolved(resolve_includes(paths[i], file));
397
434
  if (resolved.size()) return resolved[0].abs_path;
398
435
  }
399
436
  // nothing found
400
- return std::string("");
437
+ return sass::string("");
401
438
  }
402
439
 
403
440
  // try to load the given filename
404
441
  // returned memory must be freed
405
442
  // will auto convert .sass files
406
- char* read_file(const std::string& path)
443
+ char* read_file(const sass::string& path)
407
444
  {
408
445
  #ifdef _WIN32
409
446
  BYTE* pBuffer;
410
447
  DWORD dwBytes;
411
448
  wchar_t resolved[32768];
412
449
  // windows unicode filepaths are encoded in utf16
413
- std::string abspath(join_paths(get_cwd(), path));
414
- std::wstring wpath(UTF_8::convert_to_utf16("\\\\?\\" + abspath));
450
+ sass::string abspath(join_paths(get_cwd(), path));
451
+ if (!(abspath[0] == '/' && abspath[1] == '/')) {
452
+ abspath = "//?/" + abspath;
453
+ }
454
+ std::wstring wpath(UTF_8::convert_to_utf16(abspath));
415
455
  std::replace(wpath.begin(), wpath.end(), '/', '\\');
416
456
  DWORD rv = GetFullPathNameW(wpath.c_str(), 32767, resolved, NULL);
417
457
  if (rv > 32767) throw Exception::OperationError("Path is too long");
@@ -430,28 +470,34 @@ namespace Sass {
430
470
  // just convert from unsigned char*
431
471
  char* contents = (char*) pBuffer;
432
472
  #else
473
+ // Read the file using `<cstdio>` instead of `<fstream>` for better portability.
474
+ // The `<fstream>` header initializes `<locale>` and this buggy in GCC4/5 with static linking.
475
+ // See:
476
+ // https://www.spinics.net/lists/gcchelp/msg46851.html
477
+ // https://github.com/sass/sassc-ruby/issues/128
433
478
  struct stat st;
434
479
  if (stat(path.c_str(), &st) == -1 || S_ISDIR(st.st_mode)) return 0;
435
- std::ifstream file(path.c_str(), std::ios::in | std::ios::binary | std::ios::ate);
436
- char* contents = 0;
437
- if (file.is_open()) {
438
- size_t size = file.tellg();
439
- // allocate an extra byte for the null char
440
- // and another one for edge-cases in lexer
441
- contents = (char*) malloc((size+2)*sizeof(char));
442
- file.seekg(0, std::ios::beg);
443
- file.read(contents, size);
444
- contents[size+0] = '\0';
445
- contents[size+1] = '\0';
446
- file.close();
480
+ FILE* fd = std::fopen(path.c_str(), "rb");
481
+ if (fd == nullptr) return nullptr;
482
+ const std::size_t size = st.st_size;
483
+ char* contents = static_cast<char*>(malloc(st.st_size + 2 * sizeof(char)));
484
+ if (std::fread(static_cast<void*>(contents), 1, size, fd) != size) {
485
+ free(contents);
486
+ std::fclose(fd);
487
+ return nullptr;
488
+ }
489
+ if (std::fclose(fd) != 0) {
490
+ free(contents);
491
+ return nullptr;
447
492
  }
493
+ contents[size] = '\0';
494
+ contents[size + 1] = '\0';
448
495
  #endif
449
- std::string extension;
496
+ sass::string extension;
450
497
  if (path.length() > 5) {
451
498
  extension = path.substr(path.length() - 5, 5);
452
499
  }
453
- for(size_t i=0; i<extension.size();++i)
454
- extension[i] = tolower(extension[i]);
500
+ Util::ascii_str_tolower(&extension);
455
501
  if (extension == ".sass" && contents != 0) {
456
502
  char * converted = sass2scss(contents, SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT);
457
503
  free(contents); // free the indented contents
@@ -462,21 +508,21 @@ namespace Sass {
462
508
  }
463
509
 
464
510
  // split a path string delimited by semicolons or colons (OS dependent)
465
- std::vector<std::string> split_path_list(const char* str)
511
+ sass::vector<sass::string> split_path_list(const char* str)
466
512
  {
467
- std::vector<std::string> paths;
513
+ sass::vector<sass::string> paths;
468
514
  if (str == NULL) return paths;
469
515
  // find delimiter via prelexer (return zero at end)
470
516
  const char* end = Prelexer::find_first<PATH_SEP>(str);
471
517
  // search until null delimiter
472
518
  while (end) {
473
519
  // add path from current position to delimiter
474
- paths.push_back(std::string(str, end - str));
520
+ paths.push_back(sass::string(str, end - str));
475
521
  str = end + 1; // skip delimiter
476
522
  end = Prelexer::find_first<PATH_SEP>(str);
477
523
  }
478
524
  // add path from current position to end
479
- paths.push_back(std::string(str));
525
+ paths.push_back(sass::string(str));
480
526
  // return back
481
527
  return paths;
482
528
  }