13 #include "context.hpp"
14 #include "sass_context.hpp"
15 #include "sass_functions.hpp"
16 #include "ast_fwd_decl.hpp"
17 #include "error_handling.hpp"
23 // see sass_copy_c_string(std::string str)
24 static inline JsonNode* json_mkstream(const std::stringstream& stream)
26 // hold on to string on stack!
27 std::string str(stream.str());
28 return json_mkstring(str.c_str());
31 static int handle_error(Sass_Context* c_ctx) {
35 catch (Exception::Base& e) {
36 std::stringstream msg_stream;
37 std::string cwd(Sass::File::get_cwd());
39 std::string msg_prefix(e.errtype());
40 bool got_newline = false;
41 msg_stream << msg_prefix << ": ";
42 const char* msg = e.what();
47 else if (*msg == '\n') {
50 else if (got_newline) {
51 msg_stream << std::string(msg_prefix.size() + 2, ' ');
57 if (!got_newline) msg_stream << "\n";
59 for (size_t i = 1; i < e.import_stack->size() - 1; ++i) {
60 std::string path((*e.import_stack)[i]->imp_path);
61 std::string rel_path(Sass::File::abs2rel(path, cwd, cwd));
62 msg_stream << std::string(msg_prefix.size() + 2, ' ');
63 msg_stream << (i == 1 ? " on line " : " from line ");
64 msg_stream << e.pstate.line + 1 << " of " << rel_path << "\n";
68 std::string rel_path(Sass::File::abs2rel(e.pstate.path, cwd, cwd));
69 msg_stream << std::string(msg_prefix.size() + 2, ' ');
70 msg_stream << " on line " << e.pstate.line + 1 << " of " << rel_path << "\n";
73 // now create the code trace (ToDo: maybe have util functions?)
74 if (e.pstate.line != std::string::npos && e.pstate.column != std::string::npos) {
75 size_t line = e.pstate.line;
76 const char* line_beg = e.pstate.src;
77 while (line_beg && *line_beg && line) {
78 if (*line_beg == '\n') --line;
81 const char* line_end = line_beg;
82 while (line_end && *line_end && *line_end != '\n') {
83 if (*line_end == '\n') break;
84 if (*line_end == '\r') break;
87 size_t max_left = 42; size_t max_right = 78;
88 size_t move_in = e.pstate.column > max_left ? e.pstate.column - max_left : 0;
89 size_t shorten = (line_end - line_beg) - move_in > max_right ?
90 (line_end - line_beg) - move_in - max_right : 0;
91 msg_stream << ">> " << std::string(line_beg + move_in, line_end - shorten) << "\n";
92 msg_stream << " " << std::string(e.pstate.column - move_in, '-') << "^\n";
95 JsonNode* json_err = json_mkobject();
96 json_append_member(json_err, "status", json_mknumber(1));
97 json_append_member(json_err, "file", json_mkstring(e.pstate.path));
98 json_append_member(json_err, "line", json_mknumber((double)(e.pstate.line + 1)));
99 json_append_member(json_err, "column", json_mknumber((double)(e.pstate.column + 1)));
100 json_append_member(json_err, "message", json_mkstring(e.what()));
101 json_append_member(json_err, "formatted", json_mkstream(msg_stream));
102 try { c_ctx->error_json = json_stringify(json_err, " "); }
104 c_ctx->error_message = sass_copy_string(msg_stream.str());
105 c_ctx->error_text = sass_copy_c_string(e.what());
106 c_ctx->error_status = 1;
107 c_ctx->error_file = sass_copy_c_string(e.pstate.path);
108 c_ctx->error_line = e.pstate.line + 1;
109 c_ctx->error_column = e.pstate.column + 1;
110 c_ctx->error_src = e.pstate.src;
111 c_ctx->output_string = 0;
112 c_ctx->source_map_string = 0;
113 json_delete(json_err);
115 catch (std::bad_alloc& ba) {
116 std::stringstream msg_stream;
117 JsonNode* json_err = json_mkobject();
118 msg_stream << "Unable to allocate memory: " << ba.what() << std::endl;
119 json_append_member(json_err, "status", json_mknumber(2));
120 json_append_member(json_err, "message", json_mkstring(ba.what()));
121 json_append_member(json_err, "formatted", json_mkstream(msg_stream));
122 try { c_ctx->error_json = json_stringify(json_err, " "); }
124 c_ctx->error_message = sass_copy_string(msg_stream.str());
125 c_ctx->error_text = sass_copy_c_string(ba.what());
126 c_ctx->error_status = 2;
127 c_ctx->output_string = 0;
128 c_ctx->source_map_string = 0;
129 json_delete(json_err);
131 catch (std::exception& e) {
132 std::stringstream msg_stream;
133 JsonNode* json_err = json_mkobject();
134 msg_stream << "Internal Error: " << e.what() << std::endl;
135 json_append_member(json_err, "status", json_mknumber(3));
136 json_append_member(json_err, "message", json_mkstring(e.what()));
137 json_append_member(json_err, "formatted", json_mkstream(msg_stream));
138 try { c_ctx->error_json = json_stringify(json_err, " "); }
140 c_ctx->error_message = sass_copy_string(msg_stream.str());
141 c_ctx->error_text = sass_copy_c_string(e.what());
142 c_ctx->error_status = 3;
143 c_ctx->output_string = 0;
144 c_ctx->source_map_string = 0;
145 json_delete(json_err);
147 catch (std::string& e) {
148 std::stringstream msg_stream;
149 JsonNode* json_err = json_mkobject();
150 msg_stream << "Internal Error: " << e << std::endl;
151 json_append_member(json_err, "status", json_mknumber(4));
152 json_append_member(json_err, "message", json_mkstring(e.c_str()));
153 json_append_member(json_err, "formatted", json_mkstream(msg_stream));
154 try { c_ctx->error_json = json_stringify(json_err, " "); }
156 c_ctx->error_message = sass_copy_string(msg_stream.str());
157 c_ctx->error_text = sass_copy_c_string(e.c_str());
158 c_ctx->error_status = 4;
159 c_ctx->output_string = 0;
160 c_ctx->source_map_string = 0;
161 json_delete(json_err);
163 catch (const char* e) {
164 std::stringstream msg_stream;
165 JsonNode* json_err = json_mkobject();
166 msg_stream << "Internal Error: " << e << std::endl;
167 json_append_member(json_err, "status", json_mknumber(4));
168 json_append_member(json_err, "message", json_mkstring(e));
169 json_append_member(json_err, "formatted", json_mkstream(msg_stream));
170 try { c_ctx->error_json = json_stringify(json_err, " "); }
172 c_ctx->error_message = sass_copy_string(msg_stream.str());
173 c_ctx->error_text = sass_copy_c_string(e);
174 c_ctx->error_status = 4;
175 c_ctx->output_string = 0;
176 c_ctx->source_map_string = 0;
177 json_delete(json_err);
180 std::stringstream msg_stream;
181 JsonNode* json_err = json_mkobject();
182 msg_stream << "Unknown error occurred" << std::endl;
183 json_append_member(json_err, "status", json_mknumber(5));
184 json_append_member(json_err, "message", json_mkstring("unknown"));
185 try { c_ctx->error_json = json_stringify(json_err, " "); }
187 c_ctx->error_message = sass_copy_string(msg_stream.str());
188 c_ctx->error_text = sass_copy_c_string("unknown");
189 c_ctx->error_status = 5;
190 c_ctx->output_string = 0;
191 c_ctx->source_map_string = 0;
192 json_delete(json_err);
194 return c_ctx->error_status;
197 // allow one error handler to throw another error
198 // this can happen with invalid utf8 and json lib
199 static int handle_errors(Sass_Context* c_ctx) {
200 try { return handle_error(c_ctx); }
201 catch (...) { return handle_error(c_ctx); }
202 return c_ctx->error_status;
205 static Block_Obj sass_parse_block(Sass_Compiler* compiler) throw()
208 // assert valid pointer
209 if (compiler == 0) return 0;
210 // The cpp context must be set by now
211 Context* cpp_ctx = compiler->cpp_ctx;
212 Sass_Context* c_ctx = compiler->c_ctx;
213 // We will take care to wire up the rest
214 compiler->cpp_ctx->c_compiler = compiler;
215 compiler->state = SASS_COMPILER_PARSED;
219 // get input/output path from options
220 std::string input_path = safe_str(c_ctx->input_path);
221 std::string output_path = safe_str(c_ctx->output_path);
223 // maybe skip some entries of included files
224 // we do not include stdin for data contexts
225 bool skip = c_ctx->type == SASS_CONTEXT_DATA;
227 // dispatch parse call
228 Block_Obj root(cpp_ctx->parse());
232 // skip all prefixed files? (ToDo: check srcmap)
233 // IMO source-maps should point to headers already
234 // therefore don't skip it for now. re-enable or
235 // remove completely once this is tested
236 size_t headers = cpp_ctx->head_imports;
238 // copy the included files on to the context (dont forget to free later)
239 if (copy_strings(cpp_ctx->get_included_files(skip, headers), &c_ctx->included_files) == NULL)
240 throw(std::bad_alloc());
242 // return parsed block
246 // pass errors to generic error handler
247 catch (...) { handle_errors(c_ctx); }
257 using namespace Sass;
259 static void sass_clear_options (struct Sass_Options* options);
260 static void sass_reset_options (struct Sass_Options* options);
261 static void copy_options(struct Sass_Options* to, struct Sass_Options* from) {
262 // do not overwrite ourself
263 if (to == from) return;
264 // free assigned memory
265 sass_clear_options(to);
268 // Reset pointers on source
269 sass_reset_options(from);
272 #define IMPLEMENT_SASS_OPTION_ACCESSOR(type, option) \
273 type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return options->option; } \
274 void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) { options->option = option; }
275 #define IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \
276 type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return safe_str(options->option, def); }
277 #define IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def) \
278 void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) \
279 { free(options->option); options->option = option || def ? sass_copy_c_string(option ? option : def) : 0; }
280 #define IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(type, option, def) \
281 IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \
282 IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def)
284 #define IMPLEMENT_SASS_CONTEXT_GETTER(type, option) \
285 type ADDCALL sass_context_get_##option (struct Sass_Context* ctx) { return ctx->option; }
286 #define IMPLEMENT_SASS_CONTEXT_TAKER(type, option) \
287 type sass_context_take_##option (struct Sass_Context* ctx) \
288 { type foo = ctx->option; ctx->option = 0; return foo; }
291 // generic compilation function (not exported, use file/data compile instead)
292 static Sass_Compiler* sass_prepare_context (Sass_Context* c_ctx, Context* cpp_ctx) throw()
295 // register our custom functions
296 if (c_ctx->c_functions) {
297 auto this_func_data = c_ctx->c_functions;
298 while (this_func_data && *this_func_data) {
299 cpp_ctx->add_c_function(*this_func_data);
304 // register our custom headers
305 if (c_ctx->c_headers) {
306 auto this_head_data = c_ctx->c_headers;
307 while (this_head_data && *this_head_data) {
308 cpp_ctx->add_c_header(*this_head_data);
313 // register our custom importers
314 if (c_ctx->c_importers) {
315 auto this_imp_data = c_ctx->c_importers;
316 while (this_imp_data && *this_imp_data) {
317 cpp_ctx->add_c_importer(*this_imp_data);
322 // reset error status
323 c_ctx->error_json = 0;
324 c_ctx->error_text = 0;
325 c_ctx->error_message = 0;
326 c_ctx->error_status = 0;
327 // reset error position
328 c_ctx->error_src = 0;
329 c_ctx->error_file = 0;
330 c_ctx->error_line = std::string::npos;
331 c_ctx->error_column = std::string::npos;
333 // allocate a new compiler instance
334 Sass_Compiler* compiler = (struct Sass_Compiler*) calloc(1, sizeof(struct Sass_Compiler));
335 compiler->state = SASS_COMPILER_CREATED;
337 // store in sass compiler
338 compiler->c_ctx = c_ctx;
339 compiler->cpp_ctx = cpp_ctx;
340 cpp_ctx->c_compiler = compiler;
342 // use to parse block
346 // pass errors to generic error handler
347 catch (...) { handle_errors(c_ctx); }
354 // generic compilation function (not exported, use file/data compile instead)
355 static int sass_compile_context (Sass_Context* c_ctx, Context* cpp_ctx)
358 // prepare sass compiler with context and options
359 Sass_Compiler* compiler = sass_prepare_context(c_ctx, cpp_ctx);
362 // call each compiler step
363 sass_compiler_parse(compiler);
364 sass_compiler_execute(compiler);
366 // pass errors to generic error handler
367 catch (...) { handle_errors(c_ctx); }
369 sass_delete_compiler(compiler);
371 return c_ctx->error_status;
374 inline void init_options (struct Sass_Options* options)
376 options->precision = 5;
377 options->indent = " ";
378 options->linefeed = LFEED;
381 Sass_Options* ADDCALL sass_make_options (void)
383 struct Sass_Options* options = (struct Sass_Options*) calloc(1, sizeof(struct Sass_Options));
384 if (options == 0) { std::cerr << "Error allocating memory for options" << std::endl; return 0; }
385 init_options(options);
389 Sass_File_Context* ADDCALL sass_make_file_context(const char* input_path)
391 SharedObj::setTaint(true); // needed for static colors
392 struct Sass_File_Context* ctx = (struct Sass_File_Context*) calloc(1, sizeof(struct Sass_File_Context));
393 if (ctx == 0) { std::cerr << "Error allocating memory for file context" << std::endl; return 0; }
394 ctx->type = SASS_CONTEXT_FILE;
397 if (input_path == 0) { throw(std::runtime_error("File context created without an input path")); }
398 if (*input_path == 0) { throw(std::runtime_error("File context created with empty input path")); }
399 sass_option_set_input_path(ctx, input_path);
406 Sass_Data_Context* ADDCALL sass_make_data_context(char* source_string)
408 struct Sass_Data_Context* ctx = (struct Sass_Data_Context*) calloc(1, sizeof(struct Sass_Data_Context));
409 if (ctx == 0) { std::cerr << "Error allocating memory for data context" << std::endl; return 0; }
410 ctx->type = SASS_CONTEXT_DATA;
413 if (source_string == 0) { throw(std::runtime_error("Data context created without a source string")); }
414 if (*source_string == 0) { throw(std::runtime_error("Data context created with empty source string")); }
415 ctx->source_string = source_string;
422 struct Sass_Compiler* ADDCALL sass_make_data_compiler (struct Sass_Data_Context* data_ctx)
424 if (data_ctx == 0) return 0;
425 Context* cpp_ctx = new Data_Context(*data_ctx);
426 return sass_prepare_context(data_ctx, cpp_ctx);
429 struct Sass_Compiler* ADDCALL sass_make_file_compiler (struct Sass_File_Context* file_ctx)
431 if (file_ctx == 0) return 0;
432 Context* cpp_ctx = new File_Context(*file_ctx);
433 return sass_prepare_context(file_ctx, cpp_ctx);
436 int ADDCALL sass_compile_data_context(Sass_Data_Context* data_ctx)
438 if (data_ctx == 0) return 1;
439 if (data_ctx->error_status)
440 return data_ctx->error_status;
442 if (data_ctx->source_string == 0) { throw(std::runtime_error("Data context has no source string")); }
443 // empty source string is a valid case, even if not really usefull (different than with file context)
444 // if (*data_ctx->source_string == 0) { throw(std::runtime_error("Data context has empty source string")); }
446 catch (...) { return handle_errors(data_ctx) | 1; }
447 Context* cpp_ctx = new Data_Context(*data_ctx);
448 return sass_compile_context(data_ctx, cpp_ctx);
451 int ADDCALL sass_compile_file_context(Sass_File_Context* file_ctx)
453 if (file_ctx == 0) return 1;
454 if (file_ctx->error_status)
455 return file_ctx->error_status;
457 if (file_ctx->input_path == 0) { throw(std::runtime_error("File context has no input path")); }
458 if (*file_ctx->input_path == 0) { throw(std::runtime_error("File context has empty input path")); }
460 catch (...) { return handle_errors(file_ctx) | 1; }
461 Context* cpp_ctx = new File_Context(*file_ctx);
462 return sass_compile_context(file_ctx, cpp_ctx);
465 int ADDCALL sass_compiler_parse(struct Sass_Compiler* compiler)
467 if (compiler == 0) return 1;
468 if (compiler->state == SASS_COMPILER_PARSED) return 0;
469 if (compiler->state != SASS_COMPILER_CREATED) return -1;
470 if (compiler->c_ctx == NULL) return 1;
471 if (compiler->cpp_ctx == NULL) return 1;
472 if (compiler->c_ctx->error_status)
473 return compiler->c_ctx->error_status;
474 // parse the context we have set up (file or data)
475 compiler->root = sass_parse_block(compiler);
480 int ADDCALL sass_compiler_execute(struct Sass_Compiler* compiler)
482 if (compiler == 0) return 1;
483 if (compiler->state == SASS_COMPILER_EXECUTED) return 0;
484 if (compiler->state != SASS_COMPILER_PARSED) return -1;
485 if (compiler->c_ctx == NULL) return 1;
486 if (compiler->cpp_ctx == NULL) return 1;
487 if (compiler->root.isNull()) return 1;
488 if (compiler->c_ctx->error_status)
489 return compiler->c_ctx->error_status;
490 compiler->state = SASS_COMPILER_EXECUTED;
491 Context* cpp_ctx = compiler->cpp_ctx;
492 Block_Obj root = compiler->root;
493 // compile the parsed root block
494 try { compiler->c_ctx->output_string = cpp_ctx->render(root); }
495 // pass catched errors to generic error handler
496 catch (...) { return handle_errors(compiler->c_ctx) | 1; }
497 // generate source map json and store on context
498 compiler->c_ctx->source_map_string = cpp_ctx->render_srcmap();
503 // helper function, not exported, only accessible locally
504 static void sass_reset_options (struct Sass_Options* options)
506 // free pointer before
508 options->input_path = 0;
509 options->output_path = 0;
510 options->plugin_path = 0;
511 options->include_path = 0;
512 options->source_map_file = 0;
513 options->source_map_root = 0;
514 options->c_functions = 0;
515 options->c_importers = 0;
516 options->c_headers = 0;
517 options->plugin_paths = 0;
518 options->include_paths = 0;
521 // helper function, not exported, only accessible locally
522 static void sass_clear_options (struct Sass_Options* options)
524 if (options == 0) return;
525 // Deallocate custom functions
526 if (options->c_functions) {
527 Sass_Function_List this_func_data = options->c_functions;
528 while (this_func_data && *this_func_data) {
529 free(*this_func_data);
533 // Deallocate custom headers
534 if (options->c_headers) {
535 Sass_Importer_List this_head_data = options->c_headers;
536 while (this_head_data && *this_head_data) {
537 free(*this_head_data);
541 // Deallocate custom importers
542 if (options->c_importers) {
543 Sass_Importer_List this_imp_data = options->c_importers;
544 while (this_imp_data && *this_imp_data) {
545 free(*this_imp_data);
549 // Deallocate inc paths
550 if (options->plugin_paths) {
551 struct string_list* cur;
552 struct string_list* next;
553 cur = options->plugin_paths;
561 // Deallocate inc paths
562 if (options->include_paths) {
563 struct string_list* cur;
564 struct string_list* next;
565 cur = options->include_paths;
573 // Free options strings
574 free(options->input_path);
575 free(options->output_path);
576 free(options->plugin_path);
577 free(options->include_path);
578 free(options->source_map_file);
579 free(options->source_map_root);
580 // Free custom functions
581 free(options->c_functions);
582 // Free custom importers
583 free(options->c_importers);
584 free(options->c_headers);
585 // Reset our pointers
586 options->input_path = 0;
587 options->output_path = 0;
588 options->plugin_path = 0;
589 options->include_path = 0;
590 options->source_map_file = 0;
591 options->source_map_root = 0;
592 options->c_functions = 0;
593 options->c_importers = 0;
594 options->c_headers = 0;
595 options->plugin_paths = 0;
596 options->include_paths = 0;
599 // helper function, not exported, only accessible locally
600 // sass_free_context is also defined in old sass_interface
601 static void sass_clear_context (struct Sass_Context* ctx)
603 if (ctx == 0) return;
604 // release the allocated memory (mostly via sass_copy_c_string)
605 if (ctx->output_string) free(ctx->output_string);
606 if (ctx->source_map_string) free(ctx->source_map_string);
607 if (ctx->error_message) free(ctx->error_message);
608 if (ctx->error_text) free(ctx->error_text);
609 if (ctx->error_json) free(ctx->error_json);
610 if (ctx->error_file) free(ctx->error_file);
611 free_string_array(ctx->included_files);
612 // play safe and reset properties
613 ctx->output_string = 0;
614 ctx->source_map_string = 0;
615 ctx->error_message = 0;
619 ctx->included_files = 0;
620 // debug leaked memory
621 #ifdef DEBUG_SHARED_PTR
622 SharedObj::dumpMemLeaks();
624 // now clear the options
625 sass_clear_options(ctx);
628 void ADDCALL sass_delete_compiler (struct Sass_Compiler* compiler)
633 Context* cpp_ctx = compiler->cpp_ctx;
634 if (cpp_ctx) delete(cpp_ctx);
635 compiler->cpp_ctx = NULL;
636 compiler->c_ctx = NULL;
637 compiler->root = NULL;
641 void ADDCALL sass_delete_options (struct Sass_Options* options)
643 sass_clear_options(options); free(options);
646 // Deallocate all associated memory with file context
647 void ADDCALL sass_delete_file_context (struct Sass_File_Context* ctx)
649 // clear the context and free it
650 sass_clear_context(ctx); free(ctx);
652 // Deallocate all associated memory with data context
653 void ADDCALL sass_delete_data_context (struct Sass_Data_Context* ctx)
655 // clean the source string if it was not passed
656 // we reset this member once we start parsing
657 if (ctx->source_string) free(ctx->source_string);
658 // clear the context and free it
659 sass_clear_context(ctx); free(ctx);
662 // Getters for sass context from specific implementations
663 struct Sass_Context* ADDCALL sass_file_context_get_context(struct Sass_File_Context* ctx) { return ctx; }
664 struct Sass_Context* ADDCALL sass_data_context_get_context(struct Sass_Data_Context* ctx) { return ctx; }
666 // Getters for context options from Sass_Context
667 struct Sass_Options* ADDCALL sass_context_get_options(struct Sass_Context* ctx) { return ctx; }
668 struct Sass_Options* ADDCALL sass_file_context_get_options(struct Sass_File_Context* ctx) { return ctx; }
669 struct Sass_Options* ADDCALL sass_data_context_get_options(struct Sass_Data_Context* ctx) { return ctx; }
670 void ADDCALL sass_file_context_set_options (struct Sass_File_Context* ctx, struct Sass_Options* opt) { copy_options(ctx, opt); }
671 void ADDCALL sass_data_context_set_options (struct Sass_Data_Context* ctx, struct Sass_Options* opt) { copy_options(ctx, opt); }
673 // Getters for Sass_Compiler options (get conected sass context)
674 enum Sass_Compiler_State ADDCALL sass_compiler_get_state(struct Sass_Compiler* compiler) { return compiler->state; }
675 struct Sass_Context* ADDCALL sass_compiler_get_context(struct Sass_Compiler* compiler) { return compiler->c_ctx; }
676 struct Sass_Options* ADDCALL sass_compiler_get_options(struct Sass_Compiler* compiler) { return compiler->c_ctx; }
677 // Getters for Sass_Compiler options (query import stack)
678 size_t ADDCALL sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.size(); }
679 Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.back(); }
680 Sass_Import_Entry ADDCALL sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx) { return compiler->cpp_ctx->import_stack[idx]; }
681 // Getters for Sass_Compiler options (query function stack)
682 size_t ADDCALL sass_compiler_get_callee_stack_size(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->callee_stack.size(); }
683 Sass_Callee_Entry ADDCALL sass_compiler_get_last_callee(struct Sass_Compiler* compiler) { return &compiler->cpp_ctx->callee_stack.back(); }
684 Sass_Callee_Entry ADDCALL sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx) { return &compiler->cpp_ctx->callee_stack[idx]; }
686 // Calculate the size of the stored null terminated array
687 size_t ADDCALL sass_context_get_included_files_size (struct Sass_Context* ctx)
688 { size_t l = 0; auto i = ctx->included_files; while (i && *i) { ++i; ++l; } return l; }
690 // Create getter and setters for options
691 IMPLEMENT_SASS_OPTION_ACCESSOR(int, precision);
692 IMPLEMENT_SASS_OPTION_ACCESSOR(enum Sass_Output_Style, output_style);
693 IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_comments);
694 IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_embed);
695 IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_contents);
696 IMPLEMENT_SASS_OPTION_ACCESSOR(bool, source_map_file_urls);
697 IMPLEMENT_SASS_OPTION_ACCESSOR(bool, omit_source_map_url);
698 IMPLEMENT_SASS_OPTION_ACCESSOR(bool, is_indented_syntax_src);
699 IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Function_List, c_functions);
700 IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Importer_List, c_importers);
701 IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Importer_List, c_headers);
702 IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, indent);
703 IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, linefeed);
704 IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, plugin_path, 0);
705 IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, include_path, 0);
706 IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, input_path, 0);
707 IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, output_path, 0);
708 IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file, 0);
709 IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_root, 0);
711 // Create getter and setters for context
712 IMPLEMENT_SASS_CONTEXT_GETTER(int, error_status);
713 IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_json);
714 IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_message);
715 IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_text);
716 IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_file);
717 IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_line);
718 IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_column);
719 IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_src);
720 IMPLEMENT_SASS_CONTEXT_GETTER(const char*, output_string);
721 IMPLEMENT_SASS_CONTEXT_GETTER(const char*, source_map_string);
722 IMPLEMENT_SASS_CONTEXT_GETTER(char**, included_files);
724 // Take ownership of memory (value on context is set to 0)
725 IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_json);
726 IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_message);
727 IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_text);
728 IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_file);
729 IMPLEMENT_SASS_CONTEXT_TAKER(char*, output_string);
730 IMPLEMENT_SASS_CONTEXT_TAKER(char*, source_map_string);
731 IMPLEMENT_SASS_CONTEXT_TAKER(char**, included_files);
733 // Push function for include paths (no manipulation support for now)
734 void ADDCALL sass_option_push_include_path(struct Sass_Options* options, const char* path)
737 struct string_list* include_path = (struct string_list*) calloc(1, sizeof(struct string_list));
738 if (include_path == 0) return;
739 include_path->string = path ? sass_copy_c_string(path) : 0;
740 struct string_list* last = options->include_paths;
741 if (!options->include_paths) {
742 options->include_paths = include_path;
746 last->next = include_path;
751 // Push function for include paths (no manipulation support for now)
752 size_t ADDCALL sass_option_get_include_path_size(struct Sass_Options* options)
755 struct string_list* cur = options->include_paths;
756 while (cur) { len ++; cur = cur->next; }
760 // Push function for include paths (no manipulation support for now)
761 const char* ADDCALL sass_option_get_include_path(struct Sass_Options* options, size_t i)
763 struct string_list* cur = options->include_paths;
764 while (i) { i--; cur = cur->next; }
768 // Push function for plugin paths (no manipulation support for now)
769 void ADDCALL sass_option_push_plugin_path(struct Sass_Options* options, const char* path)
772 struct string_list* plugin_path = (struct string_list*) calloc(1, sizeof(struct string_list));
773 if (plugin_path == 0) return;
774 plugin_path->string = path ? sass_copy_c_string(path) : 0;
775 struct string_list* last = options->plugin_paths;
776 if (!options->plugin_paths) {
777 options->plugin_paths = plugin_path;
781 last->next = plugin_path;