sassc 0.0.9 → 0.0.10

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 (111) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/ext/libsass/.gitignore +13 -6
  4. data/ext/libsass/Makefile +42 -26
  5. data/ext/libsass/Makefile.am +43 -30
  6. data/ext/libsass/Readme.md +4 -2
  7. data/ext/libsass/appveyor.yml +10 -14
  8. data/ext/libsass/ast.cpp +54 -44
  9. data/ext/libsass/ast.hpp +404 -236
  10. data/ext/libsass/ast_def_macros.hpp +5 -0
  11. data/ext/libsass/ast_factory.hpp +6 -3
  12. data/ext/libsass/ast_fwd_decl.hpp +12 -0
  13. data/ext/libsass/b64/encode.h +2 -2
  14. data/ext/libsass/backtrace.hpp +13 -17
  15. data/ext/libsass/base64vlq.hpp +4 -1
  16. data/ext/libsass/bind.cpp +12 -15
  17. data/ext/libsass/bind.hpp +6 -6
  18. data/ext/libsass/color_names.hpp +4 -1
  19. data/ext/libsass/configure.ac +7 -21
  20. data/ext/libsass/constants.cpp +6 -4
  21. data/ext/libsass/constants.hpp +10 -4
  22. data/ext/libsass/context.cpp +89 -58
  23. data/ext/libsass/context.hpp +28 -35
  24. data/ext/libsass/contextualize.cpp +20 -10
  25. data/ext/libsass/contextualize.hpp +8 -23
  26. data/ext/libsass/contrib/libsass.spec +66 -0
  27. data/ext/libsass/cssize.cpp +547 -0
  28. data/ext/libsass/cssize.hpp +82 -0
  29. data/ext/libsass/debug.hpp +3 -3
  30. data/ext/libsass/debugger.hpp +358 -0
  31. data/ext/libsass/emitter.cpp +255 -0
  32. data/ext/libsass/emitter.hpp +83 -0
  33. data/ext/libsass/environment.hpp +7 -3
  34. data/ext/libsass/error_handling.cpp +11 -14
  35. data/ext/libsass/error_handling.hpp +9 -7
  36. data/ext/libsass/eval.cpp +253 -161
  37. data/ext/libsass/eval.hpp +13 -13
  38. data/ext/libsass/expand.cpp +135 -64
  39. data/ext/libsass/expand.hpp +11 -13
  40. data/ext/libsass/extend.cpp +66 -20
  41. data/ext/libsass/extend.hpp +6 -11
  42. data/ext/libsass/file.cpp +31 -26
  43. data/ext/libsass/file.hpp +6 -1
  44. data/ext/libsass/functions.cpp +270 -287
  45. data/ext/libsass/functions.hpp +8 -11
  46. data/ext/libsass/inspect.cpp +385 -255
  47. data/ext/libsass/inspect.hpp +15 -26
  48. data/ext/libsass/kwd_arg_macros.hpp +5 -0
  49. data/ext/libsass/mapping.hpp +4 -3
  50. data/ext/libsass/memory_manager.hpp +5 -2
  51. data/ext/libsass/node.cpp +50 -50
  52. data/ext/libsass/node.hpp +26 -27
  53. data/ext/libsass/operation.hpp +15 -4
  54. data/ext/libsass/output.cpp +401 -0
  55. data/ext/libsass/output.hpp +56 -0
  56. data/ext/libsass/parser.cpp +573 -399
  57. data/ext/libsass/parser.hpp +122 -88
  58. data/ext/libsass/paths.hpp +7 -2
  59. data/ext/libsass/plugins.cpp +155 -0
  60. data/ext/libsass/plugins.hpp +56 -0
  61. data/ext/libsass/position.cpp +128 -0
  62. data/ext/libsass/position.hpp +108 -11
  63. data/ext/libsass/prelexer.cpp +184 -110
  64. data/ext/libsass/prelexer.hpp +131 -24
  65. data/ext/libsass/remove_placeholders.cpp +1 -1
  66. data/ext/libsass/remove_placeholders.hpp +6 -6
  67. data/ext/libsass/sass.cpp +3 -3
  68. data/ext/libsass/sass.h +12 -4
  69. data/ext/libsass/sass2scss.cpp +3 -2
  70. data/ext/libsass/sass2scss.h +5 -0
  71. data/ext/libsass/sass_context.cpp +136 -37
  72. data/ext/libsass/sass_context.h +19 -10
  73. data/ext/libsass/sass_functions.cpp +29 -2
  74. data/ext/libsass/sass_functions.h +8 -2
  75. data/ext/libsass/sass_interface.cpp +32 -23
  76. data/ext/libsass/sass_interface.h +9 -4
  77. data/ext/libsass/sass_util.cpp +19 -23
  78. data/ext/libsass/sass_util.hpp +28 -27
  79. data/ext/libsass/sass_values.cpp +6 -4
  80. data/ext/libsass/sass_values.h +3 -3
  81. data/ext/libsass/script/ci-build-libsass +13 -1
  82. data/ext/libsass/script/ci-report-coverage +2 -1
  83. data/ext/libsass/source_map.cpp +79 -28
  84. data/ext/libsass/source_map.hpp +35 -16
  85. data/ext/libsass/subset_map.hpp +6 -4
  86. data/ext/libsass/to_c.hpp +4 -4
  87. data/ext/libsass/to_string.cpp +13 -8
  88. data/ext/libsass/to_string.hpp +6 -4
  89. data/ext/libsass/units.cpp +2 -1
  90. data/ext/libsass/units.hpp +6 -1
  91. data/ext/libsass/utf8_string.cpp +0 -5
  92. data/ext/libsass/utf8_string.hpp +3 -2
  93. data/ext/libsass/util.cpp +461 -49
  94. data/ext/libsass/util.hpp +34 -13
  95. data/ext/libsass/version.sh +10 -0
  96. data/ext/libsass/win/libsass.filters +20 -11
  97. data/ext/libsass/win/libsass.vcxproj +11 -8
  98. data/lib/sassc/importer.rb +1 -8
  99. data/lib/sassc/native.rb +7 -0
  100. data/lib/sassc/native/native_context_api.rb +5 -5
  101. data/lib/sassc/version.rb +1 -1
  102. data/test/native_test.rb +1 -1
  103. metadata +14 -10
  104. data/ext/libsass/copy_c_str.cpp +0 -13
  105. data/ext/libsass/copy_c_str.hpp +0 -5
  106. data/ext/libsass/output_compressed.cpp +0 -401
  107. data/ext/libsass/output_compressed.hpp +0 -95
  108. data/ext/libsass/output_nested.cpp +0 -364
  109. data/ext/libsass/output_nested.hpp +0 -108
  110. data/ext/libsass/test-driver +0 -127
  111. data/ext/libsass/token.hpp +0 -32
@@ -1,27 +1,19 @@
1
- #define SASS_EXPAND
1
+ #ifndef SASS_EXPAND_H
2
+ #define SASS_EXPAND_H
2
3
 
3
- #include <vector>
4
4
  #include <map>
5
+ #include <vector>
5
6
  #include <iostream>
6
7
 
7
- #ifndef SASS_AST
8
8
  #include "ast.hpp"
9
- #endif
10
-
11
- #ifndef SASS_OPERATION
9
+ #include "eval.hpp"
12
10
  #include "operation.hpp"
13
- #endif
14
-
15
- #ifndef SASS_ENVIRONMENT
16
11
  #include "environment.hpp"
17
- #endif
12
+ #include "contextualize.hpp"
18
13
 
