sassc 2.0.0 → 2.4.0

Sign up to get free protection for your applications and to get access to all the features.
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
  }