sassc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +15 -0
  3. data/.gitmodules +3 -0
  4. data/.travis.yml +9 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +24 -0
  8. data/Rakefile +21 -0
  9. data/ext/libsass/.editorconfig +15 -0
  10. data/ext/libsass/.gitattributes +2 -0
  11. data/ext/libsass/.gitignore +61 -0
  12. data/ext/libsass/.travis.yml +38 -0
  13. data/ext/libsass/COPYING +25 -0
  14. data/ext/libsass/INSTALL +1 -0
  15. data/ext/libsass/LICENSE +25 -0
  16. data/ext/libsass/Makefile +223 -0
  17. data/ext/libsass/Makefile.am +145 -0
  18. data/ext/libsass/Readme.md +93 -0
  19. data/ext/libsass/appveyor.yml +76 -0
  20. data/ext/libsass/ast.cpp +581 -0
  21. data/ext/libsass/ast.hpp +1949 -0
  22. data/ext/libsass/ast_def_macros.hpp +16 -0
  23. data/ext/libsass/ast_factory.hpp +87 -0
  24. data/ext/libsass/ast_fwd_decl.hpp +72 -0
  25. data/ext/libsass/b64/cencode.h +32 -0
  26. data/ext/libsass/b64/encode.h +77 -0
  27. data/ext/libsass/backtrace.hpp +81 -0
  28. data/ext/libsass/base64vlq.cpp +43 -0
  29. data/ext/libsass/base64vlq.hpp +28 -0
  30. data/ext/libsass/bind.cpp +187 -0
  31. data/ext/libsass/bind.hpp +18 -0
  32. data/ext/libsass/cencode.c +102 -0
  33. data/ext/libsass/color_names.hpp +324 -0
  34. data/ext/libsass/configure.ac +130 -0
  35. data/ext/libsass/constants.cpp +144 -0
  36. data/ext/libsass/constants.hpp +145 -0
  37. data/ext/libsass/context.cpp +507 -0
  38. data/ext/libsass/context.hpp +150 -0
  39. data/ext/libsass/contextualize.cpp +157 -0
  40. data/ext/libsass/contextualize.hpp +65 -0
  41. data/ext/libsass/copy_c_str.cpp +13 -0
  42. data/ext/libsass/copy_c_str.hpp +5 -0
  43. data/ext/libsass/debug.hpp +39 -0
  44. data/ext/libsass/environment.hpp +75 -0
  45. data/ext/libsass/error_handling.cpp +28 -0
  46. data/ext/libsass/error_handling.hpp +28 -0
  47. data/ext/libsass/eval.cpp +1149 -0
  48. data/ext/libsass/eval.hpp +80 -0
  49. data/ext/libsass/expand.cpp +430 -0
  50. data/ext/libsass/expand.hpp +77 -0
  51. data/ext/libsass/extconf.rb +6 -0
  52. data/ext/libsass/extend.cpp +1962 -0
  53. data/ext/libsass/extend.hpp +50 -0
  54. data/ext/libsass/file.cpp +291 -0
  55. data/ext/libsass/file.hpp +18 -0
  56. data/ext/libsass/functions.cpp +1565 -0
  57. data/ext/libsass/functions.hpp +187 -0
  58. data/ext/libsass/inspect.cpp +727 -0
  59. data/ext/libsass/inspect.hpp +108 -0
  60. data/ext/libsass/json.cpp +1411 -0
  61. data/ext/libsass/json.hpp +117 -0
  62. data/ext/libsass/kwd_arg_macros.hpp +23 -0
  63. data/ext/libsass/m4/.gitkeep +0 -0
  64. data/ext/libsass/mapping.hpp +17 -0
  65. data/ext/libsass/memory_manager.hpp +54 -0
  66. data/ext/libsass/node.cpp +251 -0
  67. data/ext/libsass/node.hpp +122 -0
  68. data/ext/libsass/operation.hpp +153 -0
  69. data/ext/libsass/output_compressed.cpp +401 -0
  70. data/ext/libsass/output_compressed.hpp +95 -0
  71. data/ext/libsass/output_nested.cpp +364 -0
  72. data/ext/libsass/output_nested.hpp +108 -0
  73. data/ext/libsass/parser.cpp +2016 -0
  74. data/ext/libsass/parser.hpp +264 -0
  75. data/ext/libsass/paths.hpp +69 -0
  76. data/ext/libsass/position.hpp +22 -0
  77. data/ext/libsass/posix/getopt.c +562 -0
  78. data/ext/libsass/posix/getopt.h +95 -0
  79. data/ext/libsass/prelexer.cpp +688 -0
  80. data/ext/libsass/prelexer.hpp +513 -0
  81. data/ext/libsass/remove_placeholders.cpp +59 -0
  82. data/ext/libsass/remove_placeholders.hpp +43 -0
  83. data/ext/libsass/res/resource.rc +35 -0
  84. data/ext/libsass/sass.cpp +33 -0
  85. data/ext/libsass/sass.h +60 -0
  86. data/ext/libsass/sass2scss.cpp +834 -0
  87. data/ext/libsass/sass2scss.h +110 -0
  88. data/ext/libsass/sass_context.cpp +709 -0
  89. data/ext/libsass/sass_context.h +120 -0
  90. data/ext/libsass/sass_functions.cpp +137 -0
  91. data/ext/libsass/sass_functions.h +90 -0
  92. data/ext/libsass/sass_interface.cpp +277 -0
  93. data/ext/libsass/sass_interface.h +97 -0
  94. data/ext/libsass/sass_util.cpp +136 -0
  95. data/ext/libsass/sass_util.hpp +259 -0
  96. data/ext/libsass/sass_values.cpp +337 -0
  97. data/ext/libsass/sass_values.h +124 -0
  98. data/ext/libsass/script/bootstrap +10 -0
  99. data/ext/libsass/script/branding +10 -0
  100. data/ext/libsass/script/ci-build-libsass +72 -0
  101. data/ext/libsass/script/ci-install-compiler +4 -0
  102. data/ext/libsass/script/ci-install-deps +19 -0
  103. data/ext/libsass/script/ci-report-coverage +25 -0
  104. data/ext/libsass/script/coveralls-debug +32 -0
  105. data/ext/libsass/script/spec +5 -0
  106. data/ext/libsass/script/tap-driver +652 -0
  107. data/ext/libsass/script/tap-runner +1 -0
  108. data/ext/libsass/source_map.cpp +133 -0
  109. data/ext/libsass/source_map.hpp +46 -0
  110. data/ext/libsass/subset_map.hpp +145 -0
  111. data/ext/libsass/support/libsass.pc.in +11 -0
  112. data/ext/libsass/test-driver +127 -0
  113. data/ext/libsass/test/test_node.cpp +98 -0
  114. data/ext/libsass/test/test_paths.cpp +29 -0
  115. data/ext/libsass/test/test_selector_difference.cpp +28 -0
  116. data/ext/libsass/test/test_specificity.cpp +28 -0
  117. data/ext/libsass/test/test_subset_map.cpp +472 -0
  118. data/ext/libsass/test/test_superselector.cpp +71 -0
  119. data/ext/libsass/test/test_unification.cpp +33 -0
  120. data/ext/libsass/to_c.cpp +61 -0
  121. data/ext/libsass/to_c.hpp +44 -0
  122. data/ext/libsass/to_string.cpp +29 -0
  123. data/ext/libsass/to_string.hpp +32 -0
  124. data/ext/libsass/token.hpp +32 -0
  125. data/ext/libsass/units.cpp +54 -0
  126. data/ext/libsass/units.hpp +10 -0
  127. data/ext/libsass/utf8.h +34 -0
  128. data/ext/libsass/utf8/checked.h +327 -0
  129. data/ext/libsass/utf8/core.h +329 -0
  130. data/ext/libsass/utf8/unchecked.h +228 -0
  131. data/ext/libsass/utf8_string.cpp +102 -0
  132. data/ext/libsass/utf8_string.hpp +36 -0
  133. data/ext/libsass/util.cpp +189 -0
  134. data/ext/libsass/util.hpp +26 -0
  135. data/ext/libsass/win/libsass.filters +291 -0
  136. data/ext/libsass/win/libsass.sln +28 -0
  137. data/ext/libsass/win/libsass.vcxproj +255 -0
  138. data/lib/sassc.rb +6 -0
  139. data/lib/sassc/engine.rb +13 -0
  140. data/lib/sassc/native.rb +44 -0
  141. data/lib/sassc/native/native_context_api.rb +140 -0
  142. data/lib/sassc/native/native_functions_api.rb +41 -0
  143. data/lib/sassc/native/sass_input_style.rb +11 -0
  144. data/lib/sassc/native/sass_output_style.rb +10 -0
  145. data/lib/sassc/native/sass_value.rb +95 -0
  146. data/lib/sassc/native/string_list.rb +8 -0
  147. data/lib/sassc/version.rb +3 -0
  148. data/sassc.gemspec +43 -0
  149. data/test/smoke_test.rb +171 -0
  150. data/test/test_helper.rb +4 -0
  151. metadata +281 -0