19
14
  namespace Sass {
20
15
  using namespace std;
21
16
 
22
- struct Context;
23
- class Eval;
24
- class Contextualize;
25
17
  typedef Environment<AST_Node*> Env;
26
18
  struct Backtrace;
27
19
 
@@ -34,6 +26,9 @@ namespace Sass {
34
26
  vector<Block*> block_stack;
35
27
  vector<String*> property_stack;
36
28
  vector<Selector*> selector_stack;
29
+ vector<Selector*> at_root_selector_stack;
30
+ bool in_at_root;
31
+ bool in_keyframes;
37
32
  Backtrace* backtrace;
38
33
 
39
34
  Statement* fallback_impl(AST_Node* n);
@@ -49,6 +44,7 @@ namespace Sass {
49
44
  Statement* operator()(Propset*);
50
45
  Statement* operator()(Media_Block*);
51
46
  Statement* operator()(Feature_Block*);
47
+ Statement* operator()(At_Root_Block*);
52
48
  Statement* operator()(At_Rule*);
53
49
  Statement* operator()(Declaration*);
54
50
  Statement* operator()(Assignment*);
@@ -75,3 +71,5 @@ namespace Sass {
75
71
  };
76
72
 
77
73
  }
74
+
75
+ #endif
@@ -5,9 +5,7 @@
5
5
  #include "backtrace.hpp"
6
6
  #include "paths.hpp"
7
7
  #include "parser.hpp"
8
- #ifndef SASS_AST
9
8
  #include "node.hpp"
10
- #endif
11
9
  #include "sass_util.hpp"
12
10
  #include "debug.hpp"
13
11
  #include <iostream>
@@ -237,14 +235,15 @@ namespace Sass {
237
235
  return os;
238
236
  }
239
237
  #endif
238
+
240
239
  static bool parentSuperselector(Complex_Selector* pOne, Complex_Selector* pTwo, Context& ctx) {
241
240
  // TODO: figure out a better way to create a Complex_Selector from scratch
242
241
  // TODO: There's got to be a better way. This got ugly quick...
243
- Position noPosition;
244
- Type_Selector fakeParent("", noPosition, "temp");
245
- Compound_Selector fakeHead("", noPosition, 1 /*size*/);
242
+ Position noPosition(-1, -1, -1);
243
+ Type_Selector fakeParent(ParserState("[FAKE]"), "temp");
244
+ Compound_Selector fakeHead(ParserState("[FAKE]"), 1 /*size*/);
246
245
  fakeHead.elements().push_back(&fakeParent);
247
- Complex_Selector fakeParentContainer("", noPosition, Complex_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
246
+ Complex_Selector fakeParentContainer(ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
248
247
 
249
248
  pOne->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
250
249
  pTwo->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
@@ -602,11 +601,11 @@ namespace Sass {
602
601
  static bool parentSuperselector(const Node& one, const Node& two, Context& ctx) {
603
602
  // TODO: figure out a better way to create a Complex_Selector from scratch
604
603
  // TODO: There's got to be a better way. This got ugly quick...
605
- Position noPosition;
606
- Type_Selector fakeParent("", noPosition, "temp");
607
- Compound_Selector fakeHead("", noPosition, 1 /*size*/);
604
+ Position noPosition(-1, -1, -1);
605
+ Type_Selector fakeParent(ParserState("[FAKE]"), "temp");
606
+ Compound_Selector fakeHead(ParserState("[FAKE]"), 1 /*size*/);
608
607
  fakeHead.elements().push_back(&fakeParent);
609
- Complex_Selector fakeParentContainer("", noPosition, Complex_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
608
+ Complex_Selector fakeParentContainer(ParserState("[FAKE]"), Complex_Selector::ANCESTOR_OF, &fakeHead /*head*/, NULL /*tail*/);
610
609
 
611
610
  Complex_Selector* pOneWithFakeParent = nodeToComplexSelector(one, ctx);
612
611
  pOneWithFakeParent->set_innermost(&fakeParentContainer, Complex_Selector::ANCESTOR_OF);
@@ -1521,7 +1520,7 @@ namespace Sass {
1521
1520
  // DEBUG_EXEC(EXTEND_COMPOUND, printComplexSelector(&seq, "SEQ: "))
1522
1521
 
1523
1522
 
1524
- Compound_Selector* pSels = new (ctx.mem) Compound_Selector(pSelector->path(), pSelector->position());
1523
+ Compound_Selector* pSels = new (ctx.mem) Compound_Selector(pSelector->pstate());
1525
1524
  for (vector<ExtensionPair>::iterator groupIter = group.begin(), groupIterEnd = group.end(); groupIter != groupIterEnd; groupIter++) {
1526
1525
  ExtensionPair& pair = *groupIter;
1527
1526
  Compound_Selector* pCompound = pair.second;
@@ -1553,7 +1552,7 @@ namespace Sass {
1553
1552
  Compound_Selector* pUnifiedSelector = NULL;
1554
1553
 
1555
1554
  if (!pInnermostCompoundSelector) {
1556
- pInnermostCompoundSelector = new (ctx.mem) Compound_Selector(pSelector->path(), pSelector->position());
1555
+ pInnermostCompoundSelector = new (ctx.mem) Compound_Selector(pSelector->pstate());
1557
1556
  }
1558
1557
 
1559
1558
  pUnifiedSelector = pInnermostCompoundSelector->unify_with(pSelectorWithoutExtendSelectors, ctx);
@@ -1579,7 +1578,7 @@ namespace Sass {
1579
1578
  // complex is that Complex_Selector contains a combinator, but in ruby combinators have already been filtered
1580
1579
  // out and aren't operated on.
1581
1580
  Complex_Selector* pNewSelector = pExtComplexSelector->cloneFully(ctx);
1582
- Complex_Selector* pNewInnerMost = new (ctx.mem) Complex_Selector(pSelector->path(), pSelector->position(), Complex_Selector::ANCESTOR_OF, pUnifiedSelector, NULL);
1581
+ Complex_Selector* pNewInnerMost = new (ctx.mem) Complex_Selector(pSelector->pstate(), Complex_Selector::ANCESTOR_OF, pUnifiedSelector, NULL);
1583
1582
  Complex_Selector::Combinator combinator = pNewSelector->clear_innermost();
1584
1583
  pNewSelector->set_innermost(pNewInnerMost, combinator);
1585
1584
 
@@ -1596,6 +1595,7 @@ namespace Sass {
1596
1595
  #endif
1597
1596
 
1598
1597
 
1598
+ if (pSelector && pSelector->has_line_feed()) pNewSelector->has_line_feed(true);
1599
1599
 
1600
1600
  // Set the sources on our new Complex_Selector to the sources of this simple sequence plus the thing we're extending.
1601
1601
  DEBUG_PRINTLN(EXTEND_COMPOUND, "SOURCES SETTING ON NEW SEQ: " << complexSelectorToNode(pNewSelector, ctx))
@@ -1675,13 +1675,58 @@ namespace Sass {
1675
1675
 
1676
1676
  if (pHead) {
1677
1677
  SubsetMapEntries entries = subsetMap.get_v(pHead->to_str_vec());
1678
+ for (ExtensionPair ext : entries) {
1679
+ // check if both selectors have the same media block parent
1680
+ if (ext.first->media_block() == pComplexSelector->media_block()) continue;
1681
+ To_String to_string(&ctx);
1682
+ if (ext.second->media_block() && ext.second->media_block()->media_queries() &&
1683
+ pComplexSelector->media_block() && pComplexSelector->media_block()->media_queries())
1684
+ {
1685
+ string query_left(ext.second->media_block()->media_queries()->perform(&to_string));
1686
+ string query_right(pComplexSelector->media_block()->media_queries()->perform(&to_string));
1687
+ if (query_left == query_right) continue;
1688
+ }
1678
1689
 
1679
- hasExtension = entries.size() > 0;
1690
+ // fail if one goes across media block boundaries
1691
+ stringstream err;
1692
+ string cwd(Sass::File::get_cwd());
1693
+ ParserState pstate(ext.second->pstate());
1694
+ string rel_path(Sass::File::resolve_relative_path(pstate.path, cwd, cwd));
1695
+ err << "You may not @extend an outer selector from within @media.\n";
1696
+ err << "You may only @extend selectors within the same directive.\n";
1697
+ err << "From \"@extend " << ext.second->perform(&to_string) << "\"";
1698
+ err << " on line " << pstate.line+1 << " of " << rel_path << "\n";
1699
+ error(err.str(), pComplexSelector->pstate());
1700
+ }
1701
+ if (entries.size() > 0) hasExtension = true;
1680
1702
  }
1681
1703
 
1682
1704
  pIter = pIter->tail();
1683
1705
  }
1684
1706
 
1707
+ if (!hasExtension) {
1708
+ /* ToDo: don't break stuff
1709
+ stringstream err;
1710
+ To_String to_string(&ctx);
1711
+ string cwd(Sass::File::get_cwd());
1712
+ string sel1(pComplexSelector->perform(&to_string));
1713
+ Compound_Selector* pExtendSelector = 0;
1714
+ for (auto i : subsetMap.values()) {
1715
+ if (i.first == pComplexSelector) {
1716
+ pExtendSelector = i.second;
1717
+ break;
1718
+ }
1719
+ }
1720
+ if (!pExtendSelector || !pExtendSelector->is_optional()) {
1721
+ string sel2(pExtendSelector ? pExtendSelector->perform(&to_string) : "[unknown]");
1722
+ err << "\"" << sel1 << "\" failed to @extend \"" << sel2 << "\"\n";
1723
+ err << "The selector \"" << sel2 << "\" was not found.\n";
1724
+ err << "Use \"@extend " << sel2 << " !optional\" if the extend should be able to fail.";
1725
+ error(err.str(), pExtendSelector ? pExtendSelector->pstate() : pComplexSelector->pstate());
1726
+ }
1727
+ */
1728
+ }
1729
+
1685
1730
  return hasExtension;
1686
1731
  }
1687
1732
 
@@ -1703,8 +1748,9 @@ namespace Sass {
1703
1748
  ExtensionSubsetMap& subsetMap,
1704
1749
  set<Compound_Selector> seen) {
1705
1750
 
1706
- Node complexSelector = complexSelectorToNode(pComplexSelector, ctx);
1751
+ pComplexSelector->tail()->has_line_feed(pComplexSelector->has_line_feed());
1707
1752
 
1753
+ Node complexSelector = complexSelectorToNode(pComplexSelector, ctx);
1708
1754
  DEBUG_PRINTLN(EXTEND_COMPLEX, "EXTEND COMPLEX: " << complexSelector)
1709
1755
 
1710
1756
  Node extendedNotExpanded = Node::createCollection();
@@ -1808,9 +1854,9 @@ namespace Sass {
1808
1854
  */
1809
1855
  static Selector_List* extendSelectorList(Selector_List* pSelectorList, Context& ctx, ExtensionSubsetMap& subsetMap, bool& extendedSomething) {
1810
1856
 
1811
- To_String to_string;
1857
+ To_String to_string(&ctx);
1812
1858
 
1813
- Selector_List* pNewSelectors = new (ctx.mem) Selector_List(pSelectorList->path(), pSelectorList->position(), pSelectorList->length());
1859
+ Selector_List* pNewSelectors = new (ctx.mem) Selector_List(pSelectorList->pstate(), pSelectorList->length());
1814
1860
 
1815
1861
  extendedSomething = false;
1816
1862
 
@@ -1883,7 +1929,7 @@ namespace Sass {
1883
1929
  // Extend a ruleset by extending the selectors and updating them on the ruleset. The block's rules don't need to change.
1884
1930
  template <typename ObjectType>
1885
1931
  static void extendObjectWithSelectorAndBlock(ObjectType* pObject, Context& ctx, ExtensionSubsetMap& subsetMap) {
1886
- To_String to_string;
1932
+ To_String to_string(&ctx);
1887
1933
 
1888
1934
  DEBUG_PRINTLN(EXTEND_OBJECT, "FOUND SELECTOR: " << static_cast<Selector_List*>(pObject->selector())->perform(&to_string))
1889
1935
 
@@ -1904,12 +1950,12 @@ namespace Sass {
1904
1950
  // re-parse in order to restructure expanded placeholder nodes correctly.
1905
1951
  //
1906
1952
  // TODO: I don't know if this is needed, but it was in the original C++ implementation, so I kept it. Try running the tests without re-parsing.
1953
+ // this probably messes up source-maps
1907
1954
  pObject->selector(
1908
1955
  Parser::from_c_str(
1909
1956
  (pNewSelectorList->perform(&to_string) + ";").c_str(),
1910
1957
  ctx,
1911
- pNewSelectorList->path(),
1912
- pNewSelectorList->position()
1958
+ pNewSelectorList->pstate()
1913
1959
  ).parse_selector_group()
1914
1960
  );
1915
1961
  } else {
@@ -1,26 +1,19 @@
1
- #define SASS_EXTEND
1
+ #ifndef SASS_EXTEND_H
2
+ #define SASS_EXTEND_H
2
3
 
3
- #include <vector>
4
4
  #include <map>
5
5
  #include <set>
6
+ #include <vector>
6
7
  #include <iostream>
7
8
 
8
- #ifndef SASS_AST
9
9
  #include "ast.hpp"
10
- #endif
11
-
12
- #ifndef SASS_OPERATION
13
10
  #include "operation.hpp"
14
- #endif
15
-
16
- #ifndef SASS_SUBSET_MAP
17
11
  #include "subset_map.hpp"
18
- #endif
19
12
 
20
13
  namespace Sass {
21
14
  using namespace std;
22
15
 
23
- struct Context;
16
+ class Context;
24
17
 
25
18
  typedef Subset_Map<string, pair<Complex_Selector*, Compound_Selector*> > ExtensionSubsetMap;
26
19
 
@@ -48,3 +41,5 @@ namespace Sass {
48
41
  };
49
42
 
50
43
  }
44
+
45
+ #endif
@@ -9,6 +9,7 @@
9
9
  #include <iostream>
10
10
  #include <fstream>
11
11
  #include <cctype>
12
+ #include <vector>
12
13
  #include <algorithm>
13
14
  #include <sys/stat.h>
14
15
  #include "file.hpp"
@@ -202,34 +203,38 @@ namespace Sass {
202
203
  // (4) given + extension
203
204
  char* contents = 0;
204
205
  real_path = path;
205
- // if the file isn't found with the given filename ...
206
+ vector<string> exts(3);
207
+ exts[0] = ".scss";
208
+ exts[1] = ".sass";
209
+ exts[2] = ".css";
210
+
211
+ // if the file isn't found with the given filename (1)
206
212
  if (!(contents = read_file(real_path))) {
207
213
  string dir(dir_name(path));
208
214
  string base(base_name(path));
209
- string _base("_" + base);
210
- real_path = dir + _base;
211
- // if the file isn't found with '_' + filename ...
212
- if (!(contents = read_file(real_path))) {
213
- string _base_scss(_base + ".scss");
214
- real_path = dir + _base_scss;
215
- // if the file isn't found with '_' + filename + ".scss" ...
216
- if (!(contents = read_file(real_path))) {
217
- string _base_sass(_base + ".sass");
218
- real_path = dir + _base_sass;
219
- // if the file isn't found with '_' + filename + ".sass" ...
220
- if (!(contents = read_file(real_path))) {
221
- string base_scss(base + ".scss");
222
- real_path = dir + base_scss;
223
- // if the file isn't found with filename + ".scss" ...
224
- if (!(contents = read_file(real_path))) {
225
- string base_sass(base + ".sass");
226
- real_path = dir + base_sass;
227
- // if the file isn't found with filename + ".sass" ...
228
- if (!(contents = read_file(real_path))) {
229
- // default back to scss version
230
- real_path = dir + base_scss;
231
- }
232
- }
215
+ real_path = dir + base;
216
+ // (2) underscore + given
217
+ string test_path(dir + "_" + base);
218
+ if ((contents = read_file(test_path))) {
219
+ real_path = test_path;
220
+ }
221
+ // (3) underscore + given + extension
222
+ if (!contents) {
223
+ for(auto ext : exts) {
224
+ test_path = dir + "_" + base + ext;
225
+ if ((contents = read_file(test_path))) {
226
+ real_path = test_path;
227
+ break;
228
+ }
229
+ }
230
+ }
231
+ // (4) given + extension
232
+ if (!contents) {
233
+ for(auto ext : exts) {
234
+ test_path = dir + base + ext;
235
+ if ((contents = read_file(test_path))) {
236
+ real_path = test_path;
237
+ break;
233
238
  }
234
239
  }
235
240
  }
@@ -279,7 +284,7 @@ namespace Sass {
279
284
  for(size_t i=0; i<extension.size();++i)
280
285
  extension[i] = tolower(extension[i]);
281
286
  if (extension == ".sass" && contents != 0) {
282
- char * converted = sass2scss(contents, SASS2SCSS_PRETTIFY_1);
287
+ char * converted = sass2scss(contents, SASS2SCSS_PRETTIFY_1 | SASS2SCSS_KEEP_COMMENT);
283
288
  delete[] contents; // free the indented contents
284
289
  return converted; // should be freed by caller
285
290
  } else {
@@ -1,8 +1,11 @@
1
+ #ifndef SASS_FILE_H
2
+ #define SASS_FILE_H
3
+
1
4
  #include <string>
2
5
 
3
6
  namespace Sass {
4
7
  using namespace std;
5
- struct Context;
8
+ class Context;
6
9
  namespace File {
7
10
  string get_cwd();
8
11
  string base_name(string);
@@ -16,3 +19,5 @@ namespace Sass {
16
19
  char* read_file(string path);
17
20
  }
18
21
  }
22
+
23
+ #endif
@@ -27,9 +27,9 @@
27
27
  #include "wincrypt.h"
28
28
  #endif
29
29
 
30
- #define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, path, position, backtrace)
31
- #define ARGR(argname, argtype, lo, hi) get_arg_r(argname, env, sig, path, position, lo, hi, backtrace)
32
- #define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, path, position, backtrace, ctx)
30
+ #define ARG(argname, argtype) get_arg<argtype>(argname, env, sig, pstate, backtrace)
31
+ #define ARGR(argname, argtype, lo, hi) get_arg_r(argname, env, sig, pstate, lo, hi, backtrace)
32
+ #define ARGM(argname, argtype, ctx) get_arg_m(argname, env, sig, pstate, backtrace, ctx)
33
33
 
34
34
  namespace Sass {
35
35
  using std::stringstream;
@@ -37,12 +37,11 @@ namespace Sass {
37
37
 
38
38
  Definition* make_native_function(Signature sig, Native_Function f, Context& ctx)
39
39
  {
40
- Parser sig_parser = Parser::from_c_str(sig, ctx, "[built-in function]");
40
+ Parser sig_parser = Parser::from_c_str(sig, ctx, ParserState("[built-in function]"));
41
41
  sig_parser.lex<Prelexer::identifier>();
42
42
  string name(Util::normalize_underscores(sig_parser.lexed));
43
43
  Parameters* params = sig_parser.parse_parameters();
44
- return new (ctx.mem) Definition("[built-in function]",
45
- Position(),
44
+ return new (ctx.mem) Definition(ParserState("[built-in function]"),
46
45
  sig,
47
46
  name,
48
47
  params,
@@ -52,7 +51,7 @@ namespace Sass {
52
51
 
53
52
  Definition* make_c_function(Signature sig, Sass_C_Function f, void* cookie, Context& ctx)
54
53
  {
55
- Parser sig_parser = Parser::from_c_str(sig, ctx, "[c function]");
54
+ Parser sig_parser = Parser::from_c_str(sig, ctx, ParserState("[c function]"));
56
55
  // allow to overload generic callback plus @warn, @error and @debug with custom functions
57
56
  sig_parser.lex < alternatives < identifier, exactly <'*'>,
58
57
  exactly < Constants::warn_kwd >,
@@ -61,8 +60,7 @@ namespace Sass {
61
60
  > >();
62
61
  string name(Util::normalize_underscores(sig_parser.lexed));
63
62
  Parameters* params = sig_parser.parse_parameters();
64
- return new (ctx.mem) Definition("[c function]",
65
- Position(),
63
+ return new (ctx.mem) Definition(ParserState("[c function]"),
66
64
  sig,
67
65
  name,
68
66
  params,
@@ -74,7 +72,7 @@ namespace Sass {
74
72
  namespace Functions {
75
73
 
76
74
  template <typename T>
77
- T* get_arg(const string& argname, Env& env, Signature sig, const string& path, Position position, Backtrace* backtrace)
75
+ T* get_arg(const string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace)
78
76
  {
79
77
  // Minimal error handling -- the expectation is that built-ins will be written correctly!
80
78
  T* val = dynamic_cast<T*>(env[argname]);
@@ -85,35 +83,35 @@ namespace Sass {
85
83
  msg += sig;
86
84
  msg += "` must be a ";
87
85
  msg += T::type_name();
88
- error(msg, path, position, backtrace);
86
+ error(msg, pstate, backtrace);
89
87
  }
90
88
  return val;
91
89
  }
92
90
 
93
- Map* get_arg_m(const string& argname, Env& env, Signature sig, const string& path, Position position, Backtrace* backtrace, Context& ctx)
91
+ Map* get_arg_m(const string& argname, Env& env, Signature sig, ParserState pstate, Backtrace* backtrace, Context& ctx)
94
92
  {
95
93
  // Minimal error handling -- the expectation is that built-ins will be written correctly!
96
94
  Map* val = dynamic_cast<Map*>(env[argname]);
97
95
  if (val) return val;
98
96
 
99
97
  List* lval = dynamic_cast<List*>(env[argname]);
100
- if (lval && lval->length() == 0) return new (ctx.mem) Map(path, position, 0);
98
+ if (lval && lval->length() == 0) return new (ctx.mem) Map(pstate, 0);
101
99
 
102
100
  // fallback on get_arg for error handling
103
- val = get_arg<Map>(argname, env, sig, path, position, backtrace);
101
+ val = get_arg<Map>(argname, env, sig, pstate, backtrace);
104
102
  return val;
105
103
  }
106
104
 
107
- Number* get_arg_r(const string& argname, Env& env, Signature sig, const string& path, Position position, double lo, double hi, Backtrace* backtrace)
105
+ Number* get_arg_r(const string& argname, Env& env, Signature sig, ParserState pstate, double lo, double hi, Backtrace* backtrace)
108
106
  {
109
107
  // Minimal error handling -- the expectation is that built-ins will be written correctly!
110
- Number* val = get_arg<Number>(argname, env, sig, path, position, backtrace);
108
+ Number* val = get_arg<Number>(argname, env, sig, pstate, backtrace);
111
109
  double v = val->value();
112
110
  if (!(lo <= v && v <= hi)) {
113
111
  stringstream msg;
114
112
  msg << "argument `" << argname << "` of `" << sig << "` must be between ";
115
113
  msg << lo << " and " << hi;
116
- error(msg.str(), path, position, backtrace);
114
+ error(msg.str(), pstate, backtrace);
117
115
  }
118
116
  return val;
119
117
  }
@@ -144,7 +142,7 @@ namespace Sass {
144
142
  // random_device degrades sharply once the entropy pool
145
143
  // is exhausted. For practical use, random_device is
146
144
  // generally only used to seed a PRNG such as mt19937.
147
- static mt19937 rand(GetSeed());
145
+ static mt19937 rand(static_cast<unsigned int>(GetSeed()));
148
146
 
149
147
  // features
150
148
  static set<string> features;
@@ -153,24 +151,30 @@ namespace Sass {
153
151
  // RGB FUNCTIONS
154
152
  ////////////////
155
153
 
154
+ inline double color_num(Number* n) {
155
+ if (n->unit() == "%") {
156
+ return std::min(std::max(n->value(), 0.0), 1.0) * 255;
157
+ } else {
158
+ return std::min(std::max(n->value(), 0.0), 255.0);
159
+ }
160
+ }
161
+
156
162
  Signature rgb_sig = "rgb($red, $green, $blue)";
157
163
  BUILT_IN(rgb)
158
164
  {
159
- return new (ctx.mem) Color(path,
160
- position,
161
- ARGR("$red", Number, 0, 255)->value(),
162
- ARGR("$green", Number, 0, 255)->value(),
163
- ARGR("$blue", Number, 0, 255)->value());
165
+ return new (ctx.mem) Color(pstate,
166
+ color_num(ARGR("$red", Number, 0, 255)),
167
+ color_num(ARGR("$green", Number, 0, 255)),
168
+ color_num(ARGR("$blue", Number, 0, 255)));
164
169
  }
165
170
 
166
171
  Signature rgba_4_sig = "rgba($red, $green, $blue, $alpha)";
167
172
  BUILT_IN(rgba_4)
168
173
  {
169
- return new (ctx.mem) Color(path,
170
- position,
171
- ARGR("$red", Number, 0, 255)->value(),
172
- ARGR("$green", Number, 0, 255)->value(),
173
- ARGR("$blue", Number, 0, 255)->value(),
174
+ return new (ctx.mem) Color(pstate,
175
+ color_num(ARGR("$red", Number, 0, 255)),
176
+ color_num(ARGR("$green", Number, 0, 255)),
177
+ color_num(ARGR("$blue", Number, 0, 255)),
174
178
  ARGR("$alpha", Number, 0, 1)->value());
175
179
  }
176
180
 
@@ -186,15 +190,15 @@ namespace Sass {
186
190
 
187
191
  Signature red_sig = "red($color)";
188
192
  BUILT_IN(red)
189
- { return new (ctx.mem) Number(path, position, ARG("$color", Color)->r()); }
193
+ { return new (ctx.mem) Number(pstate, ARG("$color", Color)->r()); }
190
194
 
191
195
  Signature green_sig = "green($color)";
192
196
  BUILT_IN(green)
193
- { return new (ctx.mem) Number(path, position, ARG("$color", Color)->g()); }
197
+ { return new (ctx.mem) Number(pstate, ARG("$color", Color)->g()); }
194
198
 
195
199
  Signature blue_sig = "blue($color)";
196
200
  BUILT_IN(blue)
197
- { return new (ctx.mem) Number(path, position, ARG("$color", Color)->b()); }
201
+ { return new (ctx.mem) Number(pstate, ARG("$color", Color)->b()); }
198
202
 
199
203
  Signature mix_sig = "mix($color-1, $color-2, $weight: 50%)";
200
204
  BUILT_IN(mix)
@@ -210,8 +214,7 @@ namespace Sass {
210
214
  double w1 = (((w * a == -1) ? w : (w + a)/(1 + w*a)) + 1)/2.0;
211
215
  double w2 = 1 - w1;
212
216
 
213
- return new (ctx.mem) Color(path,
214
- position,
217
+ return new (ctx.mem) Color(pstate,
215
218
  std::floor(w1*color1->r() + w2*color2->r()),
216
219
  std::floor(w1*color1->g() + w2*color2->g()),
217
220
  std::floor(w1*color1->b() + w2*color2->b()),
@@ -266,7 +269,7 @@ namespace Sass {
266
269
  return m1;
267
270
  }
268
271
 
269
- Color* hsla_impl(double h, double s, double l, double a, Context& ctx, const string& path, Position position)
272
+ Color* hsla_impl(double h, double s, double l, double a, Context& ctx, ParserState pstate)
270
273
  {
271
274
  h /= 360.0;
272
275
  s /= 100.0;
@@ -282,7 +285,7 @@ namespace Sass {
282
285
  double g = (h_to_rgb(m1, m2, h) * 255.0);
283
286
  double b = (h_to_rgb(m1, m2, h-1.0/3.0) * 255.0);
284
287
 
285
- return new (ctx.mem) Color(path, position, r, g, b, a);
288
+ return new (ctx.mem) Color(pstate, r, g, b, a);
286
289
  }
287
290
 
288
291
  Signature hsl_sig = "hsl($hue, $saturation, $lightness)";
@@ -293,8 +296,7 @@ namespace Sass {
293
296
  ARGR("$lightness", Number, 0, 100)->value(),
294
297
  1.0,
295
298
  ctx,
296
- path,
297
- position);
299
+ pstate);
298
300
  }
299
301
 
300
302
  Signature hsla_sig = "hsla($hue, $saturation, $lightness, $alpha)";
@@ -305,8 +307,7 @@ namespace Sass {
305
307
  ARGR("$lightness", Number, 0, 100)->value(),
306
308
  ARGR("$alpha", Number, 0, 1)->value(),
307
309
  ctx,
308
- path,
309
- position);
310
+ pstate);
310
311
  }
311
312
 
312
313
  Signature hue_sig = "hue($color)";
@@ -316,7 +317,7 @@ namespace Sass {
316
317
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
317
318
  rgb_color->g(),
318
319
  rgb_color->b());
319
- return new (ctx.mem) Number(path, position, hsl_color.h, "deg");
320
+ return new (ctx.mem) Number(pstate, hsl_color.h, "deg");
320
321
  }
321
322
 
322
323
  Signature saturation_sig = "saturation($color)";
@@ -326,7 +327,7 @@ namespace Sass {
326
327
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
327
328
  rgb_color->g(),
328
329
  rgb_color->b());
329
- return new (ctx.mem) Number(path, position, hsl_color.s, "%");
330
+ return new (ctx.mem) Number(pstate, hsl_color.s, "%");
330
331
  }
331
332
 
332
333
  Signature lightness_sig = "lightness($color)";
@@ -336,7 +337,7 @@ namespace Sass {
336
337
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
337
338
  rgb_color->g(),
338
339
  rgb_color->b());
339
- return new (ctx.mem) Number(path, position, hsl_color.l, "%");
340
+ return new (ctx.mem) Number(pstate, hsl_color.l, "%");
340
341
  }
341
342
 
342
343
  Signature adjust_hue_sig = "adjust-hue($color, $degrees)";
@@ -352,8 +353,7 @@ namespace Sass {
352
353
  hsl_color.l,
353
354
  rgb_color->a(),
354
355
  ctx,
355
- path,
356
- position);
356
+ pstate);
357
357
  }
358
358
 
359
359
  Signature lighten_sig = "lighten($color, $amount)";
@@ -375,8 +375,7 @@ namespace Sass {
375
375
  hslcolorL + amount->value(),
376
376
  rgb_color->a(),
377
377
  ctx,
378
- path,
379
- position);
378
+ pstate);
380
379
  }
381
380
 
382
381
  Signature darken_sig = "darken($color, $amount)";
@@ -399,8 +398,7 @@ namespace Sass {
399
398
  hslcolorL - amount->value(),
400
399
  rgb_color->a(),
401
400
  ctx,
402
- path,
403
- position);
401
+ pstate);
404
402
  }
405
403
 
406
404
  Signature saturate_sig = "saturate($color, $amount: false)";
@@ -410,7 +408,7 @@ namespace Sass {
410
408
  Number* amount = dynamic_cast<Number*>(env["$amount"]);
411
409
  if (!amount) {
412
410
  To_String to_string(&ctx);
413
- return new (ctx.mem) String_Constant(path, position, "saturate(" + env["$color"]->perform(&to_string) + ")");
411
+ return new (ctx.mem) String_Constant(pstate, "saturate(" + env["$color"]->perform(&to_string) + ")");
414
412
  }
415
413
 
416
414
  ARGR("$amount", Number, 0, 100);
@@ -418,20 +416,23 @@ namespace Sass {
418
416
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
419
417
  rgb_color->g(),
420
418
  rgb_color->b());
421
- //Check saturation is not negative before saturate it
422
- double hslcolorS = hsl_color.s;
419
+
420
+ double hslcolorS = hsl_color.s + amount->value();
421
+
422
+ // Saturation cannot be below 0 or above 100
423
423
  if (hslcolorS < 0) {
424
424
  hslcolorS = 0;
425
425
  }
426
-
426
+ if (hslcolorS > 100) {
427
+ hslcolorS = 100;
428
+ }
427
429
 
428
430
  return hsla_impl(hsl_color.h,
429
- hslcolorS + amount->value(),
431
+ hslcolorS,
430
432
  hsl_color.l,
431
433
  rgb_color->a(),
432
434
  ctx,
433
- path,
434
- position);
435
+ pstate);
435
436
  }
436
437
 
437
438
  Signature desaturate_sig = "desaturate($color, $amount)";
@@ -442,19 +443,23 @@ namespace Sass {
442
443
  HSL hsl_color = rgb_to_hsl(rgb_color->r(),
443
444
  rgb_color->g(),
444
445
  rgb_color->b());
445
- //Check saturation is not over 100 before desaturate it
446
- double hslcolorS = hsl_color.s;
446
+
447
+ double hslcolorS = hsl_color.s - amount->value();
448
+
449
+ // Saturation cannot be below 0 or above 100
450
+ if (hslcolorS <= 0) {
451
+ hslcolorS = 0;
452
+ }
447
453
  if (hslcolorS > 100) {
448
454
  hslcolorS = 100;
449
455
  }
450
456
 
451
457
  return hsla_impl(hsl_color.h,
452
- hslcolorS - amount->value(),
458
+ hslcolorS,
453
459
  hsl_color.l,
454
460
  rgb_color->a(),
455
461
  ctx,
456
- path,
457
- position);
462
+ pstate);
458
463
  }
459
464
 
460
465
  Signature grayscale_sig = "grayscale($color)";
@@ -464,7 +469,7 @@ namespace Sass {
464
469
  Number* amount = dynamic_cast<Number*>(env["$color"]);
465
470
  if (amount) {
466
471
  To_String to_string(&ctx);
467
- return new (ctx.mem) String_Constant(path, position, "grayscale(" + amount->perform(&to_string) + ")");
472
+ return new (ctx.mem) String_Constant(pstate, "grayscale(" + amount->perform(&to_string) + ")");
468
473
  }
469
474
 
470
475
  Color* rgb_color = ARG("$color", Color);
@@ -476,8 +481,7 @@ namespace Sass {
476
481
  hsl_color.l,
477
482
  rgb_color->a(),
478
483
  ctx,
479
- path,
480
- position);
484
+ pstate);
481
485
  }
482
486
 
483
487
  Signature complement_sig = "complement($color)";
@@ -492,8 +496,7 @@ namespace Sass {
492
496
  hsl_color.l,
493
497
  rgb_color->a(),
494
498
  ctx,
495
- path,
496
- position);
499
+ pstate);
497
500
  }
498
501
 
499
502
  Signature invert_sig = "invert($color)";
@@ -503,12 +506,11 @@ namespace Sass {
503
506
  Number* amount = dynamic_cast<Number*>(env["$color"]);
504
507
  if (amount) {
505
508
  To_String to_string(&ctx);
506
- return new (ctx.mem) String_Constant(path, position, "invert(" + amount->perform(&to_string) + ")");
509
+ return new (ctx.mem) String_Constant(pstate, "invert(" + amount->perform(&to_string) + ")");
507
510
  }
508
511
 
509
512
  Color* rgb_color = ARG("$color", Color);
510
- return new (ctx.mem) Color(path,
511
- position,
513
+ return new (ctx.mem) Color(pstate,
512
514
  255 - rgb_color->r(),
513
515
  255 - rgb_color->g(),
514
516
  255 - rgb_color->b(),
@@ -524,17 +526,17 @@ namespace Sass {
524
526
  {
525
527
  String_Constant* ie_kwd = dynamic_cast<String_Constant*>(env["$color"]);
526
528
  if (ie_kwd) {
527
- return new (ctx.mem) String_Constant(path, position, "alpha(" + ie_kwd->value() + ")");
529
+ return new (ctx.mem) String_Constant(pstate, "alpha(" + ie_kwd->value() + ")");
528
530
  }
529
531
 
530
532
  // CSS3 filter function overload: pass literal through directly
531
533
  Number* amount = dynamic_cast<Number*>(env["$color"]);
532
534
  if (amount) {
533
535
  To_String to_string(&ctx);
534
- return new (ctx.mem) String_Constant(path, position, "opacity(" + amount->perform(&to_string) + ")");
536
+ return new (ctx.mem) String_Constant(pstate, "opacity(" + amount->perform(&to_string) + ")");
535
537
  }
536
538
 
537
- return new (ctx.mem) Number(path, position, ARG("$color", Color)->a());
539
+ return new (ctx.mem) Number(pstate, ARG("$color", Color)->a());
538
540
  }
539
541
 
540
542
  Signature opacify_sig = "opacify($color, $amount)";
@@ -542,13 +544,13 @@ namespace Sass {
542
544
  BUILT_IN(opacify)
543
545
  {
544
546
  Color* color = ARG("$color", Color);
545
- double alpha = color->a() + ARGR("$amount", Number, 0, 1)->value();
546
- return new (ctx.mem) Color(path,
547
- position,
547
+ double amount = ARGR("$amount", Number, 0, 1)->value();
548
+ double alpha = std::min(color->a() + amount, 1.0);
549
+ return new (ctx.mem) Color(pstate,
548
550
  color->r(),
549
551
  color->g(),
550
552
  color->b(),
551
- alpha > 1.0 ? 1.0 : alpha);
553
+ alpha);
552
554
  }
553
555
 
554
556
  Signature transparentize_sig = "transparentize($color, $amount)";
@@ -556,13 +558,13 @@ namespace Sass {
556
558
  BUILT_IN(transparentize)
557
559
  {
558
560
  Color* color = ARG("$color", Color);
559
- double alpha = color->a() - ARGR("$amount", Number, 0, 1)->value();
560
- return new (ctx.mem) Color(path,
561
- position,
561
+ double amount = ARGR("$amount", Number, 0, 1)->value();
562
+ double alpha = std::max(color->a() - amount, 0.0);
563
+ return new (ctx.mem) Color(pstate,
562
564
  color->r(),
563
565
  color->g(),
564
566
  color->b(),
565
- alpha < 0.0 ? 0.0 : alpha);
567
+ alpha);
566
568
  }
567
569
 
568
570
  ////////////////////////
@@ -585,11 +587,10 @@ namespace Sass {
585
587
  bool hsl = h || s || l;
586
588
 
587
589
  if (rgb && hsl) {
588
- error("cannot specify both RGB and HSL values for `adjust-color`", path, position);
590
+ error("cannot specify both RGB and HSL values for `adjust-color`", pstate);
589
591
  }
590
592
  if (rgb) {
591
- return new (ctx.mem) Color(path,
592
- position,
593
+ return new (ctx.mem) Color(pstate,
593
594
  color->r() + (r ? r->value() : 0),
594
595
  color->g() + (g ? g->value() : 0),
595
596
  color->b() + (b ? b->value() : 0),
@@ -602,18 +603,16 @@ namespace Sass {
602
603
  hsl_struct.l + (l ? l->value() : 0),
603
604
  color->a() + (a ? a->value() : 0),
604
605
  ctx,
605
- path,
606
- position);
606
+ pstate);
607
607
  }
608
608
  if (a) {
609
- return new (ctx.mem) Color(path,
610
- position,
609
+ return new (ctx.mem) Color(pstate,
611
610
  color->r(),
612
611
  color->g(),
613
612
  color->b(),
614
613
  color->a() + (a ? a->value() : 0));
615
614
  }
616
- error("not enough arguments for `adjust-color`", path, position);
615
+ error("not enough arguments for `adjust-color`", pstate);
617
616
  // unreachable
618
617
  return color;
619
618
  }
@@ -634,15 +633,14 @@ namespace Sass {
634
633
  bool hsl = h || s || l;
635
634
 
636
635
  if (rgb && hsl) {
637
- error("cannot specify both RGB and HSL values for `scale-color`", path, position);
636
+ error("cannot specify both RGB and HSL values for `scale-color`", pstate);
638
637
  }
639
638
  if (rgb) {
640
639
  double rscale = (r ? ARGR("$red", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
641
640
  double gscale = (g ? ARGR("$green", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
642
641
  double bscale = (b ? ARGR("$blue", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
643
642
  double ascale = (a ? ARGR("$alpha", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
644
- return new (ctx.mem) Color(path,
645
- position,
643
+ return new (ctx.mem) Color(pstate,
646
644
  color->r() + rscale * (rscale > 0.0 ? 255 - color->r() : color->r()),
647
645
  color->g() + gscale * (gscale > 0.0 ? 255 - color->g() : color->g()),
648
646
  color->b() + bscale * (bscale > 0.0 ? 255 - color->b() : color->b()),
@@ -657,19 +655,18 @@ namespace Sass {
657
655
  hsl_struct.h += hscale * (hscale > 0.0 ? 360.0 - hsl_struct.h : hsl_struct.h);
658
656
  hsl_struct.s += sscale * (sscale > 0.0 ? 100.0 - hsl_struct.s : hsl_struct.s);
659
657
  hsl_struct.l += lscale * (lscale > 0.0 ? 100.0 - hsl_struct.l : hsl_struct.l);
660
- double alpha = color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->r());
661
- return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, path, position);
658
+ double alpha = color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a());
659
+ return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate);
662
660
  }
663
661
  if (a) {
664
662
  double ascale = (a ? ARGR("$alpha", Number, -100.0, 100.0)->value() : 0.0) / 100.0;
665
- return new (ctx.mem) Color(path,
666
- position,
663
+ return new (ctx.mem) Color(pstate,
667
664
  color->r(),
668
665
  color->g(),
669
666
  color->b(),
670
667
  color->a() + ascale * (ascale > 0.0 ? 1.0 - color->a() : color->a()));
671
668
  }
672
- error("not enough arguments for `scale-color`", path, position);
669
+ error("not enough arguments for `scale-color`", pstate);
673
670
  // unreachable
674
671
  return color;
675
672
  }
@@ -690,11 +687,10 @@ namespace Sass {
690
687
  bool hsl = h || s || l;
691
688
 
692
689
  if (rgb && hsl) {
693
- error("cannot specify both RGB and HSL values for `change-color`", path, position);
690
+ error("cannot specify both RGB and HSL values for `change-color`", pstate);
694
691
  }
695
692
  if (rgb) {
696
- return new (ctx.mem) Color(path,
697
- position,
693
+ return new (ctx.mem) Color(pstate,
698
694
  r ? ARGR("$red", Number, 0, 255)->value() : color->r(),
699
695
  g ? ARGR("$green", Number, 0, 255)->value() : color->g(),
700
696
  b ? ARGR("$blue", Number, 0, 255)->value() : color->b(),
@@ -706,18 +702,17 @@ namespace Sass {
706
702
  if (s) hsl_struct.s = ARGR("$saturation", Number, 0, 100)->value();
707
703
  if (l) hsl_struct.l = ARGR("$lightness", Number, 0, 100)->value();
708
704
  double alpha = a ? ARGR("$alpha", Number, 0, 1.0)->value() : color->a();
709
- return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, path, position);
705
+ return hsla_impl(hsl_struct.h, hsl_struct.s, hsl_struct.l, alpha, ctx, pstate);
710
706
  }
711
707
  if (a) {
712
708
  double alpha = a ? ARGR("$alpha", Number, 0, 1.0)->value() : color->a();
713
- return new (ctx.mem) Color(path,
714
- position,
709
+ return new (ctx.mem) Color(pstate,
715
710
  color->r(),
716
711
  color->g(),
717
712
  color->b(),
718
713
  alpha);
719
714
  }
720
- error("not enough arguments for `change-color`", path, position);
715
+ error("not enough arguments for `change-color`", pstate);
721
716
  // unreachable
722
717
  return color;
723
718
  }
@@ -749,7 +744,7 @@ namespace Sass {
749
744
  for (size_t i = 0, L = result.length(); i < L; ++i) {
750
745
  result[i] = std::toupper(result[i]);
751
746
  }
752
- return new (ctx.mem) String_Constant(path, position, result);
747
+ return new (ctx.mem) String_Constant(pstate, result);
753
748
  }
754
749
 
755
750
  ///////////////////
@@ -759,24 +754,24 @@ namespace Sass {
759
754
  Signature unquote_sig = "unquote($string)";
760
755
  BUILT_IN(sass_unquote)
761
756
  {
762
- To_String to_string;
757
+ To_String to_string(&ctx);
763
758
  AST_Node* arg = env["$string"];
764
- string org(arg->perform(&to_string));
765
- string str(unquote(org));
766
- String_Constant* result = new (ctx.mem) String_Constant(path, position, str);
767
- // remember if the string was quoted (color tokens)
768
- if (org[0] != str[0]) result->needs_unquoting(true);
769
- result->is_delayed(true);
770
- return result;
759
+ if (String_Quoted* string_quoted = dynamic_cast<String_Quoted*>(arg)) {
760
+ String_Constant* result = new (ctx.mem) String_Constant(pstate, string_quoted->value());
761
+ // remember if the string was quoted (color tokens)
762
+ result->sass_fix_1291(string_quoted->quote_mark() != 0);
763
+ return result;
764
+ }
765
+ return new (ctx.mem) String_Constant(pstate, string(arg->perform(&to_string)));
771
766
  }
772
767
 
773
768
  Signature quote_sig = "quote($string)";
774
769
  BUILT_IN(sass_quote)
775
770
  {
776
- To_String to_string;
771
+ To_String to_string(&ctx);
777
772
  AST_Node* arg = env["$string"];
778
773
  string str(quote(arg->perform(&to_string), String_Constant::double_quote()));
779
- String_Constant* result = new (ctx.mem) String_Constant(path, position, str);
774
+ String_Constant* result = new (ctx.mem) String_Constant(pstate, str);
780
775
  result->is_delayed(true);
781
776
  return result;
782
777
  }
@@ -788,33 +783,24 @@ namespace Sass {
788
783
  size_t len = string::npos;
789
784
  try {
790
785
  String_Constant* s = ARG("$string", String_Constant);
791
- string str = s->value();
792
- size_t length_of_s = str.size();
793
- size_t i = 0;
794
-
795
- if (s->is_quoted()) {
796
- ++i;
797
- --length_of_s;
798
- }
799
-
800
- len = UTF_8::code_point_count(str, i, length_of_s);
786
+ len = UTF_8::code_point_count(s->value(), 0, s->value().size());
801
787
 
802
788
  }
803
789
  catch (utf8::invalid_code_point) {
804
790
  string msg("utf8::invalid_code_point");
805
- error(msg, path, position, backtrace);
791
+ error(msg, pstate, backtrace);
806
792
  }
807
793
  catch (utf8::not_enough_room) {
808
794
  string msg("utf8::not_enough_room");
809
- error(msg, path, position, backtrace);
795
+ error(msg, pstate, backtrace);
810
796
  }
811
797
  catch (utf8::invalid_utf8) {
812
798
  string msg("utf8::invalid_utf8");
813
- error(msg, path, position, backtrace);
799
+ error(msg, pstate, backtrace);
814
800
  }
815
801
  catch (...) { throw; }
816
802
  // return something even if we had an error (-1)
817
- return new (ctx.mem) Number(path, position, len);
803
+ return new (ctx.mem) Number(pstate, len);
818
804
  }
819
805
 
820
806
  Signature str_insert_sig = "str-insert($string, $insert, $index)";
@@ -824,7 +810,6 @@ namespace Sass {
824
810
  try {
825
811
  String_Constant* s = ARG("$string", String_Constant);
826
812
  str = s->value();
827
- char quotemark = s->quote_mark();
828
813
  str = unquote(str);
829
814
  String_Constant* i = ARG("$insert", String_Constant);
830
815
  string ins = i->value();
@@ -835,7 +820,7 @@ namespace Sass {
835
820
 
836
821
  if (index > 0 && index <= len) {
837
822
  // positive and within string length
838
- str.insert(UTF_8::offset_at_position(str, index - 1), ins);
823
+ str.insert(UTF_8::offset_at_position(str, static_cast<size_t>(index) - 1), ins);
839
824
  }
840
825
  else if (index > len) {
841
826
  // positive and past string length
@@ -847,31 +832,31 @@ namespace Sass {
847
832
  else if (std::abs(index) <= len) {
848
833
  // negative and within string length
849
834
  index += len + 1;
850
- str.insert(UTF_8::offset_at_position(str, index), ins);
835
+ str.insert(UTF_8::offset_at_position(str, static_cast<size_t>(index)), ins);
851
836
  }
852
837
  else {
853
838
  // negative and past string length
854
839
  str = ins + str;
855
840
  }
856
841
 
857
- if (quotemark) {
858
- str = quote(str, String_Constant::double_quote());
842
+ if (String_Quoted* ss = dynamic_cast<String_Quoted*>(s)) {
843
+ if (ss->quote_mark()) str = quote(str);
859
844
  }
860
845
  }
861
846
  catch (utf8::invalid_code_point) {
862
847
  string msg("utf8::invalid_code_point");
863
- error(msg, path, position, backtrace);
848
+ error(msg, pstate, backtrace);
864
849
  }
865
850
  catch (utf8::not_enough_room) {
866
851
  string msg("utf8::not_enough_room");
867
- error(msg, path, position, backtrace);
852
+ error(msg, pstate, backtrace);
868
853
  }
869
854
  catch (utf8::invalid_utf8) {
870
855
  string msg("utf8::invalid_utf8");
871
- error(msg, path, position, backtrace);
856
+ error(msg, pstate, backtrace);
872
857
  }
873
858
  catch (...) { throw; }
874
- return new (ctx.mem) String_Constant(path, position, str);
859
+ return new (ctx.mem) String_Constant(pstate, str);
875
860
  }
876
861
 
877
862
  Signature str_index_sig = "str-index($string, $substring)";
@@ -888,25 +873,25 @@ namespace Sass {
888
873
 
889
874
  size_t c_index = str.find(substr);
890
875
  if(c_index == string::npos) {
891
- return new (ctx.mem) Null(path, position);
876
+ return new (ctx.mem) Null(pstate);
892
877
  }
893
878
  index = UTF_8::code_point_count(str, 0, c_index) + 1;
894
879
  }
895
880
  catch (utf8::invalid_code_point) {
896
881
  string msg("utf8::invalid_code_point");
897
- error(msg, path, position, backtrace);
882
+ error(msg, pstate, backtrace);
898
883
  }
899
884
  catch (utf8::not_enough_room) {
900
885
  string msg("utf8::not_enough_room");
901
- error(msg, path, position, backtrace);
886
+ error(msg, pstate, backtrace);
902
887
  }
903
888
  catch (utf8::invalid_utf8) {
904
889
  string msg("utf8::invalid_utf8");
905
- error(msg, path, position, backtrace);
890
+ error(msg, pstate, backtrace);
906
891
  }
907
892
  catch (...) { throw; }
908
893
  // return something even if we had an error (-1)
909
- return new (ctx.mem) Number(path, position, index);
894
+ return new (ctx.mem) Number(pstate, index);
910
895
  }
911
896
 
912
897
  Signature str_slice_sig = "str-slice($string, $start-at, $end-at:-1)";
@@ -918,39 +903,44 @@ namespace Sass {
918
903
  Number* n = ARG("$start-at", Number);
919
904
  Number* m = ARG("$end-at", Number);
920
905
 
921
- string str = s->value();
922
- char quotemark = s->quote_mark();
923
- str = unquote(str);
906
+ string str = unquote(s->value());
924
907
 
925
908
  // normalize into 0-based indices
926
- size_t start = UTF_8::offset_at_position(str, UTF_8::normalize_index(n->value(), UTF_8::code_point_count(str)));
927
- size_t end = UTF_8::offset_at_position(str, UTF_8::normalize_index(m->value(), UTF_8::code_point_count(str)));
909
+ size_t start = UTF_8::offset_at_position(str, UTF_8::normalize_index(static_cast<int>(n->value()), UTF_8::code_point_count(str)));
910
+ size_t end = UTF_8::offset_at_position(str, UTF_8::normalize_index(static_cast<int>(m->value()), UTF_8::code_point_count(str)));
928
911
 
929
912
  // `str-slice` should always return an empty string when $end-at == 0
930
913
  // `normalize_index` normalizes 1 -> 0 so we need to check the original value
931
- if(start == end && m->value() > 0) {
914
+ if(m->value() == 0) {
915
+ if (String_Quoted* ss = dynamic_cast<String_Quoted*>(s)) {
916
+ if(!ss->quote_mark()) return new (ctx.mem) Null(pstate);
917
+ } else {
918
+ return new (ctx.mem) Null(pstate);
919
+ }
920
+ newstr = "";
921
+ } else if(start == end && m->value() != 0) {
932
922
  newstr = str.substr(start, 1);
933
923
  } else if(end > start) {
934
924
  newstr = str.substr(start, end - start + UTF_8::code_point_size_at_offset(str, end));
935
925
  }
936
- if(quotemark) {
937
- newstr = quote(newstr, String_Constant::double_quote());
926
+ if (String_Quoted* ss = dynamic_cast<String_Quoted*>(s)) {
927
+ if(ss->quote_mark()) newstr = quote(newstr);
938
928
  }
939
929
  }
940
930
  catch (utf8::invalid_code_point) {
941
931
  string msg("utf8::invalid_code_point");
942
- error(msg, path, position, backtrace);
932
+ error(msg, pstate, backtrace);
943
933
  }
944
934
  catch (utf8::not_enough_room) {
945
935
  string msg("utf8::not_enough_room");
946
- error(msg, path, position, backtrace);
936
+ error(msg, pstate, backtrace);
947
937
  }
948
938
  catch (utf8::invalid_utf8) {
949
939
  string msg("utf8::invalid_utf8");
950
- error(msg, path, position, backtrace);
940
+ error(msg, pstate, backtrace);
951
941
  }
952
942
  catch (...) { throw; }
953
- return new (ctx.mem) String_Constant(path, position, newstr);
943
+ return new (ctx.mem) String_Constant(pstate, newstr);
954
944
  }
955
945
 
956
946
  Signature to_upper_case_sig = "to-upper-case($string)";
@@ -965,7 +955,10 @@ namespace Sass {
965
955
  }
966
956
  }
967
957
 
968
- return new (ctx.mem) String_Constant(path, position, str);
958
+ if (String_Quoted* ss = dynamic_cast<String_Quoted*>(s)) {
959
+ str = ss->quote_mark() ? quote(str) : str;
960
+ }
961
+ return new (ctx.mem) String_Constant(pstate, str);
969
962
  }
970
963
 
971
964
  Signature to_lower_case_sig = "to-lower-case($string)";
@@ -980,89 +973,90 @@ namespace Sass {
980
973
  }
981
974
  }
982
975
 
983
- return new (ctx.mem) String_Constant(path, position, str);
976
+ if (String_Quoted* ss = dynamic_cast<String_Quoted*>(s)) {
977
+ str = ss->quote_mark() ? quote(str, '"') : str;
978
+ }
979
+ return new (ctx.mem) String_Constant(pstate, str);
984
980
  }
985
981
 
986
982
  ///////////////////
987
983
  // NUMBER FUNCTIONS
988
984
  ///////////////////
989
985
 
990
- Signature percentage_sig = "percentage($value)";
986
+ Signature percentage_sig = "percentage($number)";
991
987
  BUILT_IN(percentage)
992
988
  {
993
- Number* n = ARG("$value", Number);
994
- if (!n->is_unitless()) error("argument $value of `" + string(sig) + "` must be unitless", path, position);
995
- return new (ctx.mem) Number(path, position, n->value() * 100, "%");
989
+ Number* n = ARG("$number", Number);
990
+ if (!n->is_unitless()) error("argument $number of `" + string(sig) + "` must be unitless", pstate);
991
+ return new (ctx.mem) Number(pstate, n->value() * 100, "%");
996
992
  }
997
993
 
998
- Signature round_sig = "round($value)";
994
+ Signature round_sig = "round($number)";
999
995
  BUILT_IN(round)
1000
996
  {
1001
- Number* n = ARG("$value", Number);
997
+ Number* n = ARG("$number", Number);
1002
998
  Number* r = new (ctx.mem) Number(*n);
1003
- r->path(path);
1004
- r->position(position);
999
+ r->pstate(pstate);
1005
1000
  r->value(std::floor(r->value() + 0.5));
1006
1001
  return r;
1007
1002
  }
1008
1003
 
1009
- Signature ceil_sig = "ceil($value)";
1004
+ Signature ceil_sig = "ceil($number)";
1010
1005
  BUILT_IN(ceil)
1011
1006
  {
1012
- Number* n = ARG("$value", Number);
1007
+ Number* n = ARG("$number", Number);
1013
1008
  Number* r = new (ctx.mem) Number(*n);
1014
- r->path(path);
1015
- r->position(position);
1009
+ r->pstate(pstate);
1016
1010
  r->value(std::ceil(r->value()));
1017
1011
  return r;
1018
1012
  }
1019
1013
 
1020
- Signature floor_sig = "floor($value)";
1014
+ Signature floor_sig = "floor($number)";
1021
1015
  BUILT_IN(floor)
1022
1016
  {
1023
- Number* n = ARG("$value", Number);
1017
+ Number* n = ARG("$number", Number);
1024
1018
  Number* r = new (ctx.mem) Number(*n);
1025
- r->path(path);
1026
- r->position(position);
1019
+ r->pstate(pstate);
1027
1020
  r->value(std::floor(r->value()));
1028
1021
  return r;
1029
1022
  }
1030
1023
 
1031
- Signature abs_sig = "abs($value)";
1024
+ Signature abs_sig = "abs($number)";
1032
1025
  BUILT_IN(abs)
1033
1026
  {
1034
- Number* n = ARG("$value", Number);
1027
+ Number* n = ARG("$number", Number);
1035
1028
  Number* r = new (ctx.mem) Number(*n);
1036
- r->path(path);
1037
- r->position(position);
1029
+ r->pstate(pstate);
1038
1030
  r->value(std::abs(r->value()));
1039
1031
  return r;
1040
1032
  }
1041
1033
 
1042
- Signature min_sig = "min($x1, $x2...)";
1034
+ Signature min_sig = "min($numbers...)";
1043
1035
  BUILT_IN(min)
1044
1036
  {
1045
- Number* x1 = ARG("$x1", Number);
1046
- List* arglist = ARG("$x2", List);
1047
- Number* least = x1;
1037
+ List* arglist = ARG("$numbers", List);
1038
+ Number* least = 0;
1048
1039
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1049
1040
  Number* xi = dynamic_cast<Number*>(arglist->value_at_index(i));
1050
- if (!xi) error("`" + string(sig) + "` only takes numeric arguments", path, position);
1051
- if (lt(xi, least, ctx)) least = xi;
1041
+ if (least) {
1042
+ if (!xi) error("`" + string(sig) + "` only takes numeric arguments", pstate);
1043
+ if (lt(xi, least, ctx)) least = xi;
1044
+ } else least = xi;
1052
1045
  }
1053
1046
  return least;
1054
1047
  }
1055
1048
 
1056
- Signature max_sig = "max($x1, $x2...)";
1049
+ Signature max_sig = "max($numbers...)";
1057
1050
  BUILT_IN(max)
1058
1051
  {
1059
- Number* x1 = ARG("$x1", Number);
1060
- List* arglist = ARG("$x2", List);
1061
- Number* greatest = x1;
1052
+ List* arglist = ARG("$numbers", List);
1053
+ Number* greatest = 0;
1062
1054
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1063
1055
  Number* xi = dynamic_cast<Number*>(arglist->value_at_index(i));
1064
- if (!xi) error("`" + string(sig) + "` only takes numeric arguments", path, position);
1065
- if (lt(greatest, xi, ctx)) greatest = xi;
1056
+ if (greatest) {
1057
+ if (!xi) error("`" + string(sig) + "` only takes numeric arguments", pstate);
1058
+ if (lt(greatest, xi, ctx)) greatest = xi;
1059
+ } else greatest = xi;
1066
1060
  }
1067
1061
  return greatest;
1068
1062
  }
@@ -1071,16 +1065,16 @@ namespace Sass {
1071
1065
  BUILT_IN(random)
1072
1066
  {
1073
1067
  Number* l = dynamic_cast<Number*>(env["$limit"]);
1074
- if (l && trunc(l->value()) != l->value()) error("argument $limit of `" + string(sig) + "` must be an integer", path, position);
1068
+ if (l && trunc(l->value()) != l->value()) error("argument $limit of `" + string(sig) + "` must be an integer", pstate);
1075
1069
  if (l) {
1076
1070
  uniform_real_distribution<> distributor(1, l->value() + 1);
1077
- uint_fast32_t distributed = distributor(rand);
1078
- return new (ctx.mem) Number(path, position, (double)distributed);
1071
+ uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
1072
+ return new (ctx.mem) Number(pstate, (double)distributed);
1079
1073
  }
1080
1074
  else {
1081
1075
  uniform_real_distribution<> distributor(0, 1);
1082
- uint_fast32_t distributed = distributor(rand);
1083
- return new (ctx.mem) Number(path, position, trunc(distributed));
1076
+ uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
1077
+ return new (ctx.mem) Number(pstate, trunc(distributed));
1084
1078
  }
1085
1079
  }
1086
1080
 
@@ -1094,14 +1088,12 @@ namespace Sass {
1094
1088
  Expression* v = ARG("$list", Expression);
1095
1089
  if (v->concrete_type() == Expression::MAP) {
1096
1090
  Map* map = dynamic_cast<Map*>(env["$list"]);
1097
- return new (ctx.mem) Number(path,
1098
- position,
1091
+ return new (ctx.mem) Number(pstate,
1099
1092
  map ? map->length() : 1);
1100
1093
  }
1101
1094
 
1102
1095
  List* list = dynamic_cast<List*>(env["$list"]);
1103
- return new (ctx.mem) Number(path,
1104
- position,
1096
+ return new (ctx.mem) Number(pstate,
1105
1097
  list ? list->length() : 1);
1106
1098
  }
1107
1099
 
@@ -1111,26 +1103,26 @@ namespace Sass {
1111
1103
  Map* m = dynamic_cast<Map*>(env["$list"]);
1112
1104
  List* l = dynamic_cast<List*>(env["$list"]);
1113
1105
  Number* n = ARG("$n", Number);
1114
- if (n->value() == 0) error("argument `$n` of `" + string(sig) + "` must be non-zero", path, position);
1106
+ if (n->value() == 0) error("argument `$n` of `" + string(sig) + "` must be non-zero", pstate);
1115
1107
  // if the argument isn't a list, then wrap it in a singleton list
1116
1108
  if (!m && !l) {
1117
- l = new (ctx.mem) List(path, position, 1);
1109
+ l = new (ctx.mem) List(pstate, 1);
1118
1110
  *l << ARG("$list", Expression);
1119
1111
  }
1120
1112
  size_t len = m ? m->length() : l->length();
1121
1113
  bool empty = m ? m->empty() : l->empty();
1122
- if (empty) error("argument `$list` of `" + string(sig) + "` must not be empty", path, position);
1114
+ if (empty) error("argument `$list` of `" + string(sig) + "` must not be empty", pstate);
1123
1115
  double index = std::floor(n->value() < 0 ? len + n->value() : n->value() - 1);
1124
- if (index < 0 || index > len - 1) error("index out of bounds for `" + string(sig) + "`", path, position);
1116
+ if (index < 0 || index > len - 1) error("index out of bounds for `" + string(sig) + "`", pstate);
1125
1117
 
1126
1118
  if (m) {
1127
- l = new (ctx.mem) List(path, position, 1);
1128
- *l << m->keys()[index];
1129
- *l << m->at(m->keys()[index]);
1119
+ l = new (ctx.mem) List(pstate, 1);
1120
+ *l << m->keys()[static_cast<unsigned int>(index)];
1121
+ *l << m->at(m->keys()[static_cast<unsigned int>(index)]);
1130
1122
  return l;
1131
1123
  }
1132
1124
  else {
1133
- return l->value_at_index(index);
1125
+ return l->value_at_index(static_cast<int>(index));
1134
1126
  }
1135
1127
  }
1136
1128
 
@@ -1141,13 +1133,13 @@ namespace Sass {
1141
1133
  Number* n = ARG("$n", Number);
1142
1134
  Expression* v = ARG("$value", Expression);
1143
1135
  if (!l) {
1144
- l = new (ctx.mem) List(path, position, 1);
1136
+ l = new (ctx.mem) List(pstate, 1);
1145
1137
  *l << ARG("$list", Expression);
1146
1138
  }
1147
- if (l->empty()) error("argument `$list` of `" + string(sig) + "` must not be empty", path, position);
1139
+ if (l->empty()) error("argument `$list` of `" + string(sig) + "` must not be empty", pstate);
1148
1140
  double index = std::floor(n->value() < 0 ? l->length() + n->value() : n->value() - 1);
1149
- if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + string(sig) + "`", path, position);
1150
- List* result = new (ctx.mem) List(path, position, l->length(), l->separator());
1141
+ if (index < 0 || index > l->length() - 1) error("index out of bounds for `" + string(sig) + "`", pstate);
1142
+ List* result = new (ctx.mem) List(pstate, l->length(), l->separator());
1151
1143
  for (size_t i = 0, L = l->length(); i < L; ++i) {
1152
1144
  *result << ((i == index) ? v : (*l)[i]);
1153
1145
  }
@@ -1160,13 +1152,13 @@ namespace Sass {
1160
1152
  List* l = dynamic_cast<List*>(env["$list"]);
1161
1153
  Expression* v = ARG("$value", Expression);
1162
1154
  if (!l) {
1163
- l = new (ctx.mem) List(path, position, 1);
1155
+ l = new (ctx.mem) List(pstate, 1);
1164
1156
  *l << ARG("$list", Expression);
1165
1157
  }
1166
1158
  for (size_t i = 0, L = l->length(); i < L; ++i) {
1167
- if (eq(l->value_at_index(i), v, ctx)) return new (ctx.mem) Number(path, position, i+1);
1159
+ if (eq(l->value_at_index(i), v, ctx)) return new (ctx.mem) Number(pstate, i+1);
1168
1160
  }
1169
- return new (ctx.mem) Null(path, position);
1161
+ return new (ctx.mem) Null(pstate);
1170
1162
  }
1171
1163
 
1172
1164
  Signature join_sig = "join($list1, $list2, $separator: auto)";
@@ -1177,20 +1169,20 @@ namespace Sass {
1177
1169
  String_Constant* sep = ARG("$separator", String_Constant);
1178
1170
  List::Separator sep_val = (l1 ? l1->separator() : List::SPACE);
1179
1171
  if (!l1) {
1180
- l1 = new (ctx.mem) List(path, position, 1);
1172
+ l1 = new (ctx.mem) List(pstate, 1);
1181
1173
  *l1 << ARG("$list1", Expression);
1182
1174
  sep_val = (l2 ? l2->separator() : List::SPACE);
1183
1175
  }
1184
1176
  if (!l2) {
1185
- l2 = new (ctx.mem) List(path, position, 1);
1177
+ l2 = new (ctx.mem) List(pstate, 1);
1186
1178
  *l2 << ARG("$list2", Expression);
1187
1179
  }
1188
1180
  size_t len = l1->length() + l2->length();
1189
1181
  string sep_str = unquote(sep->value());
1190
1182
  if (sep_str == "space") sep_val = List::SPACE;
1191
1183
  else if (sep_str == "comma") sep_val = List::COMMA;
1192
- else if (sep_str != "auto") error("argument `$separator` of `" + string(sig) + "` must be `space`, `comma`, or `auto`", path, position);
1193
- List* result = new (ctx.mem) List(path, position, len, sep_val);
1184
+ else if (sep_str != "auto") error("argument `$separator` of `" + string(sig) + "` must be `space`, `comma`, or `auto`", pstate);
1185
+ List* result = new (ctx.mem) List(pstate, len, sep_val);
1194
1186
  *result += l1;
1195
1187
  *result += l2;
1196
1188
  return result;
@@ -1203,14 +1195,14 @@ namespace Sass {
1203
1195
  Expression* v = ARG("$val", Expression);
1204
1196
  String_Constant* sep = ARG("$separator", String_Constant);
1205
1197
  if (!l) {
1206
- l = new (ctx.mem) List(path, position, 1);
1198
+ l = new (ctx.mem) List(pstate, 1);
1207
1199
  *l << ARG("$list", Expression);
1208
1200
  }
1209
- List* result = new (ctx.mem) List(path, position, l->length() + 1, l->separator());
1201
+ List* result = new (ctx.mem) List(pstate, l->length() + 1, l->separator());
1210
1202
  string sep_str(unquote(sep->value()));
1211
1203
  if (sep_str == "space") result->separator(List::SPACE);
1212
1204
  else if (sep_str == "comma") result->separator(List::COMMA);
1213
- else if (sep_str != "auto") error("argument `$separator` of `" + string(sig) + "` must be `space`, `comma`, or `auto`", path, position);
1205
+ else if (sep_str != "auto") error("argument `$separator` of `" + string(sig) + "` must be `space`, `comma`, or `auto`", pstate);
1214
1206
  *result += l;
1215
1207
  *result << v;
1216
1208
  return result;
@@ -1224,7 +1216,7 @@ namespace Sass {
1224
1216
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1225
1217
  List* ith = dynamic_cast<List*>(arglist->value_at_index(i));
1226
1218
  if (!ith) {
1227
- ith = new (ctx.mem) List(path, position, 1);
1219
+ ith = new (ctx.mem) List(pstate, 1);
1228
1220
  *ith << arglist->value_at_index(i);
1229
1221
  if (arglist->is_arglist()) {
1230
1222
  ((Argument*)(*arglist)[i])->value(ith);
@@ -1234,10 +1226,10 @@ namespace Sass {
1234
1226
  }
1235
1227
  shortest = (i ? std::min(shortest, ith->length()) : ith->length());
1236
1228
  }
1237
- List* zippers = new (ctx.mem) List(path, position, shortest, List::COMMA);
1229
+ List* zippers = new (ctx.mem) List(pstate, shortest, List::COMMA);
1238
1230
  size_t L = arglist->length();
1239
1231
  for (size_t i = 0; i < shortest; ++i) {
1240
- List* zipper = new (ctx.mem) List(path, position, L);
1232
+ List* zipper = new (ctx.mem) List(pstate, L);
1241
1233
  for (size_t j = 0; j < L; ++j) {
1242
1234
  *zipper << (*static_cast<List*>(arglist->value_at_index(j)))[i];
1243
1235
  }
@@ -1249,25 +1241,8 @@ namespace Sass {
1249
1241
  Signature compact_sig = "compact($values...)";
1250
1242
  BUILT_IN(compact)
1251
1243
  {
1252
- List* arglist = ARG("$values", List);
1253
- List::Separator sep = List::COMMA;
1254
- if (arglist->length() == 1) {
1255
- Expression* the_arg = arglist->value_at_index(0);
1256
- arglist = dynamic_cast<List*>(the_arg);
1257
- if (!arglist) {
1258
- List* result = new (ctx.mem) List(path, position, 1, List::COMMA);
1259
- *result << the_arg;
1260
- return result;
1261
- }
1262
- sep = arglist->separator();
1263
- }
1264
- List* result = new (ctx.mem) List(path, position, 0, sep);
1265
- for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1266
- Boolean* ith = dynamic_cast<Boolean*>(arglist->value_at_index(i));
1267
- if (ith && ith->value() == false) continue;
1268
- *result << arglist->value_at_index(i);
1269
- }
1270
- return result;
1244
+ error("`compact` has been removed from libsass because it's not part of the Sass spec", pstate);
1245
+ return 0; // suppress warning, error will exit anyway
1271
1246
  }
1272
1247
 
1273
1248
  Signature list_separator_sig = "list_separator($list)";
@@ -1275,11 +1250,10 @@ namespace Sass {
1275
1250
  {
1276
1251
  List* l = dynamic_cast<List*>(env["$list"]);
1277
1252
  if (!l) {
1278
- l = new (ctx.mem) List(path, position, 1);
1253
+ l = new (ctx.mem) List(pstate, 1);
1279
1254
  *l << ARG("$list", Expression);
1280
1255
  }
1281
- return new (ctx.mem) String_Constant(path,
1282
- position,
1256
+ return new (ctx.mem) String_Constant(pstate,
1283
1257
  l->separator() == List::COMMA ? "comma" : "space");
1284
1258
  }
1285
1259
 
@@ -1295,7 +1269,7 @@ namespace Sass {
1295
1269
  try {
1296
1270
  return m->at(v);
1297
1271
  } catch (const std::out_of_range&) {
1298
- return new (ctx.mem) Null(path, position);
1272
+ return new (ctx.mem) Null(pstate);
1299
1273
  }
1300
1274
  catch (...) { throw; }
1301
1275
  }
@@ -1305,14 +1279,14 @@ namespace Sass {
1305
1279
  {
1306
1280
  Map* m = ARGM("$map", Map, ctx);
1307
1281
  Expression* v = ARG("$key", Expression);
1308
- return new (ctx.mem) Boolean(path, position, m->has(v));
1282
+ return new (ctx.mem) Boolean(pstate, m->has(v));
1309
1283
  }
1310
1284
 
1311
1285
  Signature map_keys_sig = "map-keys($map)";
1312
1286
  BUILT_IN(map_keys)
1313
1287
  {
1314
1288
  Map* m = ARGM("$map", Map, ctx);
1315
- List* result = new (ctx.mem) List(path, position, m->length(), List::COMMA);
1289
+ List* result = new (ctx.mem) List(pstate, m->length(), List::COMMA);
1316
1290
  for ( auto key : m->keys()) {
1317
1291
  *result << key;
1318
1292
  }
@@ -1323,7 +1297,7 @@ namespace Sass {
1323
1297
  BUILT_IN(map_values)
1324
1298
  {
1325
1299
  Map* m = ARGM("$map", Map, ctx);
1326
- List* result = new (ctx.mem) List(path, position, m->length(), List::COMMA);
1300
+ List* result = new (ctx.mem) List(pstate, m->length(), List::COMMA);
1327
1301
  for ( auto key : m->keys()) {
1328
1302
  *result << m->at(key);
1329
1303
  }
@@ -1337,7 +1311,7 @@ namespace Sass {
1337
1311
  Map* m2 = ARGM("$map2", Map, ctx);
1338
1312
 
1339
1313
  size_t len = m1->length() + m2->length();
1340
- Map* result = new (ctx.mem) Map(path, position, len);
1314
+ Map* result = new (ctx.mem) Map(pstate, len);
1341
1315
  *result += m1;
1342
1316
  *result += m2;
1343
1317
  return result;
@@ -1349,7 +1323,7 @@ namespace Sass {
1349
1323
  bool remove;
1350
1324
  Map* m = ARGM("$map", Map, ctx);
1351
1325
  List* arglist = ARG("$keys", List);
1352
- Map* result = new (ctx.mem) Map(path, position, 1);
1326
+ Map* result = new (ctx.mem) Map(pstate, 1);
1353
1327
  for (auto key : m->keys()) {
1354
1328
  remove = false;
1355
1329
  for (size_t j = 0, K = arglist->length(); j < K && !remove; ++j) {
@@ -1364,14 +1338,14 @@ namespace Sass {
1364
1338
  BUILT_IN(keywords)
1365
1339
  {
1366
1340
  List* arglist = new (ctx.mem) List(*ARG("$args", List));
1367
- Map* result = new (ctx.mem) Map(path, position, 1);
1341
+ Map* result = new (ctx.mem) Map(pstate, 1);
1368
1342
  // The parser ensures the ordering of arguments so we can assert this
1369
1343
  // isn't keyword argument list the first argument isn't a keyword argument
1370
1344
  if (!(arglist->empty() || ((Argument*)(*arglist)[0])->is_keyword_argument())) return result;
1371
1345
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1372
1346
  string name = string(((Argument*)(*arglist)[i])->name());
1373
1347
  string sanitized_name = string(name, 1);
1374
- *result << make_pair(new (ctx.mem) String_Constant(path, position, sanitized_name),
1348
+ *result << make_pair(new (ctx.mem) String_Constant(pstate, sanitized_name),
1375
1349
  ((Argument*)(*arglist)[i])->value());
1376
1350
  }
1377
1351
  return result;
@@ -1386,22 +1360,22 @@ namespace Sass {
1386
1360
  {
1387
1361
  Expression* v = ARG("$value", Expression);
1388
1362
  if (v->concrete_type() == Expression::STRING) {
1389
- To_String to_string;
1363
+ To_String to_string(&ctx);
1390
1364
  string str(v->perform(&to_string));
1391
1365
  if (ctx.names_to_colors.count(str)) {
1392
- return new (ctx.mem) String_Constant(path, position, "color");
1366
+ return new (ctx.mem) String_Constant(pstate, "color");
1393
1367
  }
1394
1368
  }
1395
- return new (ctx.mem) String_Constant(path, position, ARG("$value", Expression)->type());
1369
+ return new (ctx.mem) String_Constant(pstate, ARG("$value", Expression)->type());
1396
1370
  }
1397
1371
 
1398
1372
  Signature unit_sig = "unit($number)";
1399
1373
  BUILT_IN(unit)
1400
- { return new (ctx.mem) String_Constant(path, position, quote(ARG("$number", Number)->unit(), '"')); }
1374
+ { return new (ctx.mem) String_Quoted(pstate, quote(ARG("$number", Number)->unit(), '"')); }
1401
1375
 
1402
1376
  Signature unitless_sig = "unitless($number)";
1403
1377
  BUILT_IN(unitless)
1404
- { return new (ctx.mem) Boolean(path, position, ARG("$number", Number)->is_unitless()); }
1378
+ { return new (ctx.mem) Boolean(pstate, ARG("$number", Number)->is_unitless()); }
1405
1379
 
1406
1380
  Signature comparable_sig = "comparable($number-1, $number-2)";
1407
1381
  BUILT_IN(comparable)
@@ -1409,62 +1383,62 @@ namespace Sass {
1409
1383
  Number* n1 = ARG("$number-1", Number);
1410
1384
  Number* n2 = ARG("$number-2", Number);
1411
1385
  if (n1->is_unitless() || n2->is_unitless()) {
1412
- return new (ctx.mem) Boolean(path, position, true);
1386
+ return new (ctx.mem) Boolean(pstate, true);
1413
1387
  }
1414
1388
  Number tmp_n2(*n2);
1415
1389
  tmp_n2.normalize(n1->find_convertible_unit());
1416
- return new (ctx.mem) Boolean(path, position, n1->unit() == tmp_n2.unit());
1390
+ return new (ctx.mem) Boolean(pstate, n1->unit() == tmp_n2.unit());
1417
1391
  }
1418
1392
 
1419
1393
  Signature variable_exists_sig = "variable-exists($name)";
1420
1394
  BUILT_IN(variable_exists)
1421
1395
  {
1422
- string s = unquote(ARG("$name", String_Constant)->value());
1396
+ string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
1423
1397
 
1424
1398
  if(d_env.has("$"+s)) {
1425
- return new (ctx.mem) Boolean(path, position, true);
1399
+ return new (ctx.mem) Boolean(pstate, true);
1426
1400
  }
1427
1401
  else {
1428
- return new (ctx.mem) Boolean(path, position, false);
1402
+ return new (ctx.mem) Boolean(pstate, false);
1429
1403
  }
1430
1404
  }
1431
1405
 
1432
1406
  Signature global_variable_exists_sig = "global-variable-exists($name)";
1433
1407
  BUILT_IN(global_variable_exists)
1434
1408
  {
1435
- string s = unquote(ARG("$name", String_Constant)->value());
1409
+ string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
1436
1410
 
1437
1411
  if(d_env.global_frame_has("$"+s)) {
1438
- return new (ctx.mem) Boolean(path, position, true);
1412
+ return new (ctx.mem) Boolean(pstate, true);
1439
1413
  }
1440
1414
  else {
1441
- return new (ctx.mem) Boolean(path, position, false);
1415
+ return new (ctx.mem) Boolean(pstate, false);
1442
1416
  }
1443
1417
  }
1444
1418
 
1445
1419
  Signature function_exists_sig = "function-exists($name)";
1446
1420
  BUILT_IN(function_exists)
1447
1421
  {
1448
- string s = unquote(ARG("$name", String_Constant)->value());
1422
+ string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
1449
1423
 
1450
1424
  if(d_env.global_frame_has(s+"[f]")) {
1451
- return new (ctx.mem) Boolean(path, position, true);
1425
+ return new (ctx.mem) Boolean(pstate, true);
1452
1426
  }
1453
1427
  else {
1454
- return new (ctx.mem) Boolean(path, position, false);
1428
+ return new (ctx.mem) Boolean(pstate, false);
1455
1429
  }
1456
1430
  }
1457
1431
 
1458
1432
  Signature mixin_exists_sig = "mixin-exists($name)";
1459
1433
  BUILT_IN(mixin_exists)
1460
1434
  {
1461
- string s = unquote(ARG("$name", String_Constant)->value());
1435
+ string s = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
1462
1436
 
1463
1437
  if(d_env.global_frame_has(s+"[m]")) {
1464
- return new (ctx.mem) Boolean(path, position, true);
1438
+ return new (ctx.mem) Boolean(pstate, true);
1465
1439
  }
1466
1440
  else {
1467
- return new (ctx.mem) Boolean(path, position, false);
1441
+ return new (ctx.mem) Boolean(pstate, false);
1468
1442
  }
1469
1443
  }
1470
1444
 
@@ -1474,25 +1448,25 @@ namespace Sass {
1474
1448
  string s = unquote(ARG("$name", String_Constant)->value());
1475
1449
 
1476
1450
  if(features.find(s) == features.end()) {
1477
- return new (ctx.mem) Boolean(path, position, false);
1451
+ return new (ctx.mem) Boolean(pstate, false);
1478
1452
  }
1479
1453
  else {
1480
- return new (ctx.mem) Boolean(path, position, true);
1454
+ return new (ctx.mem) Boolean(pstate, true);
1481
1455
  }
1482
1456
  }
1483
1457
 
1484
1458
  Signature call_sig = "call($name, $args...)";
1485
1459
  BUILT_IN(call)
1486
1460
  {
1487
- string name = unquote(ARG("$name", String_Constant)->value());
1461
+ string name = Util::normalize_underscores(unquote(ARG("$name", String_Constant)->value()));
1488
1462
  List* arglist = new (ctx.mem) List(*ARG("$args", List));
1489
1463
 
1490
- Arguments* args = new (ctx.mem) Arguments(path, position);
1464
+ Arguments* args = new (ctx.mem) Arguments(pstate);
1491
1465
  for (size_t i = 0, L = arglist->length(); i < L; ++i) {
1492
- Argument* arg = new (ctx.mem) Argument(path, position, arglist->value_at_index(i));
1466
+ Argument* arg = new (ctx.mem) Argument(pstate, arglist->value_at_index(i));
1493
1467
  *args << arg;
1494
1468
  }
1495
- Function_Call* func = new (ctx.mem) Function_Call(path, position, name, args);
1469
+ Function_Call* func = new (ctx.mem) Function_Call(pstate, name, args);
1496
1470
  Eval eval(ctx, &d_env, backtrace);
1497
1471
  return func->perform(&eval);
1498
1472
 
@@ -1504,7 +1478,7 @@ namespace Sass {
1504
1478
 
1505
1479
  Signature not_sig = "not($value)";
1506
1480
  BUILT_IN(sass_not)
1507
- { return new (ctx.mem) Boolean(path, position, ARG("$value", Expression)->is_false()); }
1481
+ { return new (ctx.mem) Boolean(pstate, ARG("$value", Expression)->is_false()); }
1508
1482
 
1509
1483
  Signature if_sig = "if($condition, $if-true, $if-false)";
1510
1484
  // BUILT_IN(sass_if)
@@ -1528,11 +1502,8 @@ namespace Sass {
1528
1502
  Signature image_url_sig = "image-url($path, $only-path: false, $cache-buster: false)";
1529
1503
  BUILT_IN(image_url)
1530
1504
  {
1531
- String_Constant* ipath = ARG("$path", String_Constant);
1532
- bool only_path = !ARG("$only-path", Expression)->is_false();
1533
- string full_path(quote(ctx.image_path + "/" + unquote(ipath->value()), '"'));
1534
- if (!only_path) full_path = "url(" + full_path + ")";
1535
- return new (ctx.mem) String_Constant(path, position, full_path);
1505
+ error("`image_url` has been removed from libsass because it's not part of the Sass spec", pstate);
1506
+ return 0; // suppress warning, error will exit anyway
1536
1507
  }
1537
1508
 
1538
1509
  //////////////////////////
@@ -1544,11 +1515,23 @@ namespace Sass {
1544
1515
  {
1545
1516
  Expression* v = ARG("$value", Expression);
1546
1517
  if (v->concrete_type() == Expression::NULL_VAL) {
1547
- return new (ctx.mem) String_Constant(path, position, "null");
1518
+ return new (ctx.mem) String_Constant(pstate, "null");
1548
1519
  } else if (v->concrete_type() == Expression::BOOLEAN && *v == 0) {
1549
- return new (ctx.mem) String_Constant(path, position, "false");
1520
+ return new (ctx.mem) String_Constant(pstate, "false");
1521
+ } else if (v->concrete_type() == Expression::STRING) {
1522
+ return v;
1523
+ } else {
1524
+ Output_Style old_style;
1525
+ old_style = ctx.output_style;
1526
+ ctx.output_style = NESTED;
1527
+ To_String to_string(&ctx);
1528
+ string inspect = v->perform(&to_string);
1529
+ ctx.output_style = old_style;
1530
+ return new (ctx.mem) String_Constant(pstate, inspect);
1531
+
1532
+
1550
1533
  }
1551
- return v;
1534
+ // return v;
1552
1535
  }
1553
1536
 
1554
1537
  Signature unique_id_sig = "unique-id()";
@@ -1556,9 +1539,9 @@ namespace Sass {
1556
1539
  {
1557
1540
  std::stringstream ss;
1558
1541
  uniform_real_distribution<> distributor(0, 4294967296); // 16^8
1559
- uint_fast32_t distributed = distributor(rand);
1542
+ uint_fast32_t distributed = static_cast<uint_fast32_t>(distributor(rand));
1560
1543
  ss << "u" << setfill('0') << setw(8) << std::hex << distributed;
1561
- return new (ctx.mem) String_Constant(path, position, ss.str());
1544
+ return new (ctx.mem) String_Constant(pstate, ss.str());
1562
1545
  }
1563
1546
 
1564
1547
  }