diff --git a/context.cpp b/context.cpp index 44d23e346d..e2a8c335e7 100644 --- a/context.cpp +++ b/context.cpp @@ -44,12 +44,20 @@ namespace Sass { using std::cerr; using std::endl; + Sass_Queued::Sass_Queued(const string& load_path, const string& abs_path, const char* source) + { + this->load_path = load_path; + this->abs_path = abs_path; + this->source = source; + } + + Context::Context(Context::Data initializers) : mem(Memory_Manager()), source_c_str (initializers.source_c_str()), sources (vector()), include_paths (initializers.include_paths()), - queue (vector >()), + queue (vector()), style_sheets (map()), source_map (resolve_relative_path(initializers.output_path(), initializers.source_map_file(), get_cwd())), c_functions (vector()), @@ -96,6 +104,8 @@ namespace Sass { { // everything that gets put into sources will be freed by us for (size_t i = 0; i < sources.size(); ++i) delete[] sources[i]; + for (size_t n = 0; n < import_stack.size(); ++n) sass_delete_import(import_stack[n]); + sources.clear(); import_stack.clear(); } void Context::setup_color_map() @@ -155,7 +165,7 @@ namespace Sass { { sources.push_back(contents); included_files.push_back(abs_path); - queue.push_back(make_pair(load_path, contents)); + queue.push_back(Sass_Queued(load_path, abs_path, contents)); source_map.source_index.push_back(sources.size() - 1); include_links.push_back(resolve_relative_path(abs_path, source_map_file, cwd)); } @@ -246,10 +256,18 @@ namespace Sass { { Block* root = 0; for (size_t i = 0; i < queue.size(); ++i) { - Parser p(Parser::from_c_str(queue[i].second, *this, queue[i].first, Position(1 + i, 1, 1))); + struct Sass_Import* import = sass_make_import( + queue[i].load_path.c_str(), + queue[i].abs_path.c_str(), + 0, 0 + ); + import_stack.push_back(import); + Parser p(Parser::from_c_str(queue[i].source, *this, queue[i].load_path, Position(1 + i, 1, 1))); Block* ast = p.parse(); + sass_delete_import(import_stack.back()); + import_stack.pop_back(); if (i == 0) root = ast; - style_sheets[queue[i].first] = ast; + style_sheets[queue[i].load_path] = ast; } Env tge; Backtrace backtrace(0, "", Position(), ""); diff --git a/context.hpp b/context.hpp index 8bffb87cdb..04eb35b19c 100644 --- a/context.hpp +++ b/context.hpp @@ -42,6 +42,14 @@ namespace Sass { enum Output_Style { NESTED, EXPANDED, COMPACT, COMPRESSED, FORMATTED }; + struct Sass_Queued { + string abs_path; + string load_path; + const char* source; + public: + Sass_Queued(const string& load_path, const string& abs_path, const char* source); + }; + struct Context { Memory_Manager mem; @@ -57,7 +65,7 @@ namespace Sass { // vectors above have same size vector include_paths; // lookup paths for includes - vector > queue; // queue of files to be parsed + vector queue; // queue of files to be parsed map style_sheets; // map of paths to ASTs SourceMap source_map; vector c_functions; @@ -75,6 +83,7 @@ namespace Sass { // overload import calls Sass_C_Import_Callback importer; + vector import_stack; map names_to_colors; map colors_to_names; diff --git a/parser.cpp b/parser.cpp index 98c9d3191c..a6f6e958d4 100644 --- a/parser.cpp +++ b/parser.cpp @@ -12,6 +12,8 @@ #include "prelexer.hpp" #endif +#include "sass_functions.h" + #include namespace Sass { @@ -158,11 +160,15 @@ namespace Sass { Sass_C_Import_Callback importer = ctx.importer; // custom importer if (importer) { + Sass_Import* current = ctx.import_stack.back(); Sass_C_Import_Fn fn = sass_import_get_function(importer); void* cookie = sass_import_get_cookie(importer); - // get null delimited "array" of "external" imports - struct Sass_Import** imports = fn(import_path.c_str(), cookie); - struct Sass_Import** includes = imports; + // create a new import entry + string inc_path = unquote(import_path); + struct Sass_Import** includes = fn( + inc_path.c_str(), + sass_import_get_path(current), + cookie); if (includes) { while (*includes) { struct Sass_Import* include = *includes; @@ -170,24 +176,23 @@ namespace Sass { char *source = sass_import_take_source(include); // char *srcmap = sass_import_take_srcmap(include); if (source) { - string inc_path = unquote(import_path); if (file) { - ctx.add_source(file, import_path, source); + ctx.add_source(file, inc_path, source); imp->files().push_back(file); } else { - ctx.add_source(import_path, import_path, source); - imp->files().push_back(import_path); + ctx.add_source(inc_path, inc_path, source); + imp->files().push_back(inc_path); } } else if(file) { add_single_file(imp, file); } ++includes; } - // deallocate returned memory - sass_delete_import_list(imports); // go for next parse loop continue; } + // deallocate returned memory + sass_delete_import_list(includes); // custom importer returned nothing // means we should use default loader } diff --git a/sass_functions.cpp b/sass_functions.cpp index a9d37ca689..4e279c4bd9 100644 --- a/sass_functions.cpp +++ b/sass_functions.cpp @@ -43,6 +43,7 @@ extern "C" { // External import entry struct Sass_Import { char* path; + char* base; char* source; char* srcmap; }; @@ -73,16 +74,23 @@ extern "C" { // Creator for a single import entry returned by the custom importer inside the list // We take ownership of the memory for source and srcmap (freed when context is destroyd) - struct Sass_Import* sass_make_import_entry(const char* path, char* source, char* srcmap) + struct Sass_Import* sass_make_import(const char* path, const char* base, char* source, char* srcmap) { Sass_Import* v = (Sass_Import*) calloc(1, sizeof(Sass_Import)); if (v == 0) return 0; v->path = strdup(path); + v->base = strdup(base); v->source = source; v->srcmap = srcmap; return v; } + // Older style, but somehow still valid - keep around or deprecate? + struct Sass_Import* sass_make_import_entry(const char* path, char* source, char* srcmap) + { + return sass_make_import(path, path, source, srcmap); + } + // Setters and getters for entries on the import list void sass_import_set_list_entry(struct Sass_Import** list, size_t idx, struct Sass_Import* entry) { list[idx] = entry; } struct Sass_Import* sass_import_get_list_entry(struct Sass_Import** list, size_t idx) { return list[idx]; } @@ -93,17 +101,25 @@ extern "C" { struct Sass_Import** it = list; if (list == 0) return; while(*list) { - free((*list)->path); - free((*list)->source); - free((*list)->srcmap); - free(*list); + sass_delete_import(*list); ++list; } free(it); } + // Just in case we have some stray import structs + void sass_delete_import(struct Sass_Import* import) + { + free(import->path); + free(import->base); + free(import->source); + free(import->srcmap); + free(import); + } + // Getter for import entry const char* sass_import_get_path(struct Sass_Import* entry) { return entry->path; } + const char* sass_import_get_base(struct Sass_Import* entry) { return entry->base; } const char* sass_import_get_source(struct Sass_Import* entry) { return entry->source; } const char* sass_import_get_srcmap(struct Sass_Import* entry) { return entry->srcmap; } diff --git a/sass_functions.h b/sass_functions.h index acf0561942..6a1404a6b4 100644 --- a/sass_functions.h +++ b/sass_functions.h @@ -9,13 +9,16 @@ extern "C" { #endif +// Forward declaration +struct Sass_Import; + // Forward declaration struct Sass_C_Import_Descriptor; // Typedef defining the custom importer callback typedef struct Sass_C_Import_Descriptor (*Sass_C_Import_Callback); // Typedef defining the importer c function prototype -typedef struct Sass_Import** (*Sass_C_Import_Fn) (const char* url, void* cookie); +typedef struct Sass_Import** (*Sass_C_Import_Fn) (const char* url, const char* prev, void* cookie); // Creators for custom importer callback (with some additional pointer) // The pointer is mostly used to store the callback into the actual binding @@ -30,6 +33,7 @@ void* sass_import_get_cookie (Sass_C_Import_Callback fn); struct Sass_Import** sass_make_import_list (size_t length); // Creator for a single import entry returned by the custom importer inside the list struct Sass_Import* sass_make_import_entry (const char* path, char* source, char* srcmap); +struct Sass_Import* sass_make_import (const char* path, const char* base, char* source, char* srcmap); // Setters to insert an entry into the import list (you may also use [] access directly) // Since we are dealing with pointers they should have a guaranteed and fixed size @@ -38,6 +42,7 @@ struct Sass_Import* sass_import_get_list_entry (struct Sass_Import** list, size_ // Getters for import entry const char* sass_import_get_path (struct Sass_Import*); +const char* sass_import_get_base (struct Sass_Import*); const char* sass_import_get_source (struct Sass_Import*); const char* sass_import_get_srcmap (struct Sass_Import*); // Explicit functions to take ownership of these items @@ -47,6 +52,8 @@ char* sass_import_take_srcmap (struct Sass_Import*); // Deallocator for associated memory (incl. entries) void sass_delete_import_list (struct Sass_Import**); +// Just in case we have some stray import structs +void sass_delete_import (struct Sass_Import*); // Forward declaration @@ -56,7 +63,7 @@ struct Sass_C_Function_Descriptor; typedef struct Sass_C_Function_Descriptor* (*Sass_C_Function_List); typedef struct Sass_C_Function_Descriptor (*Sass_C_Function_Callback); // Typedef defining custom function prototype and its return value type -typedef union Sass_Value*(*Sass_C_Function) (union Sass_Value*, void *cookie); +typedef union Sass_Value*(*Sass_C_Function) (union Sass_Value*, void* cookie); // Creators for sass function list and function descriptors