@@ -0,0 +1,110 @@
1
+ #ifdef _WIN32
2
+
3
+ /* You should define ADD_EXPORTS *only* when building the DLL. */
4
+ #ifdef ADD_EXPORTS
5
+ #define ADDAPI __declspec(dllexport)
6
+ #define ADDCALL __cdecl
7
+ #else
8
+ #define ADDAPI
9
+ #define ADDCALL
10
+ #endif
11
+
12
+ #else /* _WIN32 not defined. */
13
+
14
+ /* Define with no value on non-Windows OSes. */
15
+ #define ADDAPI
16
+ #define ADDCALL
17
+
18
+ #endif
19
+
20
+ #ifdef __cplusplus
21
+
22
+ #include <stack>
23
+ #include <string>
24
+ #include <cstring>
25
+ #include <sstream>
26
+ #include <iostream>
27
+
28
+ #ifndef SASS2SCSS_VERSION
29
+ #define SASS2SCSS_VERSION "1.0.3"
30
+ #endif
31
+
32
+ // using std::string
33
+ using namespace std;
34
+
35
+ // add namespace for c++
36
+ namespace Sass
37
+ {
38
+
39
+ // pretty print options
40
+ const int SASS2SCSS_PRETTIFY_0 = 0;
41
+ const int SASS2SCSS_PRETTIFY_1 = 1;
42
+ const int SASS2SCSS_PRETTIFY_2 = 2;
43
+ const int SASS2SCSS_PRETTIFY_3 = 3;
44
+
45
+ // remove one-line comment
46
+ const int SASS2SCSS_KEEP_COMMENT = 32;
47
+ // remove multi-line comments
48
+ const int SASS2SCSS_STRIP_COMMENT = 64;
49
+ // convert one-line to multi-line
50
+ const int SASS2SCSS_CONVERT_COMMENT = 128;
51
+
52
+ // String for finding something interesting
53
+ const string SASS2SCSS_FIND_WHITESPACE = " \t\n\v\f\r";
54
+
55
+ // converter struct
56
+ // holding all states
57
+ struct converter
58
+ {
59
+ // bit options
60
+ int options;
61
+ // is selector
62
+ bool selector;
63
+ // concat lists
64
+ bool comma;
65
+ // has property
66
+ bool property;
67
+ // has semicolon
68
+ bool semicolon;
69
+ // comment context
70
+ string comment;
71
+ // flag end of file
72
+ bool end_of_file;
73
+ // whitespace buffer
74
+ string whitespace;
75
+ // context/block stack
76
+ stack<string> indents;
77
+ };
78
+
79
+ // function only available in c++ code
80
+ char* sass2scss (const string sass, const int options);
81
+
82
+ }
83
+ // EO namespace
84
+
85
+ // declare for c
86
+ extern "C" {
87
+ #endif
88
+
89
+ // prettyfy print options
90
+ #define SASS2SCSS_PRETTIFY_0 0
91
+ #define SASS2SCSS_PRETTIFY_1 1
92
+ #define SASS2SCSS_PRETTIFY_2 2
93
+ #define SASS2SCSS_PRETTIFY_3 3
94
+
95
+ // keep one-line comments
96
+ #define SASS2SCSS_KEEP_COMMENT 32
97
+ // remove multi-line comments
98
+ #define SASS2SCSS_STRIP_COMMENT 64
99
+ // convert one-line to multi-line
100
+ #define SASS2SCSS_CONVERT_COMMENT 128
101
+
102
+ // available to c and c++ code
103
+ ADDAPI char* ADDCALL sass2scss (const char* sass, const int options);
104
+
105
+ // Get compiled sass2scss version
106
+ ADDAPI const char* ADDCALL sass2scss_version(void);
107
+
108
+ #ifdef __cplusplus
109
+ } // __cplusplus defined.
110
+ #endif
@@ -0,0 +1,709 @@
1
+ #ifdef _WIN32
2
+ #include <io.h>
3
+ #else
4
+ #include <unistd.h>
5
+ #endif
6
+
7
+ #include <stdexcept>
8
+ #include "json.hpp"
9
+ #include "context.hpp"
10
+ #include "sass_values.h"
11
+ #include "sass_context.h"
12
+
13
+ extern "C" {
14
+ using namespace std;
15
+ using namespace Sass;
16
+
17
+ // Input behaviours
18
+ enum Sass_Input_Style {
19
+ SASS_CONTEXT_NULL,
20
+ SASS_CONTEXT_FILE,
21
+ SASS_CONTEXT_DATA,
22
+ SASS_CONTEXT_FOLDER
23
+ };
24
+
25
+ // simple linked list
26
+ struct string_list {
27
+ string_list* next;
28
+ char* string;
29
+ };
30
+
31
+ // sass config options structure
32
+ struct Sass_Options {
33
+
34
+ // Precision for fractional numbers
35
+ int precision;
36
+
37
+ // Output style for the generated css code
38
+ // A value from above SASS_STYLE_* constants
39
+ enum Sass_Output_Style output_style;
40
+
41
+ // Emit comments in the generated CSS indicating
42
+ // the corresponding source line.
43
+ bool source_comments;
44
+
45
+ // embed sourceMappingUrl as data uri
46
+ bool source_map_embed;
47
+
48
+ // embed include contents in maps
49
+ bool source_map_contents;
50
+
51
+ // Disable sourceMappingUrl in css output
52
+ bool omit_source_map_url;
53
+
54
+ // Treat source_string as sass (as opposed to scss)
55
+ bool is_indented_syntax_src;
56
+
57
+ // The input path is used for source map
58
+ // generation. It can be used to define
59
+ // something with string compilation or to
60
+ // overload the input file path. It is
61
+ // set to "stdin" for data contexts and
62
+ // to the input file on file contexts.
63
+ char* input_path;
64
+
65
+ // The output path is used for source map
66
+ // generation. Libsass will not write to
67
+ // this file, it is just used to create
68
+ // information in source-maps etc.
69
+ char* output_path;
70
+
71
+ // For the image-url Sass function
72
+ char* image_path;
73
+
74
+ // Colon-separated list of paths
75
+ // Semicolon-separated on Windows
76
+ // Maybe use array interface instead?
77
+ char* include_path;
78
+
79
+ // Include path (linked string list)
80
+ struct string_list* include_paths;
81
+
82
+ // Path to source map file
83
+ // Enables source map generation
84
+ // Used to create sourceMappingUrl
85
+ char* source_map_file;
86
+
87
+ // Custom functions that can be called from sccs code
88
+ Sass_C_Function_List c_functions;
89
+
90
+ // Callback to overload imports
91
+ Sass_C_Import_Callback importer;
92
+
93
+ };
94
+
95
+ // base for all contexts
96
+ struct Sass_Context : Sass_Options
97
+ {
98
+
99
+ // store context type info
100
+ enum Sass_Input_Style type;
101
+
102
+ // generated output data
103
+ char* output_string;
104
+
105
+ // generated source map json
106
+ char* source_map_string;
107
+
108
+ // error status
109
+ int error_status;
110
+ char* error_json;
111
+ char* error_message;
112
+ // error position
113
+ char* error_file;
114
+ size_t error_line;
115
+ size_t error_column;
116
+
117
+ // report imported files
118
+ char** included_files;
119
+
120
+ };
121
+
122
+ // struct for file compilation
123
+ struct Sass_File_Context : Sass_Context {
124
+
125
+ // no additional fields required
126
+ // input_path is already on options
127
+
128
+ };
129
+
130
+ // struct for data compilation
131
+ struct Sass_Data_Context : Sass_Context {
132
+
133
+ // provided source string
134
+ char* source_string;
135
+
136
+ };
137
+
138
+ // Compiler states
139
+ enum Sass_Compiler_State {
140
+ SASS_COMPILER_CREATED,
141
+ SASS_COMPILER_PARSED,
142
+ SASS_COMPILER_EXECUTED
143
+ };
144
+
145
+ // link c and cpp context
146
+ struct Sass_Compiler {
147
+ // progress status
148
+ Sass_Compiler_State state;
149
+ // original c context
150
+ Sass_Context* c_ctx;
151
+ // Sass::Context
152
+ void* cpp_ctx;
153
+ // Sass::Block
154
+ void* root;
155
+ };
156
+
157
+ static void copy_options(struct Sass_Options* to, struct Sass_Options* from) { *to = *from; }
158
+
159
+ #define IMPLEMENT_SASS_OPTION_ACCESSOR(type, option) \
160
+ type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return options->option; } \
161
+ void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) { options->option = option; }
162
+ #define IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(type, option) \
163
+ type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return options->option; } \
164
+ void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) \
165
+ { free(options->option); options->option = option ? strdup(option) : 0; }
166
+
167
+ #define IMPLEMENT_SASS_CONTEXT_GETTER(type, option) \
168
+ type ADDCALL sass_context_get_##option (struct Sass_Context* ctx) { return ctx->option; }
169
+ #define IMPLEMENT_SASS_CONTEXT_TAKER(type, option) \
170
+ type sass_context_take_##option (struct Sass_Context* ctx) \
171
+ { type foo = ctx->option; ctx->option = 0; return foo; }
172
+
173
+ // helper for safe access to c_ctx
174
+ static const char* safe_str (const char* str) {
175
+ return str == NULL ? "" : str;
176
+ }
177
+
178
+ static void copy_strings(const std::vector<std::string>& strings, char*** array, int skip = 0) {
179
+ int num = static_cast<int>(strings.size());
180
+ char** arr = (char**) malloc(sizeof(char*) * (num + 1));
181
+ if (arr == 0) throw(bad_alloc());
182
+
183
+ for(int i = skip; i < num; i++) {
184
+ arr[i-skip] = (char*) malloc(sizeof(char) * (strings[i].size() + 1));
185
+ if (arr[i-skip] == 0) throw(bad_alloc());
186
+ std::copy(strings[i].begin(), strings[i].end(), arr[i-skip]);
187
+ arr[i-skip][strings[i].size()] = '\0';
188
+ }
189
+
190
+ arr[num-skip] = 0;
191
+ *array = arr;
192
+ }
193
+
194
+ static void free_string_array(char ** arr) {
195
+ if(!arr)
196
+ return;
197
+
198
+ char **it = arr;
199
+ while (it && (*it)) {
200
+ free(*it);
201
+ ++it;
202
+ }
203
+
204
+ free(arr);
205
+ }
206
+
207
+ static int handle_errors(Sass_Context* c_ctx) {
208
+ try {
209
+ throw;
210
+ }
211
+ catch (Sass_Error& e) {
212
+ stringstream msg_stream;
213
+ JsonNode* json_err = json_mkobject();
214
+ 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));
218
+ json_append_member(json_err, "message", json_mkstring(e.message.c_str()));
219
+ msg_stream << e.path << ":" << e.position.line << ": " << e.message << endl;
220
+ c_ctx->error_json = json_stringify(json_err, " ");;
221
+ c_ctx->error_message = strdup(msg_stream.str().c_str());
222
+ 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;
226
+ c_ctx->output_string = 0;
227
+ c_ctx->source_map_string = 0;
228
+ json_delete(json_err);
229
+ }
230
+ catch(bad_alloc& ba) {
231
+ stringstream msg_stream;
232
+ JsonNode* json_err = json_mkobject();
233
+ msg_stream << "Unable to allocate memory: " << ba.what() << endl;
234
+ json_append_member(json_err, "status", json_mknumber(2));
235
+ json_append_member(json_err, "message", json_mkstring(ba.what()));
236
+ c_ctx->error_json = json_stringify(json_err, " ");;
237
+ c_ctx->error_message = strdup(msg_stream.str().c_str());
238
+ c_ctx->error_status = 2;
239
+ c_ctx->output_string = 0;
240
+ c_ctx->source_map_string = 0;
241
+ json_delete(json_err);
242
+ }
243
+ catch (std::exception& e) {
244
+ stringstream msg_stream;
245
+ JsonNode* json_err = json_mkobject();
246
+ msg_stream << "Error: " << e.what() << endl;
247
+ json_append_member(json_err, "status", json_mknumber(3));
248
+ json_append_member(json_err, "message", json_mkstring(e.what()));
249
+ c_ctx->error_json = json_stringify(json_err, " ");;
250
+ c_ctx->error_message = strdup(msg_stream.str().c_str());
251
+ c_ctx->error_status = 3;
252
+ c_ctx->output_string = 0;
253
+ c_ctx->source_map_string = 0;
254
+ json_delete(json_err);
255
+ }
256
+ catch (string& e) {
257
+ stringstream msg_stream;
258
+ JsonNode* json_err = json_mkobject();
259
+ msg_stream << "Error: " << e << endl;
260
+ json_append_member(json_err, "status", json_mknumber(4));
261
+ json_append_member(json_err, "message", json_mkstring(e.c_str()));
262
+ c_ctx->error_json = json_stringify(json_err, " ");;
263
+ c_ctx->error_message = strdup(msg_stream.str().c_str());
264
+ c_ctx->error_status = 4;
265
+ c_ctx->output_string = 0;
266
+ c_ctx->source_map_string = 0;
267
+ json_delete(json_err);
268
+ }
269
+ catch (...) {
270
+ stringstream msg_stream;
271
+ JsonNode* json_err = json_mkobject();
272
+ msg_stream << "Unknown error occurred" << endl;
273
+ json_append_member(json_err, "status", json_mknumber(5));
274
+ json_append_member(json_err, "message", json_mkstring("unknown"));
275
+ c_ctx->error_json = json_stringify(json_err, " ");;
276
+ c_ctx->error_message = strdup(msg_stream.str().c_str());
277
+ c_ctx->error_status = 5;
278
+ c_ctx->output_string = 0;
279
+ c_ctx->source_map_string = 0;
280
+ json_delete(json_err);
281
+ }
282
+ return c_ctx->error_status;
283
+ }
284
+
285
+ // generic compilation function (not exported, use file/data compile instead)
286
+ static Context* sass_prepare_context (Sass_Context* c_ctx, Context::Data cpp_opt)
287
+ {
288
+ try {
289
+
290
+ // get input/output path from options
291
+ string input_path = safe_str(c_ctx->input_path);
292
+ string output_path = safe_str(c_ctx->output_path);
293
+ // maybe we can extract an output path from input path
294
+ if (output_path == "" && input_path != "") {
295
+ int lastindex = static_cast<int>(input_path.find_last_of("."));
296
+ output_path = (lastindex > -1 ? input_path.substr(0, lastindex) : input_path) + ".css";
297
+ }
298
+
299
+ // convert include path linked list to static array
300
+ struct string_list* cur = c_ctx->include_paths;
301
+ // very poor loop to get the length of the linked list
302
+ size_t length = 0; while (cur) { length ++; cur = cur->next; }
303
+ // create char* array to hold all paths plus null terminator
304
+ const char** include_paths = (const char**) calloc(length + 1, sizeof(char*));
305
+ if (include_paths == 0) throw(bad_alloc());
306
+ // reset iterator
307
+ cur = c_ctx->include_paths;
308
+ // copy over the paths
309
+ for (size_t i = 0; cur; i++) {
310
+ include_paths[i] = cur->string;
311
+ cur = cur->next;
312
+ }
313
+ // transfer the options to c++
314
+ cpp_opt.input_path(input_path)
315
+ .output_path(output_path)
316
+ .output_style((Output_Style) c_ctx->output_style)
317
+ .is_indented_syntax_src(c_ctx->is_indented_syntax_src)
318
+ .source_comments(c_ctx->source_comments)
319
+ .source_map_file(safe_str(c_ctx->source_map_file))
320
+ .source_map_embed(c_ctx->source_map_embed)
321
+ .source_map_contents(c_ctx->source_map_contents)
322
+ .omit_source_map_url(c_ctx->omit_source_map_url)
323
+ .image_path(safe_str(c_ctx->image_path))
324
+ .include_paths_c_str(c_ctx->include_path)
325
+ .importer(c_ctx->importer)
326
+ .include_paths_array(include_paths)
327
+ .include_paths(vector<string>())
328
+ .precision(c_ctx->precision ? c_ctx->precision : 5);
329
+
330
+ // create new c++ Context
331
+ Context* cpp_ctx = new Context(cpp_opt);
332
+ // free intermediate data
333
+ free(include_paths);
334
+
335
+ // register our custom functions
336
+ if (c_ctx->c_functions) {
337
+ Sass_C_Function_List this_func_data = c_ctx->c_functions;
338
+ while ((this_func_data) && (*this_func_data)) {
339
+ cpp_ctx->c_functions.push_back((*this_func_data));
340
+ ++this_func_data;
341
+ }
342
+ }
343
+
344
+ // reset error status
345
+ c_ctx->error_json = 0;
346
+ c_ctx->error_message = 0;
347
+ c_ctx->error_status = 0;
348
+ // reset error position
349
+ c_ctx->error_file = 0;
350
+ c_ctx->error_line = -1;
351
+ c_ctx->error_column = -1;
352
+
353
+ // use to parse block
354
+ return cpp_ctx;
355
+
356
+ }
357
+ // pass errors to generic error handler
358
+ catch (...) { handle_errors(c_ctx); }
359
+
360
+ // error
361
+ return 0;
362
+
363
+ }
364
+
365
+ static Block* sass_parse_block (Sass_Context* c_ctx, Context* cpp_ctx)
366
+ {
367
+ try {
368
+
369
+ // get input/output path from options
370
+ string input_path = safe_str(c_ctx->input_path);
371
+ string output_path = safe_str(c_ctx->output_path);
372
+
373
+ // parsed root block
374
+ Block* root = 0;
375
+
376
+ // maybe skip some entries of included files
377
+ // we do not include stdin for data contexts
378
+ size_t skip = 0;
379
+
380
+ // dispatch to the correct render function
381
+ if (c_ctx->type == SASS_CONTEXT_FILE) {
382
+ root = cpp_ctx->parse_file();
383
+ } else if (c_ctx->type == SASS_CONTEXT_DATA) {
384
+ root = cpp_ctx->parse_string();
385
+ skip = 1; // skip first entry of includes
386
+ }
387
+
388
+ // 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);
390
+
391
+ // return parsed block
392
+ return root;
393
+
394
+ }
395
+ // pass errors to generic error handler
396
+ catch (...) { handle_errors(c_ctx); }
397
+
398
+ // error
399
+ return 0;
400
+
401
+ }
402
+
403
+ // generic compilation function (not exported, use file/data compile instead)
404
+ static int sass_compile_context (Sass_Context* c_ctx, Context::Data cpp_opt)
405
+ {
406
+
407
+ // first prepare the c++ context
408
+ Context* cpp_ctx = sass_prepare_context(c_ctx, cpp_opt);
409
+
410
+ // parse given context and return root block
411
+ Block* root = cpp_ctx ? sass_parse_block(c_ctx, cpp_ctx) : 0;
412
+
413
+ if (cpp_ctx && root) {
414
+
415
+ try {
416
+
417
+ // now compile the parsed root block
418
+ c_ctx->output_string = cpp_ctx->compile_block(root);
419
+
420
+ // generate source map json and store on context
421
+ c_ctx->source_map_string = cpp_ctx->generate_source_map();
422
+
423
+ }
424
+ // pass errors to generic error handler
425
+ catch (...) { handle_errors(c_ctx); }
426
+
427
+ }
428
+
429
+ delete cpp_ctx;
430
+
431
+ return c_ctx->error_status;
432
+ }
433
+
434
+ Sass_Options* ADDCALL sass_make_options (void)
435
+ {
436
+ return (struct Sass_Options*) calloc(1, sizeof(struct Sass_Options));
437
+ }
438
+
439
+ Sass_File_Context* ADDCALL sass_make_file_context(const char* input_path)
440
+ {
441
+ struct Sass_File_Context* ctx = (struct Sass_File_Context*) calloc(1, sizeof(struct Sass_File_Context));
442
+ if (ctx == 0) { cerr << "Error allocating memory for file context" << endl; return 0; }
443
+ ctx->type = SASS_CONTEXT_FILE;
444
+ try {
445
+ if (input_path == 0) { throw(runtime_error("File context created without an input path")); }
446
+ if (*input_path == 0) { throw(runtime_error("File context created with empty input path")); }
447
+ sass_option_set_input_path(ctx, input_path);
448
+ } catch (...) {
449
+ handle_errors(ctx);
450
+ }
451
+ return ctx;
452
+ }
453
+
454
+ Sass_Data_Context* ADDCALL sass_make_data_context(char* source_string)
455
+ {
456
+ struct Sass_Data_Context* ctx = (struct Sass_Data_Context*) calloc(1, sizeof(struct Sass_Data_Context));
457
+ if (ctx == 0) { cerr << "Error allocating memory for data context" << endl; return 0; }
458
+ ctx->type = SASS_CONTEXT_DATA;
459
+ try {
460
+ if (source_string == 0) { throw(runtime_error("Data context created without a source string")); }
461
+ if (*source_string == 0) { throw(runtime_error("Data context created with empty source string")); }
462
+ ctx->source_string = source_string;
463
+ } catch (...) {
464
+ handle_errors(ctx);
465
+ }
466
+ return ctx;
467
+ }
468
+
469
+ struct Sass_Compiler* ADDCALL sass_make_file_compiler (struct Sass_File_Context* c_ctx)
470
+ {
471
+ if (c_ctx == 0) return 0;
472
+ struct Sass_Compiler* compiler = (struct Sass_Compiler*) calloc(1, sizeof(struct Sass_Compiler));
473
+ if (compiler == 0) { cerr << "Error allocating memory for file compiler" << endl; return 0; }
474
+ compiler->state = SASS_COMPILER_CREATED;
475
+ compiler->c_ctx = c_ctx;
476
+ Context::Data cpp_opt = Context::Data();
477
+ cpp_opt.entry_point(c_ctx->input_path);
478
+ compiler->cpp_ctx = sass_prepare_context(c_ctx, cpp_opt);
479
+ return compiler;
480
+ }
481
+
482
+ struct Sass_Compiler* ADDCALL sass_make_data_compiler (struct Sass_Data_Context* c_ctx)
483
+ {
484
+ if (c_ctx == 0) return 0;
485
+ struct Sass_Compiler* compiler = (struct Sass_Compiler*) calloc(1, sizeof(struct Sass_Compiler));
486
+ if (compiler == 0) { cerr << "Error allocating memory for data compiler" << endl; return 0; }
487
+ compiler->state = SASS_COMPILER_CREATED;
488
+ compiler->c_ctx = c_ctx;
489
+ Context::Data cpp_opt = Context::Data();
490
+ cpp_opt.source_c_str(c_ctx->source_string);
491
+ compiler->cpp_ctx = sass_prepare_context(c_ctx, cpp_opt);
492
+ return compiler;
493
+ }
494
+
495
+ int ADDCALL sass_compile_data_context(Sass_Data_Context* data_ctx)
496
+ {
497
+ if (data_ctx == 0) return 1;
498
+ Sass_Context* c_ctx = data_ctx;
499
+ if (c_ctx->error_status)
500
+ return c_ctx->error_status;
501
+ Context::Data cpp_opt = Context::Data();
502
+ try {
503
+ if (data_ctx->source_string == 0) { throw(runtime_error("Data context has no source string")); }
504
+ if (*data_ctx->source_string == 0) { throw(runtime_error("Data context has empty source string")); }
505
+ cpp_opt.source_c_str(data_ctx->source_string);
506
+ }
507
+ catch (...) { return handle_errors(c_ctx) || 1; }
508
+ return sass_compile_context(c_ctx, cpp_opt);
509
+ }
510
+
511
+ int ADDCALL sass_compile_file_context(Sass_File_Context* file_ctx)
512
+ {
513
+ if (file_ctx == 0) return 1;
514
+ Sass_Context* c_ctx = file_ctx;
515
+ if (c_ctx->error_status)
516
+ return c_ctx->error_status;
517
+ Context::Data cpp_opt = Context::Data();
518
+ try {
519
+ if (file_ctx->input_path == 0) { throw(runtime_error("File context has no input path")); }
520
+ if (*file_ctx->input_path == 0) { throw(runtime_error("File context has empty input path")); }
521
+ cpp_opt.entry_point(file_ctx->input_path);
522
+ }
523
+ catch (...) { return handle_errors(c_ctx) || 1; }
524
+ return sass_compile_context(c_ctx, cpp_opt);
525
+ }
526
+
527
+ int ADDCALL sass_compiler_parse(struct Sass_Compiler* compiler)
528
+ {
529
+ if (compiler == 0) return 1;
530
+ if (compiler->state == SASS_COMPILER_PARSED) return 0;
531
+ if (compiler->state != SASS_COMPILER_CREATED) return -1;
532
+ if (compiler->c_ctx == NULL) return 1;
533
+ if (compiler->cpp_ctx == NULL) return 1;
534
+ if (compiler->c_ctx->error_status)
535
+ return compiler->c_ctx->error_status;
536
+ compiler->state = SASS_COMPILER_PARSED;
537
+ Context* cpp_ctx = (Context*) compiler->cpp_ctx;
538
+ // parse the context we have set up (file or data)
539
+ compiler->root = sass_parse_block(compiler->c_ctx, cpp_ctx);
540
+ // success
541
+ return 0;
542
+ }
543
+
544
+ int ADDCALL sass_compiler_execute(struct Sass_Compiler* compiler)
545
+ {
546
+ if (compiler == 0) return 1;
547
+ if (compiler->state == SASS_COMPILER_EXECUTED) return 0;
548
+ if (compiler->state != SASS_COMPILER_PARSED) return -1;
549
+ if (compiler->c_ctx == NULL) return 1;
550
+ if (compiler->cpp_ctx == NULL) return 1;
551
+ if (compiler->root == NULL) return 1;
552
+ if (compiler->c_ctx->error_status)
553
+ return compiler->c_ctx->error_status;
554
+ compiler->state = SASS_COMPILER_EXECUTED;
555
+ Context* cpp_ctx = (Context*) compiler->cpp_ctx;
556
+ Block* root = (Block*) compiler->root;
557
+ // compile the parsed root block
558
+ try { compiler->c_ctx->output_string = cpp_ctx->compile_block(root); }
559
+ // pass catched errors to generic error handler
560
+ catch (...) { return handle_errors(compiler->c_ctx) || 1; }
561
+ // generate source map json and store on context
562
+ compiler->c_ctx->source_map_string = cpp_ctx->generate_source_map();
563
+ // success
564
+ return 0;
565
+ }
566
+
567
+ // helper function, not exported, only accessible locally
568
+ static void sass_clear_options (struct Sass_Options* options)
569
+ {
570
+ if (options == 0) return;
571
+ // Deallocate custom functions
572
+ if (options->c_functions) {
573
+ struct Sass_C_Function_Descriptor** this_func_data = options->c_functions;
574
+ while ((this_func_data) && (*this_func_data)) {
575
+ free((*this_func_data));
576
+ ++this_func_data;
577
+ }
578
+ }
579
+ // Free custom importer
580
+ if (options->include_paths) {
581
+ struct string_list* cur;
582
+ struct string_list* next;
583
+ cur = options->include_paths;
584
+ while (cur) {
585
+ next = cur->next;
586
+ free(cur->string);
587
+ free(cur);
588
+ cur = next;
589
+ }
590
+ }
591
+ // Free custom importer
592
+ free(options->importer);
593
+ // Free the list container
594
+ free(options->c_functions);
595
+ // Make it null terminated
596
+ options->importer = 0;
597
+ options->c_functions = 0;
598
+ options->include_paths = 0;
599
+ }
600
+
601
+ // helper function, not exported, only accessible locally
602
+ // sass_free_context is also defined in old sass_interface
603
+ static void sass_clear_context (struct Sass_Context* ctx)
604
+ {
605
+ if (ctx == 0) return;
606
+ // release the allocated memory (mostly via strdup)
607
+ if (ctx->output_string) free(ctx->output_string);
608
+ if (ctx->source_map_string) free(ctx->source_map_string);
609
+ if (ctx->error_message) free(ctx->error_message);
610
+ if (ctx->error_json) free(ctx->error_json);
611
+ if (ctx->error_file) free(ctx->error_file);
612
+ if (ctx->input_path) free(ctx->input_path);
613
+ if (ctx->output_path) free(ctx->output_path);
614
+ if (ctx->image_path) free(ctx->image_path);
615
+ if (ctx->include_path) free(ctx->include_path);
616
+ if (ctx->source_map_file) free(ctx->source_map_file);
617
+ free_string_array(ctx->included_files);
618
+ // play safe and reset properties
619
+ ctx->output_string = 0;
620
+ ctx->source_map_string = 0;
621
+ ctx->error_message = 0;
622
+ ctx->error_json = 0;
623
+ ctx->error_file = 0;
624
+ ctx->input_path = 0;
625
+ ctx->output_path = 0;
626
+ ctx->image_path = 0;
627
+ ctx->include_path = 0;
628
+ ctx->source_map_file = 0;
629
+ ctx->included_files = 0;
630
+ // now clear the options
631
+ sass_clear_options(ctx);
632
+ }
633
+
634
+ void ADDCALL sass_delete_compiler (struct Sass_Compiler* compiler)
635
+ {
636
+ if (compiler == 0) return;
637
+ Context* cpp_ctx = (Context*) compiler->cpp_ctx;
638
+ compiler->cpp_ctx = 0;
639
+ delete cpp_ctx;
640
+ free(compiler);
641
+ }
642
+
643
+ // Deallocate all associated memory with contexts
644
+ void ADDCALL sass_delete_file_context (struct Sass_File_Context* ctx) { sass_clear_context(ctx); free(ctx); }
645
+ void ADDCALL sass_delete_data_context (struct Sass_Data_Context* ctx) { sass_clear_context(ctx); free(ctx); }
646
+
647
+ // Getters for sass context from specific implementations
648
+ struct Sass_Context* ADDCALL sass_file_context_get_context(struct Sass_File_Context* ctx) { return ctx; }
649
+ struct Sass_Context* ADDCALL sass_data_context_get_context(struct Sass_Data_Context* ctx) { return ctx; }
650
+
651
+ // Getters for context options from Sass_Context
652
+ struct Sass_Options* ADDCALL sass_context_get_options(struct Sass_Context* ctx) { return ctx; }
653
+ struct Sass_Options* ADDCALL sass_file_context_get_options(struct Sass_File_Context* ctx) { return ctx; }
654
+ struct Sass_Options* ADDCALL sass_data_context_get_options(struct Sass_Data_Context* ctx) { return ctx; }
655
+ void ADDCALL sass_file_context_set_options (struct Sass_File_Context* ctx, struct Sass_Options* opt) { copy_options(ctx, opt); }
656
+ void ADDCALL sass_data_context_set_options (struct Sass_Data_Context* ctx, struct Sass_Options* opt) { copy_options(ctx, opt); }
657
+
658
+ // Create getter and setters for options
659
+ IMPLEMENT_SASS_OPTION_ACCESSOR(int, precision);
660
+ IMPLEMENT_SASS_OPTION_ACCESSOR(enum Sass_Output_Style, output_style);
661
+ IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_comments);
662
+ IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_embed);
663
+ IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_contents);
664
+ IMPLEMENT_SASS_OPTION_ACCESSOR(bool, omit_source_map_url);
665
+ IMPLEMENT_SASS_OPTION_ACCESSOR(bool, is_indented_syntax_src);
666
+ IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_C_Function_List, c_functions);
667
+ IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_C_Import_Callback, importer);
668
+ IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, input_path);
669
+ IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, output_path);
670
+ IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, image_path);
671
+ IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, include_path);
672
+ IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file);
673
+
674
+ // Create getter and setters for context
675
+ IMPLEMENT_SASS_CONTEXT_GETTER(int, error_status);
676
+ IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_json);
677
+ IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_message);
678
+ IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_file);
679
+ IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_line);
680
+ IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_column);
681
+ IMPLEMENT_SASS_CONTEXT_GETTER(const char*, output_string);
682
+ IMPLEMENT_SASS_CONTEXT_GETTER(const char*, source_map_string);
683
+ IMPLEMENT_SASS_CONTEXT_GETTER(char**, included_files);
684
+
685
+ // Take ownership of memory (value on context is set to 0)
686
+ IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_json);
687
+ IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_message);
688
+ IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_file);
689
+ IMPLEMENT_SASS_CONTEXT_TAKER(char*, output_string);
690
+ IMPLEMENT_SASS_CONTEXT_TAKER(char*, source_map_string);
691
+
692
+ // Push function for include paths (no manipulation support for now)
693
+ void ADDCALL sass_option_push_include_path(struct Sass_Options* options, const char* path)
694
+ {
695
+
696
+ struct string_list* include_path = (struct string_list*) calloc(1, sizeof(struct string_list));
697
+ if (include_path == 0) return;
698
+ include_path->string = strdup(path);
699
+ struct string_list* last = options->include_paths;
700
+ if (!options->include_paths) {
701
+ options->include_paths = include_path;
702
+ } else {
703
+ while (last->next)
704
+ last = last->next;
705
+ last->next = include_path;
706
+ }
707
+
708
+ }
709
+ }