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,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
  }