sassc 0.0.1

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 (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
+ }