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,4 +1,7 @@
1
- #define SASS_PRELEXER
1
+ #ifndef SASS_PRELEXER_H
2
+ #define SASS_PRELEXER_H
3
+
4
+ #include <cstring>
2
5
 
3
6
  namespace Sass {
4
7
  namespace Prelexer {
@@ -16,7 +19,12 @@ namespace Sass {
16
19
  template <const char* prefix>
17
20
  const char* exactly(const char* src) {
18
21
  const char* pre = prefix;
19
- while (*pre && *src == *pre) ++src, ++pre;
22
+ if (*src == 0) return 0;
23
+ // there is a small chance that the search prefix
24
+ // is longer than the rest of the string to look at
25
+ while (*pre && *src == *pre) {
26
+ ++src, ++pre;
27
+ }
20
28
  return *pre ? 0 : src;
21
29
  }
22
30
 
@@ -50,6 +58,14 @@ namespace Sass {
50
58
  return p == src ? 0 : p;
51
59
  }
52
60
 
61
+ // Match a sequence of characters up to the next newline.
62
+ template <char end>
63
+ const char* until(const char* src) {
64
+ if (*src == '\n' && exactly<end>(src)) return 0;
65
+ while (*src && *src != '\n' && !exactly<end>(src)) ++src;
66
+ return ++src;
67
+ }
68
+
53
69
  // Match a sequence of characters up to the next newline.
54
70
  template <const char* prefix>
55
71
  const char* to_endl(const char* src) {
@@ -72,6 +88,69 @@ namespace Sass {
72
88
  }
73
89
  }
74
90
 
91
+ // skip to delimiter (mx) inside given range
92
+ // this will savely skip over all quoted strings
93
+ // recursive skip stuff delimited by start/stop
94
+ // first start/opener must be consumed already!
95
+ template<prelexer start, prelexer stop>
96
+ const char* skip_over_scopes(const char* src, const char* end = 0) {
97
+
98
+ size_t level = 0;
99
+ bool in_squote = false;
100
+ bool in_dquote = false;
101
+ // bool in_braces = false;
102
+
103
+ while (*src) {
104
+
105
+ // check for abort condition
106
+ if (end && src >= end) break;
107
+
108
+ // has escaped sequence?
109
+ if (*src == '\\') {
110
+ ++ src; // skip this (and next)
111
+ }
112
+ else if (*src == '"') {
113
+ in_dquote = ! in_dquote;
114
+ }
115
+ else if (*src == '\'') {
116
+ in_squote = ! in_squote;
117
+ }
118
+ else if (in_dquote || in_squote) {
119
+ // take everything literally
120
+ }
121
+
122
+ // find another opener inside?
123
+ else if (start(src)) {
124
+ ++ level; // increase counter
125
+ }
126
+
127
+ // look for the closer (maybe final, maybe not)
128
+ else if (const char* final = stop(src)) {
129
+ // only close one level?
130
+ if (level > 0) -- level;
131
+ // return position at end of stop
132
+ // delimiter may be multiple chars
133
+ else return final;
134
+ }
135
+
136
+ // next
137
+ ++ src;
138
+ }
139
+
140
+ return 0;
141
+ }
142
+
143
+ // Match a sequence of characters delimited by the supplied chars.
144
+ template <prelexer start, prelexer stop>
145
+ const char* recursive_scopes(const char* src) {
146
+ // parse opener
147
+ src = start(src);
148
+ // abort if not found
149
+ if (!src) return 0;
150
+ // parse the rest until final closer
151
+ return skip_over_scopes<start, stop>(src);
152
+ }
153
+
75
154
  // Match a sequence of characters delimited by the supplied strings.
76
155
  template <const char* beg, const char* end, bool esc>
77
156
  const char* delimited_by(const char* src) {
@@ -93,12 +172,14 @@ namespace Sass {
93
172
  const char* any_char_except(const char* src) {
94
173
  return (*src && *src != c) ? src+1 : 0;
95
174
  }
175
+ // Match word boundary (look ahead)
176
+ const char* word_boundary(const char* src);
96
177
 
97
178
  // Matches zero characters (always succeeds without consuming input).
98
- const char* epsilon(const char*);
179
+ // const char* epsilon(const char*);
99
180
 
100
181
  // Matches the empty string.
101
- const char* empty(const char*);
182
+ // const char* empty(const char*);
102
183
 
103
184
  // Succeeds of the supplied matcher fails, and vice versa.
104
185
  template <prelexer mx>
@@ -295,6 +376,10 @@ namespace Sass {
295
376
  const char* xdigits(const char* src);
296
377
  const char* alnums(const char* src);
297
378
  const char* puncts(const char* src);
379
+ // Match certain white-space charactes.
380
+ const char* wspaces(const char* src);
381
+ // const char* newline(const char* src);
382
+ // const char* whitespace(const char* src);
298
383
 
299
384
  // Match a line comment.
300
385
  const char* line_comment(const char* src);
@@ -308,13 +393,16 @@ namespace Sass {
308
393
  // Match double- and single-quoted strings.
309
394
  const char* double_quoted_string(const char* src);
310
395
  const char* single_quoted_string(const char* src);
311
- const char* string_constant(const char* src);
396
+ const char* quoted_string(const char* src);
312
397
  // Match interpolants.
313
398
  const char* interpolant(const char* src);
399
+ // Match number prefix ([\+\-]+)
400
+ const char* number_prefix(const char* src);
314
401
 
315
402
  // Whitespace handling.
316
403
  const char* optional_spaces(const char* src);
317
- const char* optional_comment(const char* src);
404
+ // const char* optional_comment(const char* src);
405
+ const char* optional_spaces_and_comments(const char* src);
318
406
  const char* spaces_and_comments(const char* src);
319
407
  const char* no_spaces(const char* src);
320
408
 
@@ -326,22 +414,25 @@ namespace Sass {
326
414
  const char* identifier(const char* src);
327
415
  const char* identifier_fragment(const char* src);
328
416
  // Match selector names.
329
- const char* sel_ident(const char* src);
417
+ // const char* sel_ident(const char* src);
330
418
  // Match interpolant schemas
331
419
  const char* identifier_schema(const char* src);
332
420
  const char* value_schema(const char* src);
333
421
  const char* filename(const char* src);
334
- const char* filename_schema(const char* src);
335
- const char* url_schema(const char* src);
336
- const char* url_value(const char* src);
422
+ // const char* filename_schema(const char* src);
423
+ // const char* url_schema(const char* src);
424
+ // const char* url_value(const char* src);
337
425
  const char* vendor_prefix(const char* src);
338
426
  // Match CSS '@' keywords.
339
427
  const char* at_keyword(const char* src);
340
428
  const char* import(const char* src);
429
+ const char* at_root(const char* src);
430
+ const char* with_directive(const char* src);
431
+ const char* without_directive(const char* src);
341
432
  const char* media(const char* src);
342
433
  const char* supports(const char* src);
343
- const char* keyframes(const char* src);
344
- const char* keyf(const char* src);
434
+ // const char* keyframes(const char* src);
435
+ // const char* keyf(const char* src);
345
436
  const char* mixin(const char* src);
346
437
  const char* function(const char* src);
347
438
  const char* return_directive(const char* src);
@@ -367,7 +458,7 @@ namespace Sass {
367
458
  const char* err(const char* src);
368
459
  const char* dbg(const char* src);
369
460
 
370
- const char* directive(const char* src);
461
+ // const char* directive(const char* src);
371
462
  const char* at_keyword(const char* src);
372
463
 
373
464
  const char* null(const char* src);
@@ -396,10 +487,11 @@ namespace Sass {
396
487
  const char* dimension(const char* src);
397
488
  const char* hex(const char* src);
398
489
  const char* hexa(const char* src);
399
- const char* rgb_prefix(const char* src);
490
+ const char* hex0(const char* src);
491
+ // const char* rgb_prefix(const char* src);
400
492
  // Match CSS uri specifiers.
401
493
  const char* uri_prefix(const char* src);
402
- const char* uri(const char* src);
494
+ // const char* uri(const char* src);
403
495
  const char* url(const char* src);
404
496
  // Match CSS "!important" keyword.
405
497
  const char* important(const char* src);
@@ -425,10 +517,10 @@ namespace Sass {
425
517
  const char* suffix_match(const char* src);
426
518
  const char* substring_match(const char* src);
427
519
  // Match CSS combinators.
428
- const char* adjacent_to(const char* src);
429
- const char* precedes(const char* src);
430
- const char* parent_of(const char* src);
431
- const char* ancestor_of(const char* src);
520
+ // const char* adjacent_to(const char* src);
521
+ // const char* precedes(const char* src);
522
+ // const char* parent_of(const char* src);
523
+ // const char* ancestor_of(const char* src);
432
524
 
433
525
  // Match SCSS variable names.
434
526
  const char* variable(const char* src);
@@ -456,8 +548,8 @@ namespace Sass {
456
548
  const char* url(const char* src);
457
549
 
458
550
  // Path matching functions.
459
- const char* folder(const char* src);
460
- const char* folders(const char* src);
551
+ // const char* folder(const char* src);
552
+ // const char* folders(const char* src);
461
553
 
462
554
 
463
555
  const char* static_string(const char* src);
@@ -477,8 +569,11 @@ namespace Sass {
477
569
  }
478
570
  template<prelexer mx>
479
571
  const char* find_first_in_interval(const char* beg, const char* end) {
572
+ bool esc = false;
480
573
  while ((beg < end) && *beg) {
481
- if (mx(beg)) return beg;
574
+ if (esc) esc = false;
575
+ else if (*beg == '\\') esc = true;
576
+ else if (mx(beg)) return beg;
482
577
  ++beg;
483
578
  }
484
579
  return 0;
@@ -486,8 +581,11 @@ namespace Sass {
486
581
  template <char c>
487
582
  unsigned int count_interval(const char* beg, const char* end) {
488
583
  unsigned int counter = 0;
584
+ bool esc = false;
489
585
  while (beg < end && *beg) {
490
- if (*beg == c) ++counter;
586
+ if (esc) esc = false;
587
+ else if (*beg == '\\') esc = true;
588
+ else if (*beg == c) ++counter;
491
589
  ++beg;
492
590
  }
493
591
  return counter;
@@ -495,9 +593,16 @@ namespace Sass {
495
593
  template <prelexer mx>
496
594
  unsigned int count_interval(const char* beg, const char* end) {
497
595
  unsigned int counter = 0;
596
+ bool esc = false;
498
597
  while (beg < end && *beg) {
499
598
  const char* p;
500
- if ((p = mx(beg))) {
599
+ if (esc) {
600
+ esc = false;
601
+ ++beg;
602
+ } else if (*beg == '\\') {
603
+ esc = true;
604
+ ++beg;
605
+ } else if ((p = mx(beg))) {
501
606
  ++counter;
502
607
  beg = p;
503
608
  }
@@ -511,3 +616,5 @@ namespace Sass {
511
616
  const char* chunk(const char* src);
512
617
  }
513
618
  }
619
+
620
+ #endif
@@ -17,7 +17,7 @@ namespace Sass {
17
17
  Selector_List* sl = static_cast<Selector_List*>(r->selector());
18
18
 
19
19
  if (sl) {
20
- Selector_List* new_sl = new (ctx.mem) Selector_List(sl->path(), sl->position());
20
+ Selector_List* new_sl = new (ctx.mem) Selector_List(sl->pstate());
21
21
 
22
22
  for (size_t i = 0, L = sl->length(); i < L; ++i) {
23
23
  if (!(*sl)[i]->has_placeholder()) {
@@ -1,20 +1,18 @@
1
+ #ifndef SASS_REMOVE_PLACEHOLDERS_H
2
+ #define SASS_REMOVE_PLACEHOLDERS_H
3
+
1
4
  #pragma once
2
5
 
3
6
  #include <iostream>
4
7
 
5
- #ifndef SASS_AST
6
8
  #include "ast.hpp"
7
- #endif
8
-
9
- #ifndef SASS_OPERATION
10
9
  #include "operation.hpp"
11
- #endif
12
10
 
13
11
  namespace Sass {
14
12
 
15
13
  using namespace std;
16
14
 
17
- struct Context;
15
+ class Context;
18
16
 
19
17
  class Remove_Placeholders : public Operation_CRTP<void, Remove_Placeholders> {
20
18
 
@@ -41,3 +39,5 @@ namespace Sass {
41
39
  };
42
40
 
43
41
  }
42
+
43
+ #endif
@@ -4,14 +4,14 @@
4
4
  #include <sstream>
5
5
 
6
6
  #include "sass.h"
7
- #include "inspect.hpp"
7
+ #include "util.hpp"
8
8
 
9
9
  extern "C" {
10
10
  using namespace std;
11
11
 
12
12
  // caller must free the returned memory
13
- char* ADDCALL sass_string_quote (const char *str, const char quotemark) {
14
- string quoted = Sass::quote(str, quotemark);
13
+ char* ADDCALL sass_string_quote (const char *str, const char quote_mark) {
14
+ string quoted = Sass::quote(str, quote_mark);
15
15
  char *cstr = (char*) malloc(quoted.length() + 1);
16
16
  std::strcpy(cstr, quoted.c_str());
17
17
  return cstr;
@@ -1,9 +1,18 @@
1
- #ifndef SASS
2
- #define SASS
1
+ #ifndef SASS_H
2
+ #define SASS_H
3
3
 
4
4
  #include <stddef.h>
5
5
  #include <stdbool.h>
6
6
 
7
+ #ifdef __GNUC__
8
+ #define DEPRECATED(func) func __attribute__ ((deprecated))
9
+ #elif defined(_MSC_VER)
10
+ #define DEPRECATED(func) __declspec(deprecated) func
11
+ #else
12
+ #pragma message("WARNING: You need to implement DEPRECATED for this compiler")
13
+ #define DEPRECATED(func) func
14
+ #endif
15
+
7
16
  #ifdef _WIN32
8
17
 
9
18
  /* You should define ADD_EXPORTS *only* when building the DLL. */
@@ -46,13 +55,12 @@ enum Sass_Output_Style {
46
55
  };
47
56
 
48
57
  // Some convenient string helper function
49
- ADDAPI char* ADDCALL sass_string_quote (const char *str, const char quotemark);
58
+ ADDAPI char* ADDCALL sass_string_quote (const char *str, const char quote_mark);
50
59
  ADDAPI char* ADDCALL sass_string_unquote (const char *str);
51
60
 
52
61
  // Get compiled libsass version
53
62
  ADDAPI const char* ADDCALL libsass_version(void);
54
63
 
55
-
56
64
  #ifdef __cplusplus
57
65
  } // __cplusplus defined.
58
66
  #endif
@@ -561,11 +561,12 @@ namespace Sass
561
561
 
562
562
  }
563
563
 
564
- // terminate warn and debug statements immediately
564
+ // terminate some statements immediately
565
565
  else if (
566
566
  sass.substr(pos_left, 5) == "@warn" ||
567
567
  sass.substr(pos_left, 6) == "@debug" ||
568
- sass.substr(pos_left, 6) == "@error"
568
+ sass.substr(pos_left, 6) == "@error" ||
569
+ sass.substr(pos_left, 8) == "@charset"
569
570
  ) { sass = indent + sass.substr(pos_left); }
570
571
  // replace some specific sass shorthand directives (if not fallowed by a white space character)
571
572
  else if (sass.substr(pos_left, 1) == "=" && sass.find_first_of(SASS2SCSS_FIND_WHITESPACE, pos_left) != pos_left + 1)
@@ -1,3 +1,6 @@
1
+ #ifndef SASS2SCSS_H
2
+ #define SASS2SCSS_H
3
+
1
4
  #ifdef _WIN32
2
5
 
3
6
  /* You should define ADD_EXPORTS *only* when building the DLL. */
@@ -108,3 +111,5 @@ extern "C" {
108
111
  #ifdef __cplusplus
109
112
  } // __cplusplus defined.
110
113
  #endif
114
+
115
+ #endif
@@ -1,14 +1,20 @@
1
1
  #ifdef _WIN32
2
2
  #include <io.h>
3
+ #define LFEED "\n"
3
4
  #else
4
5
  #include <unistd.h>
6
+ #define LFEED "\n"
5
7
  #endif
6
8
 
9
+ #include <cstring>
7
10
  #include <stdexcept>
11
+ #include "file.hpp"
8
12
  #include "json.hpp"
13
+ #include "util.hpp"
9
14
  #include "context.hpp"
10
15
  #include "sass_values.h"
11
16
  #include "sass_context.h"
17
+ #include "error_handling.hpp"
12
18
 
13
19
  extern "C" {
14
20
  using namespace std;
@@ -68,22 +74,30 @@ extern "C" {
68
74
  // information in source-maps etc.
69
75
  char* output_path;
70
76
 
71
- // For the image-url Sass function
72
- char* image_path;
77
+ // String to be used for indentation
78
+ const char* indent;
79
+ // String to be used to for line feeds
80
+ const char* linefeed;
73
81
 
74
82
  // Colon-separated list of paths
75
83
  // Semicolon-separated on Windows
76
84
  // Maybe use array interface instead?
77
85
  char* include_path;
86
+ char* plugin_path;
78
87
 
79
- // Include path (linked string list)
88
+ // Include paths (linked string list)
80
89
  struct string_list* include_paths;
90
+ // Plugin paths (linked string list)
91
+ struct string_list* plugin_paths;
81
92
 
82
93
  // Path to source map file
83
94
  // Enables source map generation
84
95
  // Used to create sourceMappingUrl
85
96
  char* source_map_file;
86
97
 
98
+ // Directly inserted in source maps
99
+ char* source_map_root;
100
+
87
101
  // Custom functions that can be called from sccs code
88
102
  Sass_C_Function_List c_functions;
89
103
 
@@ -108,6 +122,7 @@ extern "C" {
108
122
  // error status
109
123
  int error_status;
110
124
  char* error_json;
125
+ char* error_text;
111
126
  char* error_message;
112
127
  // error position
113
128
  char* error_file;
@@ -162,7 +177,7 @@ extern "C" {
162
177
  #define IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(type, option) \
163
178
  type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return options->option; } \
164
179
  void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) \
165
- { free(options->option); options->option = option ? strdup(option) : 0; }
180
+ { free(options->option); options->option = option ? sass_strdup(option) : 0; }
166
181
 
167
182
  #define IMPLEMENT_SASS_CONTEXT_GETTER(type, option) \
168
183
  type ADDCALL sass_context_get_##option (struct Sass_Context* ctx) { return ctx->option; }
@@ -175,7 +190,7 @@ extern "C" {
175
190
  return str == NULL ? "" : str;
176
191
  }
177
192
 
178
- static void copy_strings(const std::vector<std::string>& strings, char*** array, int skip = 0) {
193
+ static void copy_strings(const std::vector<std::string>& strings, char*** array, int skip = 0) throw() {
179
194
  int num = static_cast<int>(strings.size());
180
195
  char** arr = (char**) malloc(sizeof(char*) * (num + 1));
181
196
  if (arr == 0) throw(bad_alloc());
@@ -210,19 +225,37 @@ extern "C" {
210
225
  }
211
226
  catch (Sass_Error& e) {
212
227
  stringstream msg_stream;
228
+ string cwd(Sass::File::get_cwd());
213
229
  JsonNode* json_err = json_mkobject();
214
230
  json_append_member(json_err, "status", json_mknumber(1));
215
- json_append_member(json_err, "file", json_mkstring(e.path.c_str()));
216
- json_append_member(json_err, "line", json_mknumber(e.position.line));
217
- json_append_member(json_err, "column", json_mknumber(e.position.column));
231
+ json_append_member(json_err, "file", json_mkstring(e.pstate.path.c_str()));
232
+ json_append_member(json_err, "line", json_mknumber(e.pstate.line+1));
233
+ json_append_member(json_err, "column", json_mknumber(e.pstate.column+1));
218
234
  json_append_member(json_err, "message", json_mkstring(e.message.c_str()));
219
- msg_stream << e.path << ":" << e.position.line << ": " << e.message << endl;
235
+ string rel_path(Sass::File::resolve_relative_path(e.pstate.path, cwd, cwd));
236
+
237
+ string msg_prefix("Error: ");
238
+ bool got_newline = false;
239
+ msg_stream << msg_prefix;
240
+ for (char chr : e.message) {
241
+ if (chr == '\n') {
242
+ got_newline = true;
243
+ } else if (got_newline) {
244
+ msg_stream << string(msg_prefix.size(), ' ');
245
+ got_newline = false;
246
+ }
247
+ msg_stream << chr;
248
+ }
249
+ if (!got_newline) msg_stream << "\n";
250
+ msg_stream << string(msg_prefix.size(), ' ');
251
+ msg_stream << " on line " << e.pstate.line+1 << " of " << rel_path << "\n";
220
252
  c_ctx->error_json = json_stringify(json_err, " ");;
221
- c_ctx->error_message = strdup(msg_stream.str().c_str());
253
+ c_ctx->error_message = sass_strdup(msg_stream.str().c_str());
254
+ c_ctx->error_text = strdup(e.message.c_str());
222
255
  c_ctx->error_status = 1;
223
- c_ctx->error_file = strdup(e.path.c_str());
224
- c_ctx->error_line = e.position.line;
225
- c_ctx->error_column = e.position.column;
256
+ c_ctx->error_file = sass_strdup(e.pstate.path.c_str());
257
+ c_ctx->error_line = e.pstate.line+1;
258
+ c_ctx->error_column = e.pstate.column+1;
226
259
  c_ctx->output_string = 0;
227
260
  c_ctx->source_map_string = 0;
228
261
  json_delete(json_err);
@@ -234,7 +267,8 @@ extern "C" {
234
267
  json_append_member(json_err, "status", json_mknumber(2));
235
268
  json_append_member(json_err, "message", json_mkstring(ba.what()));
236
269
  c_ctx->error_json = json_stringify(json_err, " ");;
237
- c_ctx->error_message = strdup(msg_stream.str().c_str());
270
+ c_ctx->error_message = sass_strdup(msg_stream.str().c_str());
271
+ c_ctx->error_text = strdup(ba.what());
238
272
  c_ctx->error_status = 2;
239
273
  c_ctx->output_string = 0;
240
274
  c_ctx->source_map_string = 0;
@@ -247,7 +281,8 @@ extern "C" {
247
281
  json_append_member(json_err, "status", json_mknumber(3));
248
282
  json_append_member(json_err, "message", json_mkstring(e.what()));
249
283
  c_ctx->error_json = json_stringify(json_err, " ");;
250
- c_ctx->error_message = strdup(msg_stream.str().c_str());
284
+ c_ctx->error_message = sass_strdup(msg_stream.str().c_str());
285
+ c_ctx->error_text = strdup(e.what());
251
286
  c_ctx->error_status = 3;
252
287
  c_ctx->output_string = 0;
253
288
  c_ctx->source_map_string = 0;
@@ -260,7 +295,8 @@ extern "C" {
260
295
  json_append_member(json_err, "status", json_mknumber(4));
261
296
  json_append_member(json_err, "message", json_mkstring(e.c_str()));
262
297
  c_ctx->error_json = json_stringify(json_err, " ");;
263
- c_ctx->error_message = strdup(msg_stream.str().c_str());
298
+ c_ctx->error_message = sass_strdup(msg_stream.str().c_str());
299
+ c_ctx->error_text = strdup(e.c_str());
264
300
  c_ctx->error_status = 4;
265
301
  c_ctx->output_string = 0;
266
302
  c_ctx->source_map_string = 0;
@@ -273,7 +309,8 @@ extern "C" {
273
309
  json_append_member(json_err, "status", json_mknumber(5));
274
310
  json_append_member(json_err, "message", json_mkstring("unknown"));
275
311
  c_ctx->error_json = json_stringify(json_err, " ");;
276
- c_ctx->error_message = strdup(msg_stream.str().c_str());
312
+ c_ctx->error_message = sass_strdup(msg_stream.str().c_str());
313
+ c_ctx->error_text = strdup("unknown");
277
314
  c_ctx->error_status = 5;
278
315
  c_ctx->output_string = 0;
279
316
  c_ctx->source_map_string = 0;
@@ -297,19 +334,35 @@ extern "C" {
297
334
  }
298
335
 
299
336
  // convert include path linked list to static array
300
- struct string_list* cur = c_ctx->include_paths;
337
+ struct string_list* inc = c_ctx->include_paths;
301
338
  // very poor loop to get the length of the linked list
302
- size_t length = 0; while (cur) { length ++; cur = cur->next; }
339
+ size_t inc_size = 0; while (inc) { inc_size ++; inc = inc->next; }
303
340
  // create char* array to hold all paths plus null terminator
304
- const char** include_paths = (const char**) calloc(length + 1, sizeof(char*));
341
+ const char** include_paths = (const char**) calloc(inc_size + 1, sizeof(char*));
305
342
  if (include_paths == 0) throw(bad_alloc());
306
343
  // reset iterator
307
- cur = c_ctx->include_paths;
344
+ inc = c_ctx->include_paths;
345
+ // copy over the paths
346
+ for (size_t i = 0; inc; i++) {
347
+ include_paths[i] = inc->string;
348
+ inc = inc->next;
349
+ }
350
+
351
+ // convert plugin path linked list to static array
352
+ struct string_list* imp = c_ctx->plugin_paths;
353
+ // very poor loop to get the length of the linked list
354
+ size_t imp_size = 0; while (imp) { imp_size ++; imp = imp->next; }
355
+ // create char* array to hold all paths plus null terminator
356
+ const char** plugin_paths = (const char**) calloc(imp_size + 1, sizeof(char*));
357
+ if (plugin_paths == 0) throw(bad_alloc());
358
+ // reset iterator
359
+ imp = c_ctx->plugin_paths;
308
360
  // copy over the paths
309
- for (size_t i = 0; cur; i++) {
310
- include_paths[i] = cur->string;
311
- cur = cur->next;
361
+ for (size_t i = 0; imp; i++) {
362
+ plugin_paths[i] = imp->string;
363
+ imp = imp->next;
312
364
  }
365
+
313
366
  // transfer the options to c++
314
367
  cpp_opt.input_path(input_path)
315
368
  .output_path(output_path)
@@ -317,20 +370,26 @@ extern "C" {
317
370
  .is_indented_syntax_src(c_ctx->is_indented_syntax_src)
318
371
  .source_comments(c_ctx->source_comments)
319
372
  .source_map_file(safe_str(c_ctx->source_map_file))
373
+ .source_map_root(safe_str(c_ctx->source_map_root))
320
374
  .source_map_embed(c_ctx->source_map_embed)
321
375
  .source_map_contents(c_ctx->source_map_contents)
322
376
  .omit_source_map_url(c_ctx->omit_source_map_url)
323
- .image_path(safe_str(c_ctx->image_path))
324
377
  .include_paths_c_str(c_ctx->include_path)
325
- .importer(c_ctx->importer)
378
+ .plugin_paths_c_str(c_ctx->plugin_path)
326
379
  .include_paths_array(include_paths)
380
+ .plugin_paths_array(plugin_paths)
327
381
  .include_paths(vector<string>())
328
- .precision(c_ctx->precision ? c_ctx->precision : 5);
382
+ .plugin_paths(vector<string>())
383
+ .importer(c_ctx->importer)
384
+ .precision(c_ctx->precision ? c_ctx->precision : 5)
385
+ .linefeed(c_ctx->linefeed ? c_ctx->linefeed : LFEED)
386
+ .indent(c_ctx->indent ? c_ctx->indent : " ");
329
387
 
330
388
  // create new c++ Context
331
389
  Context* cpp_ctx = new Context(cpp_opt);
332
390
  // free intermediate data
333
391
  free(include_paths);
392
+ free(plugin_paths);
334
393
 
335
394
  // register our custom functions
336
395
  if (c_ctx->c_functions) {
@@ -343,6 +402,7 @@ extern "C" {
343
402
 
344
403
  // reset error status
345
404
  c_ctx->error_json = 0;
405
+ c_ctx->error_text = 0;
346
406
  c_ctx->error_message = 0;
347
407
  c_ctx->error_status = 0;
348
408
  // reset error position
@@ -386,7 +446,7 @@ extern "C" {
386
446
  }
387
447
 
388
448
  // copy the included files on to the context (dont forget to free)
389
- copy_strings(cpp_ctx->get_included_files(skip), &c_ctx->included_files, skip);
449
+ if (root) copy_strings(cpp_ctx->get_included_files(skip), &c_ctx->included_files, skip);
390
450
 
391
451
  // return parsed block
392
452
  return root;
@@ -504,7 +564,7 @@ extern "C" {
504
564
  if (*data_ctx->source_string == 0) { throw(runtime_error("Data context has empty source string")); }
505
565
  cpp_opt.source_c_str(data_ctx->source_string);
506
566
  }
507
- catch (...) { return handle_errors(c_ctx) || 1; }
567
+ catch (...) { return handle_errors(c_ctx) | 1; }
508
568
  return sass_compile_context(c_ctx, cpp_opt);
509
569
  }
510
570
 
@@ -520,7 +580,7 @@ extern "C" {
520
580
  if (*file_ctx->input_path == 0) { throw(runtime_error("File context has empty input path")); }
521
581
  cpp_opt.entry_point(file_ctx->input_path);
522
582
  }
523
- catch (...) { return handle_errors(c_ctx) || 1; }
583
+ catch (...) { return handle_errors(c_ctx) | 1; }
524
584
  return sass_compile_context(c_ctx, cpp_opt);
525
585
  }
526
586
 
@@ -557,7 +617,7 @@ extern "C" {
557
617
  // compile the parsed root block
558
618
  try { compiler->c_ctx->output_string = cpp_ctx->compile_block(root); }
559
619
  // pass catched errors to generic error handler
560
- catch (...) { return handle_errors(compiler->c_ctx) || 1; }
620
+ catch (...) { return handle_errors(compiler->c_ctx) | 1; }
561
621
  // generate source map json and store on context
562
622
  compiler->c_ctx->source_map_string = cpp_ctx->generate_source_map();
563
623
  // success
@@ -576,7 +636,19 @@ extern "C" {
576
636
  ++this_func_data;
577
637
  }
578
638
  }
579
- // Free custom importer
639
+ // Deallocate inc paths
640
+ if (options->plugin_paths) {
641
+ struct string_list* cur;
642
+ struct string_list* next;
643
+ cur = options->plugin_paths;
644
+ while (cur) {
645
+ next = cur->next;
646
+ free(cur->string);
647
+ free(cur);
648
+ cur = next;
649
+ }
650
+ }
651
+ // Deallocate inc paths
580
652
  if (options->include_paths) {
581
653
  struct string_list* cur;
582
654
  struct string_list* next;
@@ -595,6 +667,7 @@ extern "C" {
595
667
  // Make it null terminated
596
668
  options->importer = 0;
597
669
  options->c_functions = 0;
670
+ options->plugin_paths = 0;
598
671
  options->include_paths = 0;
599
672
  }
600
673
 
@@ -603,29 +676,31 @@ extern "C" {
603
676
  static void sass_clear_context (struct Sass_Context* ctx)
604
677
  {
605
678
  if (ctx == 0) return;
606
- // release the allocated memory (mostly via strdup)
679
+ // release the allocated memory (mostly via sass_strdup)
607
680
  if (ctx->output_string) free(ctx->output_string);
608
681
  if (ctx->source_map_string) free(ctx->source_map_string);
609
682
  if (ctx->error_message) free(ctx->error_message);
683
+ if (ctx->error_text) free(ctx->error_text);
610
684
  if (ctx->error_json) free(ctx->error_json);
611
685
  if (ctx->error_file) free(ctx->error_file);
612
686
  if (ctx->input_path) free(ctx->input_path);
613
687
  if (ctx->output_path) free(ctx->output_path);
614
- if (ctx->image_path) free(ctx->image_path);
615
688
  if (ctx->include_path) free(ctx->include_path);
616
689
  if (ctx->source_map_file) free(ctx->source_map_file);
690
+ if (ctx->source_map_root) free(ctx->source_map_root);
617
691
  free_string_array(ctx->included_files);
618
692
  // play safe and reset properties
619
693
  ctx->output_string = 0;
620
694
  ctx->source_map_string = 0;
621
695
  ctx->error_message = 0;
696
+ ctx->error_text = 0;
622
697
  ctx->error_json = 0;
623
698
  ctx->error_file = 0;
624
699
  ctx->input_path = 0;
625
700
  ctx->output_path = 0;
626
- ctx->image_path = 0;
627
701
  ctx->include_path = 0;
628
702
  ctx->source_map_file = 0;
703
+ ctx->source_map_root = 0;
629
704
  ctx->included_files = 0;
630
705
  // now clear the options
631
706
  sass_clear_options(ctx);
@@ -665,16 +740,20 @@ extern "C" {
665
740
  IMPLEMENT_SASS_OPTION_ACCESSOR(bool, is_indented_syntax_src);
666
741
  IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_C_Function_List, c_functions);
667
742
  IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_C_Import_Callback, importer);
743
+ IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, indent);
744
+ IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, linefeed);
668
745
  IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, input_path);
669
746
  IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, output_path);
670
- IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, image_path);
747
+ IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, plugin_path);
671
748
  IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, include_path);
672
749
  IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file);
750
+ IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_root);
673
751
 
674
752
  // Create getter and setters for context
675
753
  IMPLEMENT_SASS_CONTEXT_GETTER(int, error_status);
676
754
  IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_json);
677
755
  IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_message);
756
+ IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_text);
678
757
  IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_file);
679
758
  IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_line);
680
759
  IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_column);
@@ -685,6 +764,7 @@ extern "C" {
685
764
  // Take ownership of memory (value on context is set to 0)
686
765
  IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_json);
687
766
  IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_message);
767
+ IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_text);
688
768
  IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_file);
689
769
  IMPLEMENT_SASS_CONTEXT_TAKER(char*, output_string);
690
770
  IMPLEMENT_SASS_CONTEXT_TAKER(char*, source_map_string);
@@ -695,7 +775,7 @@ extern "C" {
695
775
 
696
776
  struct string_list* include_path = (struct string_list*) calloc(1, sizeof(struct string_list));
697
777
  if (include_path == 0) return;
698
- include_path->string = strdup(path);
778
+ include_path->string = path ? sass_strdup(path) : 0;
699
779
  struct string_list* last = options->include_paths;
700
780
  if (!options->include_paths) {
701
781
  options->include_paths = include_path;
@@ -706,4 +786,23 @@ extern "C" {
706
786
  }
707
787
 
708
788
  }
789
+
790
+ // Push function for plugin paths (no manipulation support for now)
791
+ void ADDCALL sass_option_push_plugin_path(struct Sass_Options* options, const char* path)
792
+ {
793
+
794
+ struct string_list* plugin_path = (struct string_list*) calloc(1, sizeof(struct string_list));
795
+ if (plugin_path == 0) return;
796
+ plugin_path->string = path ? sass_strdup(path) : 0;
797
+ struct string_list* last = options->plugin_paths;
798
+ if (!options->plugin_paths) {
799
+ options->plugin_paths = plugin_path;
800
+ } else {
801
+ while (last->next)
802
+ last = last->next;
803
+ last->next = plugin_path;
804
+ }
805
+
806
+ }
807
+
709
808
  }