sassc 0.0.9 → 0.0.10

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