Commit 1f5eaff3 by Michael Mifsud Committed by GitHub

Merge pull request #1866 from xzyfer/bump-libsass

Bump LibSass to 3.5.0.beta.2
parents 71a7a84c 1b9970a4
{
"name": "node-sass",
"version": "4.3.0",
"libsass": "3.4.3",
"libsass": "3.5.0.beta.2",
"description": "Wrapper around libsass",
"license": "MIT",
"bugs": "https://github.com/sass/node-sass/issues",
......
......@@ -12,6 +12,7 @@
],
'sources': [
'libsass/src/ast.cpp',
'libsass/src/ast_fwd_decl.cpp',
'libsass/src/base64vlq.cpp',
'libsass/src/bind.cpp',
'libsass/src/cencode.c',
......
language: cpp
sudo: false
os:
- linux
- osx
compiler:
- gcc
- clang
# don't create redundant code coverage reports
# - AUTOTOOLS=yes COVERAGE=yes BUILD=static
......@@ -19,27 +12,53 @@ compiler:
# this will still catch all coding errors!
# - AUTOTOOLS=yes COVERAGE=no BUILD=static
env:
- AUTOTOOLS=no COVERAGE=no BUILD=shared
- AUTOTOOLS=no COVERAGE=yes BUILD=static
- AUTOTOOLS=yes COVERAGE=no BUILD=shared
# currenty there are various issues when
# built with coverage, clang and autotools
# - AUTOTOOLS=yes COVERAGE=yes BUILD=shared
matrix:
exclude:
- compiler: clang
env: AUTOTOOLS=yes COVERAGE=yes BUILD=static
include :
- os: linux
compiler: gcc
env: AUTOTOOLS=no COVERAGE=yes BUILD=static
- os: linux
compiler: g++-5
env: AUTOTOOLS=yes COVERAGE=no BUILD=shared
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- g++-5
- os: linux
compiler: clang++-3.7
env: AUTOTOOLS=no COVERAGE=yes BUILD=static
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.7
packages:
- clang-3.7
- os: linux
compiler: clang
env: AUTOTOOLS=yes COVERAGE=no BUILD=shared
- os: osx
compiler: clang
env: AUTOTOOLS=no COVERAGE=no BUILD=shared
- os: osx
compiler: gcc
compiler: clang
env: AUTOTOOLS=no COVERAGE=yes BUILD=static
- os: osx
env: AUTOTOOLS=no BUILD=static
compiler: clang
env: AUTOTOOLS=yes COVERAGE=no BUILD=shared
script: ./script/ci-build-libsass
script:
- ./script/ci-build-libsass
- ./script/ci-build-plugin math
- ./script/ci-build-plugin glob
- ./script/ci-build-plugin digest
- ./script/ci-build-plugin tests
before_install: ./script/ci-install-deps
install: ./script/ci-install-compiler
after_success: ./script/ci-report-coverage
......@@ -4,7 +4,7 @@ AM_COPT = -Wall -O2
AM_COVLDFLAGS =
if ENABLE_COVERAGE
AM_COPT = -O0 --coverage
AM_COPT = -Wall -O1 -fno-omit-frame-pointer --coverage
AM_COVLDFLAGS += -lgcov
endif
......@@ -57,7 +57,7 @@ TESTS = \
$(SASS_SPEC_PATH)/spec/scss-tests \
$(SASS_SPEC_PATH)/spec/types
SASS_TEST_FLAGS = -V 3.4 --impl libsass
SASS_TEST_FLAGS = -V 3.5 --impl libsass
LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) ./script/tap-driver
AM_LOG_FLAGS = -c ./tester $(LOG_FLAGS)
if USE_TAP
......
......@@ -15,10 +15,14 @@ INSTALL ?= install
CFLAGS ?= -Wall
CXXFLAGS ?= -Wall
LDFLAGS ?= -Wall
ifneq "$(COVERAGE)" "yes"
ifeq "x$(COVERAGE)" "x"
CFLAGS += -O2
CXXFLAGS += -O2
LDFLAGS += -O2
else
CFLAGS += -O1 -fno-omit-frame-pointer
CXXFLAGS += -O1 -fno-omit-frame-pointer
LDFLAGS += -O1 -fno-omit-frame-pointer
endif
LDFLAGS += -Wl,-undefined,error
CAT ?= $(if $(filter $(OS),Windows_NT),type,cat)
......@@ -305,16 +309,16 @@ version: $(SASSC_BIN)
$(SASSC_BIN) -v
test: $(SASSC_BIN)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.5 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
test_build: $(SASSC_BIN)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.5 -c $(SASSC_BIN) --impl libsass $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
test_full: $(SASSC_BIN)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass --run-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.5 -c $(SASSC_BIN) --impl libsass --run-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
test_probe: $(SASSC_BIN)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.4 -c $(SASSC_BIN) --impl libsass --probe-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
$(RUBY_BIN) $(SASS_SPEC_PATH)/sass-spec.rb -V 3.5 -c $(SASSC_BIN) --impl libsass --probe-todo $(LOG_FLAGS) $(SASS_SPEC_PATH)/$(SASS_SPEC_SPEC_DIR)
clean-objects: lib
-$(RM) lib/*.a lib/*.so lib/*.dll lib/*.la
......
......@@ -13,6 +13,7 @@ SOURCES = \
functions.cpp \
color_maps.cpp \
environment.cpp \
ast_fwd_decl.cpp \
bind.cpp \
file.cpp \
util.cpp \
......
......@@ -65,7 +65,7 @@ test_script:
}
$env:TargetPath = Join-Path $pwd.Path $env:TargetPath
If (Test-Path "$env:TargetPath") {
ruby sass-spec/sass-spec.rb -V 3.4 --probe-todo --impl libsass -c $env:TargetPath -s sass-spec/spec
ruby sass-spec/sass-spec.rb -V 3.5 --probe-todo --impl libsass -c $env:TargetPath -s sass-spec/spec
if(-not($?)) {
echo "sass-spec tests failed"
exit 1
......
......@@ -121,8 +121,8 @@ if test "x$enable_cov" = "xyes"; then
# Remove all optimization flags from C[XX]FLAGS
changequote({,})
CFLAGS=`echo "$CFLAGS" | $SED -e 's/-O[0-9]*//g'`
CXXFLAGS=`echo "$CXXFLAGS" | $SED -e 's/-O[0-9]*//g'`
CFLAGS=`echo "$CFLAGS -O1 -fno-omit-frame-pointer" | $SED -e 's/-O[0-9]*//g'`
CXXFLAGS=`echo "$CXXFLAGS -O1 -fno-omit-frame-pointer" | $SED -e 's/-O[0-9]*//g'`
changequote([,])
AC_SUBST(GCOV)
......
......@@ -7,26 +7,35 @@ enum Sass_Input_Style {
SASS_CONTEXT_FOLDER
};
// simple linked list
struct string_list {
string_list* next;
char* string;
};
// sass config options structure
struct Sass_Options {
// Precision for fractional numbers
int precision;
struct Sass_Inspect_Options {
// Output style for the generated css code
// A value from above SASS_STYLE_* constants
enum Sass_Output_Style output_style;
// Precision for fractional numbers
int precision;
};
// sass config options structure
struct Sass_Output_Options : Sass_Inspect_Options {
// String to be used for indentation
const char* indent;
// String to be used to for line feeds
const char* linefeed;
// Emit comments in the generated CSS indicating
// the corresponding source line.
bool source_comments;
};
// sass config options structure
struct Sass_Options : Sass_Output_Options {
// embed sourceMappingUrl as data uri
bool source_map_embed;
......@@ -56,15 +65,9 @@ struct Sass_Options {
// information in source-maps etc.
char* output_path;
// String to be used for indentation
const char* indent;
// String to be used to for line feeds
const char* linefeed;
// Colon-separated list of paths
// Semicolon-separated on Windows
// Note: It may be better to use
// array interface instead
// Maybe use array interface instead?
char* include_path;
char* plugin_path;
......@@ -82,10 +85,13 @@ struct Sass_Options {
char* source_map_root;
// Custom functions that can be called from sccs code
Sass_C_Function_List c_functions;
Sass_Function_List c_functions;
// Callback to overload imports
Sass_C_Import_Callback importer;
Sass_Importer_List c_importers;
// List of custom headers
Sass_Importer_List c_headers;
};
......@@ -111,6 +117,7 @@ struct Sass_Context : Sass_Options
char* error_file;
size_t error_line;
size_t error_column;
const char* error_src;
// report imported files
char** included_files;
......@@ -130,6 +137,7 @@ struct Sass_Data_Context : Sass_Context {
// provided source string
char* source_string;
char* srcmap_string;
};
......@@ -147,9 +155,9 @@ struct Sass_Compiler {
// original c context
Sass_Context* c_ctx;
// Sass::Context
void* cpp_ctx;
Sass::Context* cpp_ctx;
// Sass::Block
void* root;
Sass::Block_Obj root;
};
```
......@@ -207,6 +207,15 @@ size_t sass_context_get_error_column (struct Sass_Context* ctx);
const char* sass_context_get_source_map_string (struct Sass_Context* ctx);
char** sass_context_get_included_files (struct Sass_Context* ctx);
// Getters for Sass_Compiler options (query import stack)
size_t sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler);
Sass_Import_Entry sass_compiler_get_last_import(struct Sass_Compiler* compiler);
Sass_Import_Entry sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx);
// Getters for Sass_Compiler options (query function stack)
size_t sass_compiler_get_callee_stack_size(struct Sass_Compiler* compiler);
Sass_Callee_Entry sass_compiler_get_last_callee(struct Sass_Compiler* compiler);
Sass_Callee_Entry sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx);
// Take ownership of memory (value on context is set to 0)
char* sass_context_take_error_json (struct Sass_Context* ctx);
char* sass_context_take_error_text (struct Sass_Context* ctx);
......@@ -214,10 +223,6 @@ char* sass_context_take_error_message (struct Sass_Context* ctx);
char* sass_context_take_error_file (struct Sass_Context* ctx);
char* sass_context_take_output_string (struct Sass_Context* ctx);
char* sass_context_take_source_map_string (struct Sass_Context* ctx);
// Push function for plugin/include paths (no manipulation support for now)
void sass_option_push_plugin_path (struct Sass_Options* options, const char* path);
void sass_option_push_include_path (struct Sass_Options* options, const char* path);
```
### Sass Options API
......@@ -236,13 +241,18 @@ const char* sass_option_get_indent (struct Sass_Options* options);
const char* sass_option_get_linefeed (struct Sass_Options* options);
const char* sass_option_get_input_path (struct Sass_Options* options);
const char* sass_option_get_output_path (struct Sass_Options* options);
const char* sass_option_get_plugin_path (struct Sass_Options* options);
const char* sass_option_get_include_path (struct Sass_Options* options);
const char* sass_option_get_source_map_file (struct Sass_Options* options);
const char* sass_option_get_source_map_root (struct Sass_Options* options);
Sass_C_Function_List sass_option_get_c_functions (struct Sass_Options* options);
Sass_C_Import_Callback sass_option_get_importer (struct Sass_Options* options);
// Getters for Context_Option include path array
size_t sass_option_get_include_path_size(struct Sass_Options* options);
const char* sass_option_get_include_path(struct Sass_Options* options, size_t i);
// Plugin paths to load dynamic libraries work the same
size_t sass_option_get_plugin_path_size(struct Sass_Options* options);
const char* sass_option_get_plugin_path(struct Sass_Options* options, size_t i);
// Setters for Context_Option values
void sass_option_set_precision (struct Sass_Options* options, int precision);
void sass_option_set_output_style (struct Sass_Options* options, enum Sass_Output_Style output_style);
......@@ -266,6 +276,16 @@ void sass_option_set_importer (struct Sass_Options* options, Sass_C_Import_Callb
// Push function for paths (no manipulation support for now)
void sass_option_push_plugin_path (struct Sass_Options* options, const char* path);
void sass_option_push_include_path (struct Sass_Options* options, const char* path);
// Resolve a file via the given include paths in the sass option struct
// find_file looks for the exact file name while find_include does a regular sass include
char* sass_find_file (const char* path, struct Sass_Options* opt);
char* sass_find_include (const char* path, struct Sass_Options* opt);
// Resolve a file relative to last import or include paths in the sass option struct
// find_file looks for the exact file name while find_include does a regular sass include
char* sass_compiler_find_file (const char* path, struct Sass_Compiler* compiler);
char* sass_compiler_find_include (const char* path, struct Sass_Compiler* compiler);
```
### More links
......
## Introduction
LibSass wouldn't be much good without a way to interface with it. These interface documentations describe the various functions and data structures available to implementers. They are split up over three major components, which have all their own source files (plus some common functionality).
LibSass wouldn't be much good without a way to interface with it. These
interface documentations describe the various functions and data structures
available to implementers. They are split up over three major components, which
have all their own source files (plus some common functionality).
- [Sass Context](api-context.md) - Trigger and handle the main Sass compilation
- [Sass Value](api-value.md) - Exchange values and its format with LibSass
......@@ -41,7 +44,12 @@ gcc -Wall version.c -lsass -o version && ./version
## Compiling your code
The most important is your sass file (or string of sass code). With this, you will want to start a LibSass compiler. Here is some pseudocode describing the process. The compiler has two different modes: direct input as a string with `Sass_Data_Context` or LibSass will do file reading for you by using `Sass_File_Context`. See the code for a list of options available [Sass_Options](https://github.com/sass/libsass/blob/36feef0/include/sass/interface.h#L18)
The most important is your sass file (or string of sass code). With this, you
will want to start a LibSass compiler. Here is some pseudocode describing the
process. The compiler has two different modes: direct input as a string with
`Sass_Data_Context` or LibSass will do file reading for you by using
`Sass_File_Context`. See the code for a list of options available
[Sass_Options](https://github.com/sass/libsass/blob/36feef0/include/sass/interface.h#L18)
**Building a file compiler**
......@@ -97,7 +105,9 @@ struct Sass_Data_context : Sass_Context;
This mirrors very well how `libsass` uses these structures.
- `Sass_Options` holds everything you feed in before the compilation. It also hosts `input_path` and `output_path` options, because they are used to generate/calculate relative links in source-maps. The `input_path` is shared with `Sass_File_Context`.
- `Sass_Options` holds everything you feed in before the compilation. It also hosts
`input_path` and `output_path` options, because they are used to generate/calculate
relative links in source-maps. The `input_path` is shared with `Sass_File_Context`.
- `Sass_Context` holds all the data returned by the compilation step.
- `Sass_File_Context` is a specific implementation that requires no additional fields
- `Sass_Data_Context` is a specific implementation that adds the `input_source` field
......@@ -106,8 +116,11 @@ Structs can be down-casted to access `context` or `options`!
## Memory handling and life-cycles
We keep memory around for as long as the main [context](api-context.md) object is not destroyed (`sass_delete_context`). LibSass will create copies of most inputs/options beside the main sass code.
You need to allocate and fill that buffer before passing it to LibSass. You may also overtake memory management from libsass for certain return values (i.e. `sass_context_take_output_string`).
We keep memory around for as long as the main [context](api-context.md) object
is not destroyed (`sass_delete_context`). LibSass will create copies of most
inputs/options beside the main sass code. You need to allocate and fill that
buffer before passing it to LibSass. You may also overtake memory management
from libsass for certain return values (i.e. `sass_context_take_output_string`).
```C
// to allocate buffer to be filled
......@@ -125,9 +138,6 @@ void sass_free_memory(void* ptr);
char* sass_string_unquote (const char* str);
char* sass_string_quote (const char* str, const char quote_mark);
// Resolve a file via the given include paths in the include char* array
char* sass_resolve_file (const char* path, const char* incs[]);
// Get compiled libsass version
const char* libsass_version(void);
......@@ -140,15 +150,25 @@ const char* libsass_language_version(void);
**input_path**
The `input_path` is part of `Sass_Options`, but it also is the main option for `Sass_File_Context`. It is also used to generate relative file links in source-maps. Therefore it is pretty usefull to pass this information if you have a `Sass_Data_Context` and know the original path.
The `input_path` is part of `Sass_Options`, but it also is the main option for
`Sass_File_Context`. It is also used to generate relative file links in source-
maps. Therefore it is pretty usefull to pass this information if you have a
`Sass_Data_Context` and know the original path.
**output_path**
Be aware that `libsass` does not write the output file itself. This option merely exists to give `libsass` the proper information to generate links in source-maps. The file has to be written to the disk by the binding/implementation. If the `output_path` is omitted, `libsass` tries to extrapolate one from the `input_path` by replacing (or adding) the file ending with `.css`.
Be aware that `libsass` does not write the output file itself. This option
merely exists to give `libsass` the proper information to generate links in
source-maps. The file has to be written to the disk by the
binding/implementation. If the `output_path` is omitted, `libsass` tries to
extrapolate one from the `input_path` by replacing (or adding) the file ending
with `.css`.
## Error Codes
The `error_code` is integer value which indicates the type of error that occurred inside the LibSass process. Following is the list of error codes along with the short description:
The `error_code` is integer value which indicates the type of error that
occurred inside the LibSass process. Following is the list of error codes along
with the short description:
* 1: normal errors like parsing or `eval` errors
* 2: bad allocation error (memory error)
......@@ -156,11 +176,15 @@ The `error_code` is integer value which indicates the type of error that occurre
* 4: legacy string exceptions ( `throw const char*` or `std::string` )
* 5: Some other unknown exception
Although for the API consumer, error codes do not offer much value except indicating whether *any* error occurred during the compilation, it helps debugging the LibSass internal code paths.
Although for the API consumer, error codes do not offer much value except
indicating whether *any* error occurred during the compilation, it helps
debugging the LibSass internal code paths.
## Real-World Implementations
The proof is in the pudding, so we have highlighted a few implementations that should be on par with the latest LibSass interface version. Some of them may not have all features implemented!
The proof is in the pudding, so we have highlighted a few implementations that
should be on par with the latest LibSass interface version. Some of them may not
have all features implemented!
1. [Perl Example](https://github.com/sass/perl-libsass/blob/master/lib/CSS/Sass.xs)
2. [Go Example](http://godoc.org/github.com/wellington/go-libsass#example-Context-Compile)
......@@ -168,11 +192,20 @@ The proof is in the pudding, so we have highlighted a few implementations that s
## ABI forward compatibility
We use a functional API to make dynamic linking more robust and future compatible. The API is not yet 100% stable, so we do not yet guarantee [ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) forward compatibility. We will do so, once we increase the shared library version above 1.0.
We use a functional API to make dynamic linking more robust and future
compatible. The API is not yet 100% stable, so we do not yet guarantee
[ABI](https://gcc.gnu.org/onlinedocs/libstdc++/manual/abi.html) forward
compatibility.
## Plugins (experimental)
LibSass can load plugins from directories. Just define `plugin_path` on context options to load all plugins from the given directories. To implement plugins, please consult the [[Wiki-Page for plugins|API-Plugins]].
LibSass can load plugins from directories. Just define `plugin_path` on context
options to load all plugins from the directories. To implement plugins, please
consult the following example implementations.
- https://github.com/mgreter/libsass-glob
- https://github.com/mgreter/libsass-math
- https://github.com/mgreter/libsass-digest
## Internal Structs
......
......@@ -11,7 +11,7 @@ union Sass_Value* call_fn_foo(const union Sass_Value* s_args, Sass_Function_Entr
struct Sass_Context* ctx = sass_compiler_get_context(comp);
struct Sass_Options* opts = sass_compiler_get_options(comp);
// get information about previous importer entry from the stack
struct Sass_Import* import = sass_compiler_get_last_import(comp);
Sass_Import_Entry import = sass_compiler_get_last_import(comp);
const char* prev_abs_path = sass_import_get_abs_path(import);
const char* prev_imp_path = sass_import_get_imp_path(import);
// get the cookie from function descriptor
......
......@@ -30,17 +30,41 @@ typedef union Sass_Value* (*Sass_Function_Fn)
(const union Sass_Value*, Sass_Function_Entry cb, struct Sass_Compiler* compiler);
// Creators for sass function list and function descriptors
ADDAPI Sass_Function_List ADDCALL sass_make_function_list (size_t length);
ADDAPI Sass_Function_Entry ADDCALL sass_make_function (const char* signature, Sass_Function_Fn cb, void* cookie);
Sass_Function_List sass_make_function_list (size_t length);
Sass_Function_Entry sass_make_function (const char* signature, Sass_Function_Fn cb, void* cookie);
// In case you need to free them yourself
void sass_delete_function (Sass_Function_Entry entry);
void sass_delete_function_list (Sass_Function_List list);
// Setters and getters for callbacks on function lists
ADDAPI Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos);
ADDAPI void ADDCALL sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb);
Sass_Function_Entry sass_function_get_list_entry(Sass_Function_List list, size_t pos);
void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb);
// 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
void sass_import_set_list_entry (Sass_Import_List list, size_t idx, Sass_Import_Entry entry);
Sass_Import_Entry sass_import_get_list_entry (Sass_Import_List list, size_t idx);
// Getters for custom function descriptors
ADDAPI const char* ADDCALL sass_function_get_signature (Sass_Function_Entry cb);
ADDAPI Sass_Function_Fn ADDCALL sass_function_get_function (Sass_Function_Entry cb);
ADDAPI void* ADDCALL sass_function_get_cookie (Sass_Function_Entry cb);
const char* sass_function_get_signature (Sass_Function_Entry cb);
Sass_Function_Fn sass_function_get_function (Sass_Function_Entry cb);
void* sass_function_get_cookie (Sass_Function_Entry cb);
// Getters for callee entry
const char* sass_callee_get_name (Sass_Callee_Entry);
const char* sass_callee_get_path (Sass_Callee_Entry);
size_t sass_callee_get_line (Sass_Callee_Entry);
size_t sass_callee_get_column (Sass_Callee_Entry);
enum Sass_Callee_Type sass_callee_get_type (Sass_Callee_Entry);
Sass_Env_Frame sass_callee_get_env (Sass_Callee_Entry);
// Getters and Setters for environments (lexical, local and global)
union Sass_Value* sass_env_get_lexical (Sass_Env_Frame, const char*);
void sass_env_set_lexical (Sass_Env_Frame, const char*, union Sass_Value*);
union Sass_Value* sass_env_get_local (Sass_Env_Frame, const char*);
void sass_env_set_local (Sass_Env_Frame, const char*, union Sass_Value*);
union Sass_Value* sass_env_get_global (Sass_Env_Frame, const char*);
void sass_env_set_global (Sass_Env_Frame, const char*, union Sass_Value*);
```
### More links
......
......@@ -5,7 +5,7 @@ By using custom importers, Sass stylesheets can be implemented in any possible w
You actually have to return a list of imports, since some importers may want to import multiple files from one import statement (ie. a glob/star importer). The memory you pass with source and srcmap is taken over by LibSass and freed automatically when the import is done. You are also allowed to return `0` instead of a list, which will tell LibSass to handle the import by itself (as if no custom importer was in use).
```C
struct Sass_Import** rv = sass_make_import_list(1);
Sass_Import_Entry* rv = sass_make_import_list(1);
rv[0] = sass_make_import(rel, abs, source, srcmap);
```
......@@ -31,7 +31,7 @@ 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, const char* prev, void* cookie);
typedef Sass_Import_Entry* (*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 function
......@@ -45,38 +45,38 @@ void* sass_import_get_cookie (Sass_C_Import_Callback fn);
void sass_delete_importer (Sass_C_Import_Callback fn);
// Creator for sass custom importer return argument list
struct Sass_Import** sass_make_import_list (size_t length);
Sass_Import_Entry* 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* rel, const char* abs, char* source, char* srcmap);
Sass_Import_Entry sass_make_import_entry (const char* path, char* source, char* srcmap);
Sass_Import_Entry sass_make_import (const char* rel, const char* abs, char* source, char* srcmap);
// set error message to abort import and to print out a message (path from existing object is used in output)
struct Sass_Import* sass_import_set_error(struct Sass_Import* import, const char* message, size_t line, size_t col);
Sass_Import_Entry sass_import_set_error(Sass_Import_Entry import, const char* message, size_t line, size_t col);
// 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
void sass_import_set_list_entry (struct Sass_Import** list, size_t idx, struct Sass_Import* entry);
struct Sass_Import* sass_import_get_list_entry (struct Sass_Import** list, size_t idx);
void sass_import_set_list_entry (Sass_Import_Entry* list, size_t idx, Sass_Import_Entry entry);
Sass_Import_Entry sass_import_get_list_entry (Sass_Import_Entry* list, size_t idx);
// Getters for import entry
const char* sass_import_get_rel_path (struct Sass_Import*);
const char* sass_import_get_abs_path (struct Sass_Import*);
const char* sass_import_get_source (struct Sass_Import*);
const char* sass_import_get_srcmap (struct Sass_Import*);
const char* sass_import_get_imp_path (Sass_Import_Entry);
const char* sass_import_get_abs_path (Sass_Import_Entry);
const char* sass_import_get_source (Sass_Import_Entry);
const char* sass_import_get_srcmap (Sass_Import_Entry);
// Explicit functions to take ownership of these items
// The property on our struct will be reset to NULL
char* sass_import_take_source (struct Sass_Import*);
char* sass_import_take_srcmap (struct Sass_Import*);
char* sass_import_take_source (Sass_Import_Entry);
char* sass_import_take_srcmap (Sass_Import_Entry);
// Getters for import error entries
size_t sass_import_get_error_line (struct Sass_Import*);
size_t sass_import_get_error_column (struct Sass_Import*);
const char* sass_import_get_error_message (struct Sass_Import*);
size_t sass_import_get_error_line (Sass_Import_Entry);
size_t sass_import_get_error_column (Sass_Import_Entry);
const char* sass_import_get_error_message (Sass_Import_Entry);
// Deallocator for associated memory (incl. entries)
void sass_delete_import_list (struct Sass_Import**);
void sass_delete_import_list (Sass_Import_Entry*);
// Just in case we have some stray import structs
void sass_delete_import (struct Sass_Import*);
void sass_delete_import (Sass_Import_Entry);
```
### More links
......
......@@ -58,7 +58,7 @@ union Sass_Value* sass_make_string (const char* val);
union Sass_Value* sass_make_qstring (const char* val);
union Sass_Value* sass_make_number (double val, const char* unit);
union Sass_Value* sass_make_color (double r, double g, double b, double a);
union Sass_Value* sass_make_list (size_t len, enum Sass_Separator sep);
union Sass_Value* sass_make_list (size_t len, enum Sass_Separator sep, bool is_bracketed);
union Sass_Value* sass_make_map (size_t len);
union Sass_Value* sass_make_error (const char* msg);
union Sass_Value* sass_make_warning (const char* msg);
......@@ -124,6 +124,8 @@ size_t sass_list_get_length (const union Sass_Value* v);
// Getters and setters for Sass_List
enum Sass_Separator sass_list_get_separator (const union Sass_Value* v);
void sass_list_set_separator (union Sass_Value* v, enum Sass_Separator value);
bool sass_list_get_is_bracketed (const union Sass_Value* v);
void sass_list_set_is_bracketed (union Sass_Value* v, bool value);
// Getters and setters for Sass_List values
union Sass_Value* sass_list_get_value (const union Sass_Value* v, size_t i);
void sass_list_set_value (union Sass_Value* v, size_t i, union Sass_Value* value);
......
......@@ -130,7 +130,7 @@ cd libsass
REM set PATH=%PATH%;%PROGRAMFILES%\MSBuild\12.0\Bin
msbuild /m:4 /p:Configuration=Release win\libsass.sln
REM running the spec test-suite manually (needs ruby and minitest gem)
ruby sass-spec\sass-spec.rb -V 3.4 -c win\bin\sassc.exe -s --impl libsass sass-spec/spec
ruby sass-spec\sass-spec.rb -V 3.5 -c win\bin\sassc.exe -s --impl libsass sass-spec/spec
cd ..
```
......
......@@ -45,14 +45,16 @@ The cookie can hold any pointer you want. In the `perl-libsass` implementation i
```C
// allocate memory (copies passed strings)
union Sass_Value* make_sass_boolean (int val);
union Sass_Value* make_sass_number (double val, const char* unit);
union Sass_Value* make_sass_color (double r, double g, double b, double a);
union Sass_Value* make_sass_string (const char* val);
union Sass_Value* make_sass_list (size_t len, enum Sass_Separator sep);
union Sass_Value* make_sass_map (size_t len);
union Sass_Value* make_sass_null ();
union Sass_Value* make_sass_error (const char* msg);
union Sass_Value* sass_make_null (void);
union Sass_Value* sass_make_boolean (bool val);
union Sass_Value* sass_make_string (const char* val);
union Sass_Value* sass_make_qstring (const char* val);
union Sass_Value* sass_make_number (double val, const char* unit);
union Sass_Value* sass_make_color (double r, double g, double b, double a);
union Sass_Value* sass_make_list (size_t len, enum Sass_Separator sep, bool is_bracketed);
union Sass_Value* sass_make_map (size_t len);
union Sass_Value* sass_make_error (const char* msg);
union Sass_Value* sass_make_warning (const char* msg);
// Make a deep cloned copy of the given sass value
union Sass_Value* sass_clone_value (const union Sass_Value* val);
......
......@@ -75,9 +75,6 @@ ADDAPI void ADDCALL sass_free_memory(void* ptr);
ADDAPI char* ADDCALL sass_string_quote (const char* str, const char quote_mark);
ADDAPI char* ADDCALL sass_string_unquote (const char* str);
// Resolve a file via the given include paths in the include char* array
ADDAPI char* ADDCALL sass_resolve_file (const char* path, const char* incs[]);
// Implemented sass language version
// Hardcoded version 3.4 for time being
ADDAPI const char* ADDCALL libsass_version(void);
......
......@@ -81,8 +81,6 @@ ADDAPI const char* ADDCALL sass_option_get_indent (struct Sass_Options* options)
ADDAPI const char* ADDCALL sass_option_get_linefeed (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_input_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_output_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_plugin_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_include_path (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_source_map_file (struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_source_map_root (struct Sass_Options* options);
ADDAPI Sass_Importer_List ADDCALL sass_option_get_c_headers (struct Sass_Options* options);
......@@ -124,6 +122,10 @@ ADDAPI size_t ADDCALL sass_context_get_error_column (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_source_map_string (struct Sass_Context* ctx);
ADDAPI char** ADDCALL sass_context_get_included_files (struct Sass_Context* ctx);
// Getters for options include path array
ADDAPI size_t ADDCALL sass_option_get_include_path_size(struct Sass_Options* options);
ADDAPI const char* ADDCALL sass_option_get_include_path(struct Sass_Options* options, size_t i);
// Calculate the size of the stored null terminated array
ADDAPI size_t ADDCALL sass_context_get_included_files_size (struct Sass_Context* ctx);
......@@ -143,11 +145,24 @@ ADDAPI struct Sass_Options* ADDCALL sass_compiler_get_options(struct Sass_Compil
ADDAPI size_t ADDCALL sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler);
ADDAPI Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler);
ADDAPI Sass_Import_Entry ADDCALL sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx);
ADDAPI size_t ADDCALL sass_compiler_get_callee_stack_size(struct Sass_Compiler* compiler);
ADDAPI Sass_Callee_Entry ADDCALL sass_compiler_get_last_callee(struct Sass_Compiler* compiler);
ADDAPI Sass_Callee_Entry ADDCALL sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx);
// Push function for paths (no manipulation support for now)
ADDAPI void ADDCALL sass_option_push_plugin_path (struct Sass_Options* options, const char* path);
ADDAPI void ADDCALL sass_option_push_include_path (struct Sass_Options* options, const char* path);
// Resolve a file via the given include paths in the sass option struct
// find_file looks for the exact file name while find_include does a regular sass include
ADDAPI char* ADDCALL sass_find_file (const char* path, struct Sass_Options* opt);
ADDAPI char* ADDCALL sass_find_include (const char* path, struct Sass_Options* opt);
// Resolve a file relative to last import or include paths in the sass option struct
// find_file looks for the exact file name while find_include does a regular sass include
ADDAPI char* ADDCALL sass_compiler_find_file (const char* path, struct Sass_Compiler* compiler);
ADDAPI char* ADDCALL sass_compiler_find_include (const char* path, struct Sass_Compiler* compiler);
#ifdef __cplusplus
} // __cplusplus defined.
#endif
......
......@@ -11,12 +11,18 @@ extern "C" {
// Forward declaration
struct Sass_Env;
struct Sass_Callee;
struct Sass_Import;
struct Sass_Options;
struct Sass_Compiler;
struct Sass_Importer;
struct Sass_Function;
// Typedef helpers for callee lists
typedef struct Sass_Env (*Sass_Env_Frame);
// Typedef helpers for callee lists
typedef struct Sass_Callee (*Sass_Callee_Entry);
// Typedef helpers for import lists
typedef struct Sass_Import (*Sass_Import_Entry);
typedef struct Sass_Import* (*Sass_Import_List);
......@@ -34,11 +40,18 @@ typedef struct Sass_Function* (*Sass_Function_List);
typedef union Sass_Value* (*Sass_Function_Fn)
(const union Sass_Value*, Sass_Function_Entry cb, struct Sass_Compiler* compiler);
// Type of function calls
enum Sass_Callee_Type {
SASS_CALLEE_MIXIN,
SASS_CALLEE_FUNCTION,
SASS_CALLEE_C_FUNCTION,
};
// Creator for sass custom importer return argument list
ADDAPI Sass_Importer_List ADDCALL sass_make_importer_list (size_t length);
ADDAPI Sass_Importer_Entry ADDCALL sass_importer_get_list_entry (Sass_Importer_List list, size_t idx);
ADDAPI void ADDCALL sass_importer_set_list_entry (Sass_Importer_List list, size_t idx, Sass_Importer_Entry entry);
ADDAPI void ADDCALL sass_delete_importer_list (Sass_Importer_List list);
// Creators for custom importer callback (with some additional pointer)
......@@ -66,6 +79,22 @@ ADDAPI Sass_Import_Entry ADDCALL sass_import_set_error(Sass_Import_Entry import,
ADDAPI void ADDCALL sass_import_set_list_entry (Sass_Import_List list, size_t idx, Sass_Import_Entry entry);
ADDAPI Sass_Import_Entry ADDCALL sass_import_get_list_entry (Sass_Import_List list, size_t idx);
// Getters for callee entry
ADDAPI const char* ADDCALL sass_callee_get_name (Sass_Callee_Entry);
ADDAPI const char* ADDCALL sass_callee_get_path (Sass_Callee_Entry);
ADDAPI size_t ADDCALL sass_callee_get_line (Sass_Callee_Entry);
ADDAPI size_t ADDCALL sass_callee_get_column (Sass_Callee_Entry);
ADDAPI enum Sass_Callee_Type ADDCALL sass_callee_get_type (Sass_Callee_Entry);
ADDAPI Sass_Env_Frame ADDCALL sass_callee_get_env (Sass_Callee_Entry);
// Getters and Setters for environments (lexical, local and global)
ADDAPI union Sass_Value* ADDCALL sass_env_get_lexical (Sass_Env_Frame, const char*);
ADDAPI void ADDCALL sass_env_set_lexical (Sass_Env_Frame, const char*, union Sass_Value*);
ADDAPI union Sass_Value* ADDCALL sass_env_get_local (Sass_Env_Frame, const char*);
ADDAPI void ADDCALL sass_env_set_local (Sass_Env_Frame, const char*, union Sass_Value*);
ADDAPI union Sass_Value* ADDCALL sass_env_get_global (Sass_Env_Frame, const char*);
ADDAPI void ADDCALL sass_env_set_global (Sass_Env_Frame, const char*, union Sass_Value*);
// Getters for import entry
ADDAPI const char* ADDCALL sass_import_get_imp_path (Sass_Import_Entry);
ADDAPI const char* ADDCALL sass_import_get_abs_path (Sass_Import_Entry);
......@@ -90,6 +119,8 @@ ADDAPI void ADDCALL sass_delete_import (Sass_Import_Entry);
// Creators for sass function list and function descriptors
ADDAPI Sass_Function_List ADDCALL sass_make_function_list (size_t length);
ADDAPI Sass_Function_Entry ADDCALL sass_make_function (const char* signature, Sass_Function_Fn cb, void* cookie);
ADDAPI void ADDCALL sass_delete_function (Sass_Function_Entry entry);
ADDAPI void ADDCALL sass_delete_function_list (Sass_Function_List list);
// Setters and getters for callbacks on function lists
ADDAPI Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos);
......
......@@ -50,7 +50,7 @@ ADDAPI union Sass_Value* ADDCALL sass_make_string (const char* val);
ADDAPI union Sass_Value* ADDCALL sass_make_qstring (const char* val);
ADDAPI union Sass_Value* ADDCALL sass_make_number (double val, const char* unit);
ADDAPI union Sass_Value* ADDCALL sass_make_color (double r, double g, double b, double a);
ADDAPI union Sass_Value* ADDCALL sass_make_list (size_t len, enum Sass_Separator sep);
ADDAPI union Sass_Value* ADDCALL sass_make_list (size_t len, enum Sass_Separator sep, bool is_bracketed);
ADDAPI union Sass_Value* ADDCALL sass_make_map (size_t len);
ADDAPI union Sass_Value* ADDCALL sass_make_error (const char* msg);
ADDAPI union Sass_Value* ADDCALL sass_make_warning (const char* msg);
......@@ -116,6 +116,8 @@ ADDAPI size_t ADDCALL sass_list_get_length (const union Sass_Value* v);
// Getters and setters for Sass_List
ADDAPI enum Sass_Separator ADDCALL sass_list_get_separator (const union Sass_Value* v);
ADDAPI void ADDCALL sass_list_set_separator (union Sass_Value* v, enum Sass_Separator value);
ADDAPI bool ADDCALL sass_list_get_is_bracketed (const union Sass_Value* v);
ADDAPI void ADDCALL sass_list_set_is_bracketed (union Sass_Value* v, bool value);
// Getters and setters for Sass_List values
ADDAPI union Sass_Value* ADDCALL sass_list_get_value (const union Sass_Value* v, size_t i);
ADDAPI void ADDCALL sass_list_set_value (union Sass_Value* v, size_t i, union Sass_Value* value);
......
......@@ -6,7 +6,7 @@
#endif
#ifndef LIBSASS_LANGUAGE_VERSION
#define LIBSASS_LANGUAGE_VERSION "3.4"
#define LIBSASS_LANGUAGE_VERSION "3.5"
#endif
#endif
......@@ -6,7 +6,7 @@
#endif
#ifndef LIBSASS_LANGUAGE_VERSION
#define LIBSASS_LANGUAGE_VERSION "3.4"
#define LIBSASS_LANGUAGE_VERSION "3.5"
#endif
#endif
......@@ -18,9 +18,14 @@ if [ "x$TRAVIS_OS_NAME" == "x" ]; then export TRAVIS_OS_NAME=`uname -s | perl -n
if [ "x$COVERAGE" == "xyes" ]; then
COVERAGE_OPT="--enable-coverage"
export EXTRA_CFLAGS="--coverage"
export EXTRA_CXXFLAGS="--coverage"
export EXTRA_LDFLAGS="--coverage"
export EXTRA_CFLAGS="-fprofile-arcs -ftest-coverage"
export EXTRA_CXXFLAGS="-fprofile-arcs -ftest-coverage"
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
# osx doesn't seem to know gcov lib?
export EXTRA_LDFLAGS="--coverage"
else
export EXTRA_LDFLAGS="-lgcov --coverage"
fi
else
COVERAGE_OPT="--disable-coverage"
fi
......@@ -37,7 +42,7 @@ fi
if [ "$(expr substr $(uname -s) 1 10)" == "MINGW32_NT" ]; then
MAKE_OPTS="$MAKE_OPTS -j1 V=1"
else
MAKE_OPTS="$MAKE_OPTS -j3 V=1"
MAKE_OPTS="$MAKE_OPTS -j5 V=1"
fi
if [ "x$PREFIX" == "x" ]; then
......
#!/bin/bash
PLUGIN=$1
RUBY_BIN=ruby
SASS_SPEC_PATH=sass-spec
SASSC_BIN=sassc/bin/sassc
SASS_SPEC_SPEC_DIR=plugins/libsass-${PLUGIN}/test
if [ -e ./tester ] ; then
SASSC_BIN=./tester
fi
if [ -d ./build/lib ] ; then
cp -a build/lib lib
fi
if [ "x$1" == "x" ] ; then
echo "No plugin name given"
exit 1
fi
if [ "x$COVERAGE" == "0" ] ; then
unset COVERAGE
fi
export EXTRA_CFLAGS=""
export EXTRA_CXXFLAGS=""
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
# osx doesn't seem to know gcov lib?
export EXTRA_LDFLAGS="--coverage"
else
export EXTRA_LDFLAGS="-lgcov --coverage"
fi
mkdir -p plugins
if [ ! -d plugins/libsass-${PLUGIN} ] ; then
git clone https://github.com/mgreter/libsass-${PLUGIN} plugins/libsass-${PLUGIN}
fi
if [ ! -d plugins/libsass-${PLUGIN}/build ] ; then
mkdir plugins/libsass-${PLUGIN}/build
fi
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
cd plugins/libsass-${PLUGIN}/build
cmake -G "Unix Makefiles" -D LIBSASS_DIR="../../.." ..
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
make VERBOSE=1 -j2
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
cd ../../..
# glob only works on paths relative to imports
if [ "x$PLUGIN" == "xglob" ]; then
${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build ${SASS_SPEC_SPEC_DIR}/basic/input.scss > ${SASS_SPEC_SPEC_DIR}/basic/result.css
${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build ${SASS_SPEC_SPEC_DIR}/basic/input.scss --sourcemap > /dev/null
else
cat ${SASS_SPEC_SPEC_DIR}/basic/input.scss | ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build -I ${SASS_SPEC_SPEC_DIR}/basic > ${SASS_SPEC_SPEC_DIR}/basic/result.css
cat ${SASS_SPEC_SPEC_DIR}/basic/input.scss | ${SASSC_BIN} --plugin-path plugins/libsass-${PLUGIN}/build -I ${SASS_SPEC_SPEC_DIR}/basic --sourcemap > /dev/null
fi
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
diff ${SASS_SPEC_SPEC_DIR}/basic/expected_output.css ${SASS_SPEC_SPEC_DIR}/basic/result.css
RETVAL=$?; if [ "$RETVAL" != "0" ]; then exit $RETVAL; fi
......@@ -2,6 +2,12 @@
if [ "x$COVERAGE" = "xyes" ]; then
# find / -name "gcovr"
# find / -name "coveralls"
# this is only needed for mac os x builds!
PATH=$PATH:/Users/travis/Library/Python/2.7/bin/
# exclude some directories from profiling (.libs is from autotools)
export EXCLUDE_COVERAGE="--exclude plugins
--exclude sassc/sassc.c
......@@ -21,10 +27,14 @@ if [ "x$COVERAGE" = "xyes" ]; then
--exclude src/test
--exclude src/posix
--exclude src/debugger.hpp"
# debug via gcovr
gcov -v
# debug used gcov version
# option not available on mac
if [ "$TRAVIS_OS_NAME" != "osx" ]; then
gcov -v
fi
# create summarized report
gcovr -r .
# generate and submit report to coveralls.io
# submit report to coveralls.io
coveralls $EXCLUDE_COVERAGE --gcov-options '\-lp'
else
......
......@@ -34,7 +34,7 @@ include $(top_srcdir)/Makefile.conf
libsass_la_SOURCES = ${CSOURCES} ${SOURCES}
libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 0:9:0
libsass_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 1:0:0
if ENABLE_TESTS
if ENABLE_COVERAGE
......
......@@ -44,7 +44,7 @@ public:\
type name(type name##__) { return name##_ = name##__; }\
private:
#define ADD_HASHED(type, name)\
#define HASH_PROPERTY(type, name)\
protected:\
type name##_;\
public:\
......@@ -52,4 +52,20 @@ public:\
type name(type name##__) { hash_ = 0; return name##_ = name##__; }\
private:
#define ADD_CONSTREF(type, name) \
protected: \
type name##_; \
public: \
const type& name() const { return name##_; } \
void name(type name##__) { name##_ = name##__; } \
private:
#define HASH_CONSTREF(type, name) \
protected: \
type name##_; \
public: \
const type& name() const { return name##_; } \
void name(type name##__) { hash_ = 0; name##_ = name##__; } \
private:
#endif
#include "ast.hpp"
namespace Sass {
#define IMPLEMENT_BASE_CAST(T) \
template<> \
T* Cast(AST_Node* ptr) { \
return dynamic_cast<T*>(ptr); \
}; \
\
template<> \
const T* Cast(const AST_Node* ptr) { \
return dynamic_cast<const T*>(ptr); \
}; \
IMPLEMENT_BASE_CAST(AST_Node)
IMPLEMENT_BASE_CAST(Expression)
IMPLEMENT_BASE_CAST(Statement)
IMPLEMENT_BASE_CAST(Has_Block)
IMPLEMENT_BASE_CAST(PreValue)
IMPLEMENT_BASE_CAST(Value)
IMPLEMENT_BASE_CAST(List)
IMPLEMENT_BASE_CAST(String)
IMPLEMENT_BASE_CAST(String_Constant)
IMPLEMENT_BASE_CAST(Supports_Condition)
IMPLEMENT_BASE_CAST(Selector)
IMPLEMENT_BASE_CAST(Simple_Selector)
}
#ifndef SASS_AST_FWD_DECL_H
#define SASS_AST_FWD_DECL_H
#include <map>
#include <set>
#include <deque>
#include <vector>
#include <typeinfo>
#include <iostream>
#include <algorithm>
#include <unordered_map>
......@@ -353,37 +357,94 @@ namespace Sass {
IMPL_MEM_OBJ(Complex_Selector);
IMPL_MEM_OBJ(Selector_List);
// ###########################################################################
// Implement compare, order and hashing operations for AST Nodes
// ###########################################################################
struct HashExpression {
size_t operator() (Expression_Obj ex) const;
struct HashNodes {
template <class T>
size_t operator() (const T& ex) const {
return ex.isNull() ? 0 : ex->hash();
}
};
struct CompareExpression {
bool operator()(const Expression_Obj& lhs, const Expression_Obj& rhs) const;
struct OrderNodes {
template <class T>
bool operator() (const T& lhs, const T& rhs) const {
return !lhs.isNull() && !rhs.isNull() && *lhs < *rhs;
}
};
struct HashSimpleSelector {
size_t operator() (Simple_Selector_Obj ex) const;
struct CompareNodes {
template <class T>
bool operator() (const T& lhs, const T& rhs) const {
return !lhs.isNull() && !rhs.isNull() && *lhs == *rhs;
}
};
struct CompareSimpleSelector {
bool operator()(Simple_Selector_Obj lhs, Simple_Selector_Obj rhs) const;
};
// ###########################################################################
// some often used typedefs
// ###########################################################################
typedef std::unordered_map<
Expression_Obj, // key
Expression_Obj, // value
HashExpression, // hasher
CompareExpression // compare
HashNodes, // hasher
CompareNodes // compare
> ExpressionMap;
typedef std::unordered_set<
Expression_Obj, // value
HashExpression, // hasher
CompareExpression // compare
HashNodes, // hasher
CompareNodes // compare
> ExpressionSet;
typedef std::string Subset_Map_Key;
typedef std::vector<size_t> Subset_Map_Arr;
typedef std::pair<Complex_Selector_Obj, Compound_Selector_Obj> Subset_Map_Val;
typedef std::string SubSetMapKey;
typedef std::vector<std::string> SubSetMapKeys;
typedef std::pair<Complex_Selector_Obj, Compound_Selector_Obj> SubSetMapPair;
typedef std::pair<Compound_Selector_Obj, Complex_Selector_Obj> SubSetMapLookup;
typedef std::vector<SubSetMapPair> SubSetMapPairs;
typedef std::vector<SubSetMapLookup> SubSetMapLookups;
typedef std::pair<Complex_Selector_Obj, SubSetMapPairs> SubSetMapResult;
typedef std::vector<SubSetMapResult> SubSetMapResults;
typedef std::deque<Complex_Selector_Obj> ComplexSelectorDeque;
typedef std::set<Simple_Selector_Obj, OrderNodes> SimpleSelectorSet;
typedef std::set<Complex_Selector_Obj, OrderNodes> ComplexSelectorSet;
typedef std::unordered_set<Simple_Selector_Obj, HashNodes, CompareNodes> SimpleSelectorDict;
// ###########################################################################
// explicit type conversion functions
// ###########################################################################
template<class T>
T* Cast(AST_Node* ptr);
template<class T>
const T* Cast(const AST_Node* ptr);
// sometimes you know the class you want to cast to is final
// in this case a simple typeid check is faster and safe to use
#define DECLARE_BASE_CAST(T) \
template<> T* Cast(AST_Node* ptr); \
template<> const T* Cast(const AST_Node* ptr); \
// ###########################################################################
// implement specialization for final classes
// ###########################################################################
DECLARE_BASE_CAST(AST_Node)
DECLARE_BASE_CAST(Expression)
DECLARE_BASE_CAST(Statement)
DECLARE_BASE_CAST(Has_Block)
DECLARE_BASE_CAST(PreValue)
DECLARE_BASE_CAST(Value)
DECLARE_BASE_CAST(List)
DECLARE_BASE_CAST(String)
DECLARE_BASE_CAST(String_Constant)
DECLARE_BASE_CAST(Supports_Condition)
DECLARE_BASE_CAST(Selector)
DECLARE_BASE_CAST(Simple_Selector)
}
......
......@@ -21,7 +21,7 @@ namespace Sass {
caller(c)
{ }
std::string to_string(bool warning = false)
const std::string to_string(bool warning = false)
{
size_t i = -1;
std::stringstream ss;
......
......@@ -16,7 +16,7 @@ namespace Sass {
std::map<std::string, Parameter_Obj> param_map;
for (size_t i = 0, L = as->length(); i < L; ++i) {
if (auto str = SASS_MEMORY_CAST(String_Quoted, (*as)[i]->value())) {
if (auto str = Cast<String_Quoted>((*as)[i]->value())) {
// force optional quotes (only if needed)
if (str->quote_mark()) {
str->quote_mark('*');
......@@ -42,7 +42,7 @@ namespace Sass {
if (ip >= LP) {
// skip empty rest arguments
if (a->is_rest_argument()) {
if (List_Obj l = SASS_MEMORY_CAST(List, a->value())) {
if (List_Obj l = Cast<List>(a->value())) {
if (l->length() == 0) {
++ ia; continue;
}
......@@ -61,7 +61,7 @@ namespace Sass {
if (a->is_rest_argument()) {
// We should always get a list for rest arguments
if (List_Obj rest = SASS_MEMORY_CAST(List, a->value())) {
if (List_Obj rest = Cast<List>(a->value())) {
// create a new list object for wrapped items
List_Ptr arglist = SASS_MEMORY_NEW(List,
p->pstate(),
......@@ -70,12 +70,12 @@ namespace Sass {
true);
// wrap each item from list as an argument
for (Expression_Obj item : rest->elements()) {
if (Argument_Obj arg = SASS_MEMORY_CAST(Argument, item)) {
if (Argument_Obj arg = Cast<Argument>(item)) {
arglist->append(SASS_MEMORY_COPY(arg)); // copy
} else {
arglist->append(SASS_MEMORY_NEW(Argument,
item->pstate(),
&item,
item,
"",
false,
false));
......@@ -93,9 +93,9 @@ namespace Sass {
// expand keyword arguments into their parameters
List_Ptr arglist = SASS_MEMORY_NEW(List, p->pstate(), 0, SASS_COMMA, true);
env->local_frame()[p->name()] = arglist;
Map_Obj argmap = SASS_MEMORY_CAST(Map, a->value());
Map_Obj argmap = Cast<Map>(a->value());
for (auto key : argmap->keys()) {
std::string name = unquote(SASS_MEMORY_CAST(String_Constant, key)->value());
std::string name = unquote(Cast<String_Constant>(key)->value());
arglist->append(SASS_MEMORY_NEW(Argument,
key->pstate(),
argmap->at(key),
......@@ -117,25 +117,25 @@ namespace Sass {
// get and post inc
a = (*as)[ia++];
// maybe we have another list as argument
List_Obj ls = SASS_MEMORY_CAST(List, a->value());
List_Obj ls = Cast<List>(a->value());
// skip any list completely if empty
if (ls && ls->empty() && a->is_rest_argument()) continue;
Expression_Obj value = a->value();
if (Argument_Obj arg = SASS_MEMORY_CAST(Argument, value)) {
arglist->append(&arg);
if (Argument_Obj arg = Cast<Argument>(value)) {
arglist->append(arg);
}
// check if we have rest argument
else if (a->is_rest_argument()) {
// preserve the list separator from rest args
if (List_Obj rest = SASS_MEMORY_CAST(List, a->value())) {
if (List_Obj rest = Cast<List>(a->value())) {
arglist->separator(rest->separator());
for (size_t i = 0, L = rest->size(); i < L; ++i) {
Expression_Obj obj = rest->at(i);
arglist->append(SASS_MEMORY_NEW(Argument,
obj->pstate(),
&obj,
obj,
"",
false,
false));
......@@ -155,7 +155,7 @@ namespace Sass {
}
}
// assign new arglist to environment
env->local_frame()[p->name()] = &arglist;
env->local_frame()[p->name()] = arglist;
}
// consumed parameter
++ip;
......@@ -166,7 +166,7 @@ namespace Sass {
// If the current argument is the rest argument, extract a value for processing
else if (a->is_rest_argument()) {
// normal param and rest arg
List_Obj arglist = SASS_MEMORY_CAST(List, a->value());
List_Obj arglist = Cast<List>(a->value());
// empty rest arg - treat all args as default values
if (!arglist->length()) {
break;
......@@ -187,8 +187,8 @@ namespace Sass {
}
// otherwise move one of the rest args into the param, converting to argument if necessary
Expression_Obj obj = arglist->at(0);
if (!(a = SASS_MEMORY_CAST(Argument, obj))) {
Expression_Ptr a_to_convert = &obj;
if (!(a = Cast<Argument>(obj))) {
Expression_Ptr a_to_convert = obj;
a = SASS_MEMORY_NEW(Argument,
a_to_convert->pstate(),
a_to_convert,
......@@ -202,17 +202,17 @@ namespace Sass {
}
} else if (a->is_keyword_argument()) {
Map_Obj argmap = SASS_MEMORY_CAST(Map, a->value());
Map_Obj argmap = Cast<Map>(a->value());
for (auto key : argmap->keys()) {
std::string name = "$" + unquote(SASS_MEMORY_CAST(String_Constant, key)->value());
std::string name = "$" + unquote(Cast<String_Constant>(key)->value());
if (!param_map.count(name)) {
std::stringstream msg;
msg << callee << " has no parameter named " << name;
error(msg.str(), a->pstate());
}
env->local_frame()[name] = &argmap->at(&key);
env->local_frame()[name] = argmap->at(key);
}
++ia;
continue;
......@@ -228,7 +228,7 @@ namespace Sass {
error(msg.str(), a->pstate());
}
// ordinal arg -- bind it to the next param
env->local_frame()[p->name()] = &a->value();
env->local_frame()[p->name()] = a->value();
++ip;
}
else {
......@@ -250,7 +250,7 @@ namespace Sass {
<< "provided more than once in call to " << callee;
error(msg.str(), a->pstate());
}
env->local_frame()[a->name()] = &a->value();
env->local_frame()[a->name()] = a->value();
}
}
// EO while ia
......
......@@ -6,7 +6,6 @@
#include "ast_fwd_decl.hpp"
namespace Sass {
typedef Environment<AST_Node_Obj> Env;
void bind(std::string type, std::string name, Parameters_Obj, Arguments_Obj, Context*, Env*, Eval*);
}
......
......@@ -15,7 +15,7 @@ namespace Sass {
{
Statement_Ptr old_parent = this->parent;
if (At_Root_Block_Ptr root = SASS_MEMORY_CAST_PTR(At_Root_Block, parent)) {
if (At_Root_Block_Ptr root = Cast<At_Root_Block>(parent)) {
std::vector<Statement_Ptr> old_parents = this->parents;
std::vector<Statement_Ptr> new_parents;
......@@ -39,8 +39,8 @@ namespace Sass {
}
}
At_Root_Block_Ptr ar = SASS_MEMORY_CAST_PTR(At_Root_Block, parent);
Statement_Ptr ret = this->visit_children(&ar->block());
At_Root_Block_Ptr ar = Cast<At_Root_Block>(parent);
Statement_Ptr ret = this->visit_children(ar->block());
this->parent = old_parent;
this->parents = old_parents;
......@@ -54,11 +54,11 @@ namespace Sass {
this->parents.push_back(parent);
Block_Ptr b = SASS_MEMORY_CAST_PTR(Block, parent);
Block_Ptr b = Cast<Block>(parent);
if (!b) {
if (Has_Block_Ptr bb = SASS_MEMORY_CAST(Has_Block, *parent)) {
b = &bb->block();
if (Has_Block_Ptr bb = Cast<Has_Block>(parent)) {
b = bb->block();
}
}
......@@ -99,8 +99,8 @@ namespace Sass {
Statement_Ptr CheckNesting::fallback_impl(Statement_Ptr s)
{
Block_Ptr b1 = SASS_MEMORY_CAST_PTR(Block, s);
Has_Block_Ptr b2 = SASS_MEMORY_CAST_PTR(Has_Block, s);
Block_Ptr b1 = Cast<Block>(s);
Has_Block_Ptr b2 = Cast<Has_Block>(s);
return b1 || b2 ? visit_children(s) : s;
}
......@@ -108,16 +108,16 @@ namespace Sass {
{
if (!this->parent) return true;
if (SASS_MEMORY_CAST_PTR(Content, node))
if (Cast<Content>(node))
{ this->invalid_content_parent(this->parent); }
if (is_charset(node))
{ this->invalid_charset_parent(this->parent); }
if (SASS_MEMORY_CAST_PTR(Extension, node))
if (Cast<Extension>(node))
{ this->invalid_extend_parent(this->parent); }
// if (SASS_MEMORY_CAST(Import, node))
// if (Cast<Import>(node))
// { this->invalid_import_parent(this->parent); }
if (this->is_mixin(node))
......@@ -129,13 +129,13 @@ namespace Sass {
if (this->is_function(this->parent))
{ this->invalid_function_child(node); }
if (SASS_MEMORY_CAST_PTR(Declaration, node))
if (Cast<Declaration>(node))
{ this->invalid_prop_parent(this->parent); }
if (SASS_MEMORY_CAST_PTR(Declaration, this->parent))
if (Cast<Declaration>(this->parent))
{ this->invalid_prop_child(node); }
if (SASS_MEMORY_CAST_PTR(Return, node))
if (Cast<Return>(node))
{ this->invalid_return_parent(this->parent); }
return true;
......@@ -166,8 +166,8 @@ namespace Sass {
void CheckNesting::invalid_extend_parent(Statement_Ptr parent)
{
if (!(
SASS_MEMORY_CAST_PTR(Ruleset, parent) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, parent) ||
Cast<Ruleset>(parent) ||
Cast<Mixin_Call>(parent) ||
is_mixin(parent)
)) {
throw Exception::InvalidSass(
......@@ -181,12 +181,12 @@ namespace Sass {
// {
// for (auto pp : this->parents) {
// if (
// SASS_MEMORY_CAST(Each, pp) ||
// SASS_MEMORY_CAST(For, pp) ||
// SASS_MEMORY_CAST(If, pp) ||
// SASS_MEMORY_CAST(While, pp) ||
// SASS_MEMORY_CAST(Trace, pp) ||
// SASS_MEMORY_CAST(Mixin_Call, pp) ||
// Cast<Each>(pp) ||
// Cast<For>(pp) ||
// Cast<If>(pp) ||
// Cast<While>(pp) ||
// Cast<Trace>(pp) ||
// Cast<Mixin_Call>(pp) ||
// is_mixin(pp)
// ) {
// throw Exception::InvalidSass(
......@@ -212,12 +212,12 @@ namespace Sass {
{
for (Statement_Ptr pp : this->parents) {
if (
SASS_MEMORY_CAST_PTR(Each, pp) ||
SASS_MEMORY_CAST_PTR(For, pp) ||
SASS_MEMORY_CAST_PTR(If, pp) ||
SASS_MEMORY_CAST_PTR(While, pp) ||
SASS_MEMORY_CAST_PTR(Trace, pp) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, pp) ||
Cast<Each>(pp) ||
Cast<For>(pp) ||
Cast<If>(pp) ||
Cast<While>(pp) ||
Cast<Trace>(pp) ||
Cast<Mixin_Call>(pp) ||
is_mixin(pp)
) {
throw Exception::InvalidSass(
......@@ -232,12 +232,12 @@ namespace Sass {
{
for (Statement_Ptr pp : this->parents) {
if (
SASS_MEMORY_CAST_PTR(Each, pp) ||
SASS_MEMORY_CAST_PTR(For, pp) ||
SASS_MEMORY_CAST_PTR(If, pp) ||
SASS_MEMORY_CAST_PTR(While, pp) ||
SASS_MEMORY_CAST_PTR(Trace, pp) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, pp) ||
Cast<Each>(pp) ||
Cast<For>(pp) ||
Cast<If>(pp) ||
Cast<While>(pp) ||
Cast<Trace>(pp) ||
Cast<Mixin_Call>(pp) ||
is_mixin(pp)
) {
throw Exception::InvalidSass(
......@@ -251,19 +251,19 @@ namespace Sass {
void CheckNesting::invalid_function_child(Statement_Ptr child)
{
if (!(
SASS_MEMORY_CAST_PTR(Each, child) ||
SASS_MEMORY_CAST_PTR(For, child) ||
SASS_MEMORY_CAST_PTR(If, child) ||
SASS_MEMORY_CAST_PTR(While, child) ||
SASS_MEMORY_CAST_PTR(Trace, child) ||
SASS_MEMORY_CAST_PTR(Comment, child) ||
SASS_MEMORY_CAST_PTR(Debug, child) ||
SASS_MEMORY_CAST_PTR(Return, child) ||
SASS_MEMORY_CAST_PTR(Variable, child) ||
Cast<Each>(child) ||
Cast<For>(child) ||
Cast<If>(child) ||
Cast<While>(child) ||
Cast<Trace>(child) ||
Cast<Comment>(child) ||
Cast<Debug>(child) ||
Cast<Return>(child) ||
Cast<Variable>(child) ||
// Ruby Sass doesn't distinguish variables and assignments
SASS_MEMORY_CAST_PTR(Assignment, child) ||
SASS_MEMORY_CAST_PTR(Warning, child) ||
SASS_MEMORY_CAST_PTR(Error, child)
Cast<Assignment>(child) ||
Cast<Warning>(child) ||
Cast<Error>(child)
)) {
throw Exception::InvalidSass(
child->pstate(),
......@@ -275,14 +275,14 @@ namespace Sass {
void CheckNesting::invalid_prop_child(Statement_Ptr child)
{
if (!(
SASS_MEMORY_CAST_PTR(Each, child) ||
SASS_MEMORY_CAST_PTR(For, child) ||
SASS_MEMORY_CAST_PTR(If, child) ||
SASS_MEMORY_CAST_PTR(While, child) ||
SASS_MEMORY_CAST_PTR(Trace, child) ||
SASS_MEMORY_CAST_PTR(Comment, child) ||
SASS_MEMORY_CAST_PTR(Declaration, child) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, child)
Cast<Each>(child) ||
Cast<For>(child) ||
Cast<If>(child) ||
Cast<While>(child) ||
Cast<Trace>(child) ||
Cast<Comment>(child) ||
Cast<Declaration>(child) ||
Cast<Mixin_Call>(child)
)) {
throw Exception::InvalidSass(
child->pstate(),
......@@ -296,10 +296,10 @@ namespace Sass {
if (!(
is_mixin(parent) ||
is_directive_node(parent) ||
SASS_MEMORY_CAST_PTR(Ruleset, parent) ||
SASS_MEMORY_CAST_PTR(Keyframe_Rule, parent) ||
SASS_MEMORY_CAST_PTR(Declaration, parent) ||
SASS_MEMORY_CAST_PTR(Mixin_Call, parent)
Cast<Ruleset>(parent) ||
Cast<Keyframe_Rule>(parent) ||
Cast<Declaration>(parent) ||
Cast<Mixin_Call>(parent)
)) {
throw Exception::InvalidSass(
parent->pstate(),
......@@ -326,51 +326,51 @@ namespace Sass {
!is_root_node(grandparent) &&
!is_at_root_node(grandparent);
return SASS_MEMORY_CAST_PTR(Import, parent) ||
SASS_MEMORY_CAST_PTR(Each, parent) ||
SASS_MEMORY_CAST_PTR(For, parent) ||
SASS_MEMORY_CAST_PTR(If, parent) ||
SASS_MEMORY_CAST_PTR(While, parent) ||
SASS_MEMORY_CAST_PTR(Trace, parent) ||
return Cast<Import>(parent) ||
Cast<Each>(parent) ||
Cast<For>(parent) ||
Cast<If>(parent) ||
Cast<While>(parent) ||
Cast<Trace>(parent) ||
valid_bubble_node;
}
bool CheckNesting::is_charset(Statement_Ptr n)
{
Directive_Ptr d = SASS_MEMORY_CAST_PTR(Directive, n);
Directive_Ptr d = Cast<Directive>(n);
return d && d->keyword() == "charset";
}
bool CheckNesting::is_mixin(Statement_Ptr n)
{
Definition_Ptr def = SASS_MEMORY_CAST_PTR(Definition, n);
Definition_Ptr def = Cast<Definition>(n);
return def && def->type() == Definition::MIXIN;
}
bool CheckNesting::is_function(Statement_Ptr n)
{
Definition_Ptr def = SASS_MEMORY_CAST_PTR(Definition, n);
Definition_Ptr def = Cast<Definition>(n);
return def && def->type() == Definition::FUNCTION;
}
bool CheckNesting::is_root_node(Statement_Ptr n)
{
if (SASS_MEMORY_CAST_PTR(Ruleset, n)) return false;
if (Cast<Ruleset>(n)) return false;
Block_Ptr b = SASS_MEMORY_CAST_PTR(Block, n);
Block_Ptr b = Cast<Block>(n);
return b && b->is_root();
}
bool CheckNesting::is_at_root_node(Statement_Ptr n)
{
return SASS_MEMORY_CAST_PTR(At_Root_Block, n) != NULL;
return Cast<At_Root_Block>(n) != NULL;
}
bool CheckNesting::is_directive_node(Statement_Ptr n)
{
return SASS_MEMORY_CAST_PTR(Directive, n) ||
SASS_MEMORY_CAST_PTR(Import, n) ||
SASS_MEMORY_CAST_PTR(Media_Block, n) ||
SASS_MEMORY_CAST_PTR(Supports_Block, n);
return Cast<Directive>(n) ||
Cast<Import>(n) ||
Cast<Media_Block>(n) ||
Cast<Supports_Block>(n);
}
}
......@@ -6,8 +6,6 @@
namespace Sass {
typedef Environment<AST_Node_Obj> Env;
class CheckNesting : public Operation_CRTP<Statement_Ptr, CheckNesting> {
std::vector<Statement_Ptr> parents;
......@@ -27,7 +25,7 @@ namespace Sass {
template <typename U>
Statement_Ptr fallback(U x) {
Statement_Ptr n = SASS_MEMORY_CAST_PTR(Statement, x);
Statement_Ptr n = Cast<Statement>(x);
if (this->should_visit(n)) {
return fallback_impl(n);
}
......
#ifndef SASS_COLOR_MAPS_H
#define SASS_COLOR_MAPS_H
......@@ -319,14 +320,11 @@ namespace Sass {
extern const Color transparent;
}
extern const std::map<const int, const char*> colors_to_names;
extern const std::map<const char*, Color_Ptr_Const, map_cmp_str> names_to_colors;
extern Color_Ptr_Const name_to_color(const char*);
extern Color_Ptr_Const name_to_color(const std::string&);
extern const char* color_to_name(const int);
extern const char* color_to_name(const Color&);
extern const char* color_to_name(const double);
Color_Ptr_Const name_to_color(const char*);
Color_Ptr_Const name_to_color(const std::string&);
const char* color_to_name(const int);
const char* color_to_name(const Color&);
const char* color_to_name(const double);
}
......
......@@ -87,8 +87,9 @@ namespace Sass {
{
// add cwd to include paths
include_paths.push_back(CWD);
// Sass 3.4: The current working directory will no longer be placed onto the Sass load path by default.
// If you need the current working directory to be available, set SASS_PATH=. in your shell's environment.
// include_paths.push_back(CWD);
// collect more paths from different options
collect_include_paths(c_options.include_path);
......@@ -391,8 +392,8 @@ namespace Sass {
String_Constant_Ptr loc = SASS_MEMORY_NEW(String_Constant, pstate, unquote(load_path));
Argument_Obj loc_arg = SASS_MEMORY_NEW(Argument, pstate, loc);
Arguments_Obj loc_args = SASS_MEMORY_NEW(Arguments, pstate);
loc_args->append(&loc_arg);
Function_Call_Ptr new_url = SASS_MEMORY_NEW(Function_Call, pstate, "url", &loc_args);
loc_args->append(loc_arg);
Function_Call_Ptr new_url = SASS_MEMORY_NEW(Function_Call, pstate, "url", loc_args);
imp->urls().push_back(new_url);
}
else {
......@@ -528,11 +529,11 @@ namespace Sass {
Import_Obj imp = SASS_MEMORY_NEW(Import, pstate);
// dispatch headers which will add custom functions
// custom headers are added to the import instance
call_headers(entry_path, ctx_path, pstate, &imp);
call_headers(entry_path, ctx_path, pstate, imp);
// increase head count to skip later
head_imports += resources.size() - 1;
// add the statement if we have urls
if (!imp->urls().empty()) root->append(&imp);
if (!imp->urls().empty()) root->append(imp);
// process all other resources (add Import_Stub nodes)
for (size_t i = 0, S = imp->incs().size(); i < S; ++i) {
root->append(SASS_MEMORY_NEW(Import_Stub, pstate, imp->incs()[i]));
......@@ -650,24 +651,24 @@ namespace Sass {
Cssize cssize(*this, &backtrace);
CheckNesting check_nesting;
// check nesting
check_nesting(&root);
check_nesting(root);
// expand and eval the tree
root = expand(&root);
root = expand(root);
// check nesting
check_nesting(&root);
check_nesting(root);
// merge and bubble certain rules
root = cssize(&root);
root = cssize(root);
// should we extend something?
if (!subset_map.empty()) {
// create crtp visitor object
Extend extend(*this, subset_map);
// extend tree nodes
extend(&root);
extend(root);
}
// clean up by removing empty placeholders
// ToDo: maybe we can do this somewhere else?
Remove_Placeholders remove_placeholders(*this);
Remove_Placeholders remove_placeholders;
root->perform(&remove_placeholders);
// return processed tree
return root;
......@@ -810,6 +811,7 @@ namespace Sass {
register_function(ctx, append_sig, append, env);
register_function(ctx, zip_sig, zip, env);
register_function(ctx, list_separator_sig, list_separator, env);
register_function(ctx, is_bracketed_sig, is_bracketed, env);
// Map Functions
register_function(ctx, map_get_sig, map_get, env);
register_function(ctx, map_merge_sig, map_merge, env);
......
......@@ -50,6 +50,7 @@ namespace Sass {
std::map<const std::string, StyleSheet> sheets;
Subset_Map subset_map;
std::vector<Sass_Import_Entry> import_stack;
std::vector<Sass_Callee> callee_stack;
struct Sass_Compiler* c_compiler;
......
......@@ -8,7 +8,6 @@
namespace Sass {
typedef Environment<AST_Node_Obj> Env;
struct Backtrace;
class Cssize : public Operation_CRTP<Statement_Ptr, Cssize> {
......
......@@ -178,8 +178,8 @@ namespace Sass {
std::cerr << prefix << std::string(indent, ' ') << "== " << this << std::endl;
for (typename std::map<std::string, T>::iterator i = local_frame_.begin(); i != local_frame_.end(); ++i) {
if (!ends_with(i->first, "[f]") && !ends_with(i->first, "[f]4") && !ends_with(i->first, "[f]2")) {
std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second;
if (Value_Ptr val = SASS_MEMORY_CAST_PTR(Value, i->second))
std::cerr << prefix << std::string(indent, ' ') << i->first << " " << i->second;
if (Value_Ptr val = Cast<Value>(i->second))
{ std::cerr << " : " << val->to_string(); }
std::cerr << std::endl;
}
......
......@@ -87,6 +87,9 @@ namespace Sass {
};
// define typedef for our use case
typedef Environment<AST_Node_Obj> Env;
}
#endif
......@@ -13,14 +13,12 @@ namespace Sass {
class Listize;
class Context;
class Eval;
typedef Environment<AST_Node_Obj> Env;
struct Backtrace;
class Expand : public Operation_CRTP<Statement_Ptr, Expand> {
public:
Env* environment();
Context& context();
Selector_List_Obj selector();
Backtrace* backtrace();
......
......@@ -20,6 +20,7 @@
#include "context.hpp"
#include "prelexer.hpp"
#include "utf8_string.hpp"
#include "sass_functions.hpp"
#include "sass2scss.h"
#ifdef _WIN32
......@@ -301,13 +302,9 @@ namespace Sass {
// (2) underscore + given
// (3) underscore + given + extension
// (4) given + extension
std::vector<Include> resolve_includes(const std::string& root, const std::string& file)
std::vector<Include> resolve_includes(const std::string& root, const std::string& file, const std::vector<std::string>& exts)
{
std::string filename = join_paths(root, file);
// supported extensions
const std::vector<std::string> exts = {
".scss", ".sass", ".css"
};
// split the filename
std::string base(dir_name(file));
std::string name(base_name(file));
......@@ -336,9 +333,42 @@ namespace Sass {
return includes;
}
// helper function to resolve a filename
std::vector<std::string> find_files(const std::string& file, const std::vector<std::string> paths)
{
std::vector<std::string> includes;
for (std::string path : paths) {
std::string abs_path(join_paths(path, file));
if (file_exists(abs_path)) includes.push_back(abs_path);
}
return includes;
}
std::vector<std::string> find_files(const std::string& file, struct Sass_Compiler* compiler)
{
// get the last import entry to get current base directory
// struct Sass_Options* options = sass_compiler_get_options(compiler);
Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
// create the vector with paths to lookup
std::vector<std::string> paths(1 + incs.size());
paths.push_back(dir_name(import->abs_path));
paths.insert(paths.end(), incs.begin(), incs.end());
// dispatch to find files in paths
return find_files(file, paths);
}
// helper function to search one file in all include paths
// this is normally not used internally by libsass (C-API sugar)
std::string find_file(const std::string& file, const std::vector<std::string> paths)
{
if (file.empty()) return file;
auto res = find_files(file, paths);
return res.empty() ? "" : res.front();
}
// helper function to resolve a filename
std::string find_include(const std::string& file, const std::vector<std::string> paths)
{
// search in every include path for a match
for (size_t i = 0, S = paths.size(); i < S; ++i)
{
......@@ -349,20 +379,6 @@ namespace Sass {
return std::string("");
}
// inc paths can be directly passed from C code
std::string find_file(const std::string& file, const char* paths[])
{
if (paths == 0) return std::string("");
std::vector<std::string> includes(0);
// includes.push_back(".");
const char** it = paths;
while (it && *it) {
includes.push_back(*it);
++it;
}
return find_file(file, includes);
}
// try to load the given filename
// returned memory must be freed
// will auto convert .sass files
......@@ -414,5 +430,25 @@ namespace Sass {
}
}
// split a path string delimited by semicolons or colons (OS dependent)
std::vector<std::string> split_path_list(const char* str)
{
std::vector<std::string> paths;
if (str == NULL) return paths;
// find delimiter via prelexer (return zero at end)
const char* end = Prelexer::find_first<PATH_SEP>(str);
// search until null delimiter
while (end) {
// add path from current position to delimiter
paths.push_back(std::string(str, end - str));
str = end + 1; // skip delimiter
end = Prelexer::find_first<PATH_SEP>(str);
}
// add path from current position to end
paths.push_back(std::string(str));
// return back
return paths;
}
}
}
......@@ -4,6 +4,7 @@
#include <string>
#include <vector>
#include "sass/context.h"
#include "ast_fwd_decl.hpp"
namespace Sass {
......@@ -47,9 +48,16 @@ namespace Sass {
std::string abs2rel(const std::string& path, const std::string& base = ".", const std::string& cwd = get_cwd());
// helper function to resolve a filename
// searching without variations in all paths
std::string find_file(const std::string& file, struct Sass_Compiler* options);
std::string find_file(const std::string& file, const std::vector<std::string> paths);
// inc paths can be directly passed from C code
std::string find_file(const std::string& file, const char** paths);
// helper function to resolve a include filename
// this has the original resolve logic for sass include
std::string find_include(const std::string& file, const std::vector<std::string> paths);
// split a path string delimited by semicolons or colons (OS dependent)
std::vector<std::string> split_path_list(const char* paths);
// try to load the given filename
// returned memory must be freed
......@@ -113,7 +121,10 @@ namespace Sass {
namespace File {
std::vector<Include> resolve_includes(const std::string& root, const std::string& file);
static std::vector<std::string> defaultExtensions = { ".scss", ".sass", ".css" };
std::vector<Include> resolve_includes(const std::string& root, const std::string& file,
const std::vector<std::string>& exts = defaultExtensions);
}
......
......@@ -12,7 +12,6 @@ name(Env& env, Env& d_env, Context& ctx, Signature sig, ParserState pstate, Back
namespace Sass {
struct Backtrace;
typedef Environment<AST_Node_Obj> Env;
typedef const char* Signature;
typedef Expression_Ptr (*Native_Function)(Env&, Env&, Context&, Signature, ParserState, Backtrace*, std::vector<Selector_List_Obj>);
......@@ -89,7 +88,6 @@ namespace Sass {
extern Signature call_sig;
extern Signature not_sig;
extern Signature if_sig;
extern Signature image_url_sig;
extern Signature map_get_sig;
extern Signature map_merge_sig;
extern Signature map_remove_sig;
......@@ -107,6 +105,7 @@ namespace Sass {
extern Signature is_superselector_sig;
extern Signature simple_selectors_sig;
extern Signature selector_parse_sig;
extern Signature is_bracketed_sig;
BUILT_IN(rgb);
BUILT_IN(rgba_4);
......@@ -171,7 +170,6 @@ namespace Sass {
BUILT_IN(call);
BUILT_IN(sass_not);
BUILT_IN(sass_if);
BUILT_IN(image_url);
BUILT_IN(map_get);
BUILT_IN(map_merge);
BUILT_IN(map_remove);
......@@ -189,6 +187,7 @@ namespace Sass {
BUILT_IN(is_superselector);
BUILT_IN(simple_selectors);
BUILT_IN(selector_parse);
BUILT_IN(is_bracketed);
}
}
......
......@@ -166,7 +166,7 @@ namespace Sass {
import->urls().front()->perform(this);
if (import->urls().size() == 1) {
if (&import->import_queries()) {
if (import->import_queries()) {
append_mandatory_space();
import->import_queries()->perform(this);
}
......@@ -179,7 +179,7 @@ namespace Sass {
import->urls()[i]->perform(this);
if (import->urls().size() - 1 == i) {
if (&import->import_queries()) {
if (import->import_queries()) {
append_mandatory_space();
import->import_queries()->perform(this);
}
......@@ -360,10 +360,19 @@ namespace Sass {
append_string(")");
}
std::string Inspect::lbracket(List_Ptr list) {
return list->is_bracketed() ? "[" : "(";
}
std::string Inspect::rbracket(List_Ptr list) {
return list->is_bracketed() ? "]" : ")";
}
void Inspect::operator()(List_Ptr list)
{
if (output_style() == TO_SASS && list->empty()) {
append_string("()");
if (list->empty() && (output_style() == TO_SASS || list->is_bracketed())) {
append_string(lbracket(list));
append_string(rbracket(list));
return;
}
std::string sep(list->separator() == SASS_SPACE ? " " : ",");
......@@ -374,19 +383,24 @@ namespace Sass {
bool was_space_array = in_space_array;
bool was_comma_array = in_comma_array;
// if the list is bracketed, always include the left bracket
if (list->is_bracketed()) {
append_string(lbracket(list));
}
// probably ruby sass eqivalent of element_needs_parens
if (output_style() == TO_SASS &&
else if (output_style() == TO_SASS &&
list->length() == 1 &&
!list->from_selector() &&
!SASS_MEMORY_CAST(List, list->at(0)) &&
!SASS_MEMORY_CAST(Selector_List, list->at(0))) {
append_string("(");
!Cast<List>(list->at(0)) &&
!Cast<Selector_List>(list->at(0))
) {
append_string(lbracket(list));
}
else if (!in_declaration && (list->separator() == SASS_HASH ||
(list->separator() == SASS_SPACE && in_space_array) ||
(list->separator() == SASS_COMMA && in_comma_array)
)) {
append_string("(");
append_string(lbracket(list));
}
if (list->separator() == SASS_SPACE) in_space_array = true;
......@@ -399,7 +413,7 @@ namespace Sass {
if (output_style() != TO_SASS) {
if (list_item->is_invisible()) {
// this fixes an issue with "" in a list
if (!SASS_MEMORY_CAST(String_Constant, list_item)) {
if (!Cast<String_Constant>(list_item)) {
continue;
}
}
......@@ -415,19 +429,29 @@ namespace Sass {
in_comma_array = was_comma_array;
in_space_array = was_space_array;
// if the list is bracketed, always include the right bracket
if (list->is_bracketed()) {
if (list->separator() == SASS_COMMA && list->size() == 1) {
append_string(",");
}
append_string(rbracket(list));
}
// probably ruby sass eqivalent of element_needs_parens
if (output_style() == TO_SASS &&
else if (output_style() == TO_SASS &&
list->length() == 1 &&
!list->from_selector() &&
!SASS_MEMORY_CAST(List, list->at(0)) &&
!SASS_MEMORY_CAST(Selector_List, list->at(0))) {
append_string(",)");
!Cast<List>(list->at(0)) &&
!Cast<Selector_List>(list->at(0))
) {
append_string(",");
append_string(rbracket(list));
}
else if (!in_declaration && (list->separator() == SASS_HASH ||
(list->separator() == SASS_SPACE && in_space_array) ||
(list->separator() == SASS_COMMA && in_comma_array)
)) {
append_string(")");
append_string(rbracket(list));
}
}
......@@ -443,7 +467,7 @@ namespace Sass {
expr->is_right_interpolant())
)) append_string(" ");
switch (expr->type()) {
switch (expr->optype()) {
case Sass_OP::AND: append_string("&&"); break;
case Sass_OP::OR: append_string("||"); break;
case Sass_OP::EQ: append_string("=="); break;
......@@ -471,8 +495,8 @@ namespace Sass {
void Inspect::operator()(Unary_Expression_Ptr expr)
{
if (expr->type() == Unary_Expression::PLUS) append_string("+");
else append_string("-");
if (expr->optype() == Unary_Expression::PLUS) append_string("+");
else append_string("-");
expr->operand()->perform(this);
}
......@@ -744,9 +768,9 @@ namespace Sass {
{
append_token("not", sn);
append_mandatory_space();
if (sn->needs_parens(&sn->condition())) append_string("(");
if (sn->needs_parens(sn->condition())) append_string("(");
sn->condition()->perform(this);
if (sn->needs_parens(&sn->condition())) append_string(")");
if (sn->needs_parens(sn->condition())) append_string(")");
}
void Inspect::operator()(Supports_Declaration_Ptr sd)
......@@ -766,7 +790,7 @@ namespace Sass {
void Inspect::operator()(Media_Query_Ptr mq)
{
size_t i = 0;
if (&mq->media_type()) {
if (mq->media_type()) {
if (mq->is_negated()) append_string("not ");
else if (mq->is_restricted()) append_string("only ");
mq->media_type()->perform(this);
......@@ -851,7 +875,7 @@ namespace Sass {
return;
}
if (a->value()->concrete_type() == Expression::STRING) {
String_Constant_Ptr s = SASS_MEMORY_CAST(String_Constant, a->value());
String_Constant_Ptr s = Cast<String_Constant>(a->value());
if (s) s->perform(this);
} else {
a->value()->perform(this);
......@@ -919,7 +943,7 @@ namespace Sass {
append_token(s->ns_name(), s);
if (!s->matcher().empty()) {
append_string(s->matcher());
if (&s->value() && *s->value()) {
if (s->value() && *s->value()) {
s->value()->perform(this);
}
}
......@@ -1040,8 +1064,8 @@ namespace Sass {
bool was_comma_array = in_comma_array;
// probably ruby sass eqivalent of element_needs_parens
if (output_style() == TO_SASS && g->length() == 1 &&
(!SASS_MEMORY_CAST(List, (*g)[0]) &&
!SASS_MEMORY_CAST(Selector_List, (*g)[0]))) {
(!Cast<List>((*g)[0]) &&
!Cast<Selector_List>((*g)[0]))) {
append_string("(");
}
else if (!in_declaration && in_comma_array) {
......@@ -1053,7 +1077,7 @@ namespace Sass {
for (size_t i = 0, L = g->length(); i < L; ++i) {
if (!in_wrapped && i == 0) append_indentation();
if ((*g)[i] == 0) continue;
schedule_mapping(&g->at(i)->last());
schedule_mapping(g->at(i)->last());
// add_open_mapping((*g)[i]->last());
(*g)[i]->perform(this);
// add_close_mapping((*g)[i]->last());
......@@ -1066,8 +1090,8 @@ namespace Sass {
in_comma_array = was_comma_array;
// probably ruby sass eqivalent of element_needs_parens
if (output_style() == TO_SASS && g->length() == 1 &&
(!SASS_MEMORY_CAST(List, (*g)[0]) &&
!SASS_MEMORY_CAST(Selector_List, (*g)[0]))) {
(!Cast<List>((*g)[0]) &&
!Cast<Selector_List>((*g)[0]))) {
append_string(",)");
}
else if (!in_declaration && in_comma_array) {
......
......@@ -92,6 +92,9 @@ namespace Sass {
virtual void operator()(Complex_Selector_Ptr);
virtual void operator()(Selector_List_Ptr);
virtual std::string lbracket(List_Ptr);
virtual std::string rbracket(List_Ptr);
// template <typename U>
// void fallback(U x) { fallback_impl(reinterpret_cast<AST_Node_Ptr>(x)); }
};
......
#include "sass.hpp"
#include <cctype>
#include <cstddef>
#include <iostream>
#include <iomanip>
#include "lexer.hpp"
......
......@@ -70,7 +70,7 @@ namespace Sass {
if (tail)
{
Expression_Obj tt = tail->perform(this);
if (List_Ptr ls = SASS_MEMORY_CAST(List, tt))
if (List_Ptr ls = Cast<List>(tt))
{ l->concat(ls); }
}
if (l->length() == 0) return 0;
......@@ -79,7 +79,7 @@ namespace Sass {
Expression_Ptr Listize::fallback_impl(AST_Node_Ptr n)
{
return dynamic_cast<Expression_Ptr>(n);
return Cast<Expression>(n);
}
}
......@@ -11,7 +11,6 @@
namespace Sass {
typedef Environment<AST_Node_Obj> Env;
struct Backtrace;
class Listize : public Operation_CRTP<Expression_Ptr, Listize> {
......
......@@ -18,7 +18,7 @@ namespace Sass {
std::cerr << "# REPORTING MISSING DEALLOCATIONS #\n";
std::cerr << "###################################\n";
for (auto var : all) {
if (AST_Node_Ptr ast = SASS_MEMORY_CAST_PTR(AST_Node, var)) {
if (AST_Node_Ptr ast = Cast<AST_Node>(var)) {
debug_ast(ast);
} else {
std::cerr << "LEAKED " << var << "\n";
......@@ -62,7 +62,7 @@ namespace Sass {
#endif
if (node->refcounter == 0) {
#ifdef DEBUG_SHARED_PTR
AST_Node_Ptr ptr = SASS_MEMORY_CAST_PTR(AST_Node, node);
AST_Node_Ptr ptr = Cast<AST_Node>(node);
if (node->dbg) std::cerr << "DELETE NODE " << node << "\n";
#endif
if (!node->detached) {
......
......@@ -17,7 +17,7 @@ namespace Sass {
#ifdef DEBUG_SHARED_PTR
#define SASS_MEMORY_NEW(Class, ...) \
static_cast<Class##_Ptr>((new Class(__VA_ARGS__))->trace(__FILE__, __LINE__)) \
((new Class(__VA_ARGS__))->trace(__FILE__, __LINE__)) \
#define SASS_MEMORY_COPY(obj) \
((obj)->copy(__FILE__, __LINE__)) \
......@@ -38,12 +38,6 @@ namespace Sass {
#endif
#define SASS_MEMORY_CAST(Class, obj) \
(dynamic_cast<Class##_Ptr>(&obj)) \
#define SASS_MEMORY_CAST_PTR(Class, ptr) \
(dynamic_cast<Class##_Ptr>(ptr)) \
class SharedObj {
protected:
friend class SharedPtr;
......@@ -114,13 +108,10 @@ namespace Sass {
// destructor
~SharedPtr();
public:
SharedObj* obj () {
return node;
};
SharedObj* obj () const {
return node;
};
SharedObj* operator-> () {
SharedObj* operator-> () const {
return node;
};
bool isNull () {
......@@ -129,68 +120,58 @@ namespace Sass {
bool isNull () const {
return node == NULL;
};
SharedObj* detach() {
node->detached = true;
return node;
};
SharedObj* detach() const {
if (node) {
node->detached = true;
}
return node;
};
operator bool() {
return node != NULL;
};
operator bool() const {
return node != NULL;
};
};
template < typename T >
template < class T >
class SharedImpl : private SharedPtr {
public:
SharedImpl()
: SharedPtr(NULL) {};
SharedImpl(T* node)
: SharedPtr(node) {};
template < class U >
SharedImpl(SharedImpl<U> obj)
: SharedPtr(static_cast<T*>(obj.ptr())) {}
SharedImpl(T&& node)
: SharedPtr(node) {};
SharedImpl(const T& node)
: SharedPtr(node) {};
~SharedImpl() {};
public:
T* operator& () {
operator T*() const {
return static_cast<T*>(this->obj());
};
T* operator& () const {
return static_cast<T*>(this->obj());
};
T& operator* () {
}
operator T&() const {
return *static_cast<T*>(this->obj());
};
}
T& operator* () const {
return *static_cast<T*>(this->obj());
};
T* operator-> () {
return static_cast<T*>(this->obj());
};
T* operator-> () const {
return static_cast<T*>(this->obj());
};
T* ptr () {
T* ptr () const {
return static_cast<T*>(this->obj());
};
T* detach() {
T* detach() const {
if (this->obj() == NULL) return NULL;
return static_cast<T*>(SharedPtr::detach());
}
bool isNull() {
bool isNull() const {
return this->obj() == NULL;
}
operator bool() {
return this->obj() != NULL;
bool operator<(const T& rhs) const {
return *this->ptr() < rhs;
};
operator bool() const {
return this->obj() != NULL;
......
......@@ -66,12 +66,12 @@ namespace Sass {
bool Node::contains(const Node& potentialChild, bool simpleSelectorOrderDependent) const {
bool found = false;
bool found = false;
for (NodeDeque::iterator iter = mpCollection->begin(), iterEnd = mpCollection->end(); iter != iterEnd; iter++) {
Node& toTest = *iter;
if (nodesEqual(toTest, potentialChild, simpleSelectorOrderDependent)) {
if (toTest == potentialChild) {
found = true;
break;
}
......@@ -82,37 +82,32 @@ namespace Sass {
bool Node::operator==(const Node& rhs) const {
return nodesEqual(*this, rhs, true /*simpleSelectorOrderDependent*/);
}
bool nodesEqual(const Node& lhs, const Node& rhs, bool simpleSelectorOrderDependent) {
if (lhs.type() != rhs.type()) {
if (this->type() != rhs.type()) {
return false;
}
if (lhs.isCombinator()) {
if (this->isCombinator()) {
return lhs.combinator() == rhs.combinator();
return this->combinator() == rhs.combinator();
} else if (lhs.isNil()) {
} else if (this->isNil()) {
return true; // no state to check
} else if (lhs.isSelector()){
} else if (this->isSelector()){
return selectors_equal(*&lhs.selector(), *&rhs.selector(), simpleSelectorOrderDependent);
return *this->selector() == *rhs.selector();
} else if (lhs.isCollection()) {
} else if (this->isCollection()) {
if (lhs.collection()->size() != rhs.collection()->size()) {
if (this->collection()->size() != rhs.collection()->size()) {
return false;
}
for (NodeDeque::iterator lhsIter = lhs.collection()->begin(), lhsIterEnd = lhs.collection()->end(),
for (NodeDeque::iterator lhsIter = this->collection()->begin(), lhsIterEnd = this->collection()->end(),
rhsIter = rhs.collection()->begin(); lhsIter != lhsIterEnd; lhsIter++, rhsIter++) {
if (!nodesEqual(*lhsIter, *rhsIter, simpleSelectorOrderDependent)) {
if (*lhsIter != *rhsIter) {
return false;
}
......@@ -128,10 +123,10 @@ namespace Sass {
void Node::plus(Node& rhs) {
if (!this->isCollection() || !rhs.isCollection()) {
throw "Both the current node and rhs must be collections.";
if (!this->isCollection() || !rhs.isCollection()) {
throw "Both the current node and rhs must be collections.";
}
this->collection()->insert(this->collection()->end(), rhs.collection()->begin(), rhs.collection()->end());
this->collection()->insert(this->collection()->end(), rhs.collection()->begin(), rhs.collection()->end());
}
#ifdef DEBUG
......@@ -189,7 +184,7 @@ namespace Sass {
if (pToConvert->head() && pToConvert->head()->has_parent_ref()) {
Complex_Selector_Obj tail = pToConvert->tail();
if (tail) tail->has_line_feed(pToConvert->has_line_feed());
pToConvert = &tail;
pToConvert = tail;
}
while (pToConvert) {
......@@ -216,7 +211,7 @@ namespace Sass {
// pToConvert->tail()->has_line_feed(pToConvert->has_line_feed());
}
pToConvert = &pToConvert->tail();
pToConvert = pToConvert->tail();
}
return node;
......@@ -254,7 +249,7 @@ namespace Sass {
// collections, and can result in an infinite loop during the call to parentSuperselector()
pCurrent->tail(SASS_MEMORY_COPY(child.selector()));
// if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed);
pCurrent = &pCurrent->tail();
pCurrent = pCurrent->tail();
} else if (child.isCombinator()) {
pCurrent->combinator(child.combinator());
if (child.got_line_feed) pCurrent->has_line_feed(child.got_line_feed);
......@@ -265,7 +260,7 @@ namespace Sass {
if (nextNode.isCombinator()) {
pCurrent->tail(SASS_MEMORY_NEW(Complex_Selector, ParserState("[NODE]"), Complex_Selector::ANCESTOR_OF, NULL, NULL));
if (nextNode.got_line_feed) pCurrent->tail()->has_line_feed(nextNode.got_line_feed);
pCurrent = &pCurrent->tail();
pCurrent = pCurrent->tail();
}
}
} else {
......
......@@ -113,8 +113,6 @@ namespace Sass {
Node complexSelectorToNode(Complex_Selector_Ptr pToConvert, Context& ctx);
Complex_Selector_Ptr nodeToComplexSelector(const Node& toConvert, Context& ctx);
bool nodesEqual(const Node& one, const Node& two, bool simpleSelectorOrderDependent);
}
#endif
......@@ -116,8 +116,8 @@ namespace Sass {
if (!Util::isPrintable(r, output_style())) {
for (size_t i = 0, L = b->length(); i < L; ++i) {
const Statement_Obj& stm = b->at(i);
if (dynamic_cast<Has_Block_Ptr>(&stm)) {
if (!dynamic_cast<Declaration_Ptr>(&stm)) {
if (Cast<Has_Block>(stm)) {
if (!Cast<Declaration>(stm)) {
stm->perform(this);
}
}
......@@ -135,27 +135,27 @@ namespace Sass {
append_optional_linefeed();
}
if (s) s->perform(this);
append_scope_opener(&b);
append_scope_opener(b);
for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i);
bool bPrintExpression = true;
// Check print conditions
if (Declaration_Ptr dec = SASS_MEMORY_CAST(Declaration, stm)) {
if (String_Constant_Ptr valConst = SASS_MEMORY_CAST(String_Constant, dec->value())) {
if (Declaration_Ptr dec = Cast<Declaration>(stm)) {
if (String_Constant_Ptr valConst = Cast<String_Constant>(dec->value())) {
std::string val(valConst->value());
if (String_Quoted_Ptr qstr = SASS_MEMORY_CAST_PTR(String_Quoted, valConst)) {
if (String_Quoted_Ptr qstr = Cast<String_Quoted>(valConst)) {
if (!qstr->quote_mark() && val.empty()) {
bPrintExpression = false;
}
}
}
else if (List_Ptr list = SASS_MEMORY_CAST(List, dec->value())) {
else if (List_Ptr list = Cast<List>(dec->value())) {
bool all_invisible = true;
for (size_t list_i = 0, list_L = list->length(); list_i < list_L; ++list_i) {
Expression_Ptr item = &list->at(list_i);
Expression_Ptr item = list->at(list_i);
if (!item->is_invisible()) all_invisible = false;
}
if (all_invisible) bPrintExpression = false;
if (all_invisible && !list->is_bracketed()) bPrintExpression = false;
}
}
// Print if OK
......@@ -164,7 +164,7 @@ namespace Sass {
}
}
if (output_style() == NESTED) indentation -= r->tabs();
append_scope_closer(&b);
append_scope_closer(b);
}
void Output::operator()(Keyframe_Rule_Ptr r)
......@@ -172,7 +172,7 @@ namespace Sass {
Block_Obj b = r->block();
Selector_Obj v = r->name();
if (&v) {
if (!v.isNull()) {
v->perform(this);
}
......@@ -201,7 +201,7 @@ namespace Sass {
if (!Util::isPrintable(f, output_style())) {
for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i);
if (dynamic_cast<Has_Block_Ptr>(&stm)) {
if (Cast<Has_Block>(stm)) {
stm->perform(this);
}
}
......@@ -237,7 +237,7 @@ namespace Sass {
if (!Util::isPrintable(m, output_style())) {
for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i);
if (dynamic_cast<Has_Block_Ptr>(&stm)) {
if (Cast<Has_Block>(stm)) {
stm->perform(this);
}
}
......@@ -282,7 +282,7 @@ namespace Sass {
if (v) {
append_mandatory_space();
// ruby sass bug? should use options?
append_token(v->to_string(/* opt */), &v);
append_token(v->to_string(/* opt */), v);
}
if (!b) {
append_delimiter();
......
......@@ -39,12 +39,11 @@ namespace Sass {
Token lexed;
bool in_at_root;
Parser(Context& ctx, const ParserState& pstate)
: ParserState(pstate), ctx(ctx), block_stack(), stack(0), last_media_block(),
source(0), position(0), end(0), before_token(pstate), after_token(pstate), pstate(pstate), indentation(0)
{ in_at_root = false; stack.push_back(Scope::Root); }
{ stack.push_back(Scope::Root); }
// static Parser from_string(const std::string& src, Context& ctx, ParserState pstate = ParserState("[STRING]"));
static Parser from_c_str(const char* src, Context& ctx, ParserState pstate = ParserState("[CSTRING]"), const char* source = 0);
......@@ -240,10 +239,10 @@ namespace Sass {
Arguments_Obj parse_arguments();
Argument_Obj parse_argument();
Assignment_Obj parse_assignment();
Ruleset_Obj parse_ruleset(Lookahead lookahead, bool is_root = false);
Selector_Schema_Obj parse_selector_schema(const char* end_of_selector);
Selector_List_Obj parse_selector_list(bool at_root = false);
Complex_Selector_Obj parse_complex_selector(bool in_root = true);
Ruleset_Obj parse_ruleset(Lookahead lookahead);
Selector_List_Obj parse_selector_list(bool chroot);
Complex_Selector_Obj parse_complex_selector(bool chroot);
Selector_Schema_Obj parse_selector_schema(const char* end_of_selector, bool chroot);
Compound_Selector_Obj parse_compound_selector();
Simple_Selector_Obj parse_simple_selector();
Wrapped_Selector_Obj parse_negated_selector();
......@@ -257,6 +256,7 @@ namespace Sass {
bool parse_number_prefix();
Declaration_Obj parse_declaration();
Expression_Obj parse_map();
Expression_Obj parse_bracket_list();
Expression_Obj parse_list(bool delayed = false);
Expression_Obj parse_comma_list(bool delayed = false);
Expression_Obj parse_space_list();
......@@ -340,15 +340,15 @@ namespace Sass {
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
if (position[0] == '#' && position[1] == '{') {
Expression_Obj itpl = lex_interpolation();
if (&itpl) schema->append(&itpl);
if (!itpl.isNull()) schema->append(itpl);
while (lex < close >(false)) {
// std::cerr << "LEX [[" << std::string(lexed) << "]]\n";
schema->append(SASS_MEMORY_NEW(String_Constant, pstate, lexed));
if (position[0] == '#' && position[1] == '{') {
Expression_Obj itpl = lex_interpolation();
if (&itpl) schema->append(&itpl);
if (!itpl.isNull()) schema->append(itpl);
} else {
return &schema;
return schema;
}
}
} else {
......
#include "sass.hpp"
#include <iostream>
#include "output.hpp"
#include "plugins.hpp"
#ifdef _WIN32
#include <windows.h>
#else
......@@ -7,15 +12,21 @@
#include <dlfcn.h>
#endif
#include "sass.hpp"
#include <iostream>
#include "output.hpp"
#include "plugins.hpp"
namespace Sass {
Plugins::Plugins(void) { }
Plugins::~Plugins(void) { }
Plugins::~Plugins(void)
{
for (auto function : functions) {
sass_delete_function(function);
}
for (auto importer : importers) {
sass_delete_importer(importer);
}
for (auto header : headers) {
sass_delete_importer(header);
}
}
// check if plugin is compatible with this version
// plugins may be linked static against libsass
......@@ -57,20 +68,23 @@ namespace Sass {
// try to get import address for "libsass_load_functions"
if (LOAD_LIB_FN(__plugin_load_fns__, plugin_load_functions, "libsass_load_functions"))
{
Sass_Function_List fns = plugin_load_functions();
Sass_Function_List fns = plugin_load_functions(), _p = fns;
while (fns && *fns) { functions.push_back(*fns); ++ fns; }
sass_free_memory(_p); // only delete the container, items not yet
}
// try to get import address for "libsass_load_importers"
if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_importers, "libsass_load_importers"))
{
Sass_Importer_List imps = plugin_load_importers();
Sass_Importer_List imps = plugin_load_importers(), _p = imps;
while (imps && *imps) { importers.push_back(*imps); ++ imps; }
sass_free_memory(_p); // only delete the container, items not yet
}
// try to get import address for "libsass_load_headers"
if (LOAD_LIB_FN(__plugin_load_imps__, plugin_load_headers, "libsass_load_headers"))
{
Sass_Importer_List imps = plugin_load_headers();
Sass_Importer_List imps = plugin_load_headers(), _p = imps;
while (imps && *imps) { headers.push_back(*imps); ++ imps; }
sass_free_memory(_p); // only delete the container, items not yet
}
// success
return true;
......@@ -153,7 +167,11 @@ namespace Sass {
struct dirent *dirp;
if((dp = opendir(path.c_str())) == NULL) return -1;
while ((dirp = readdir(dp)) != NULL) {
if (!ends_with(dirp->d_name, ".so")) continue;
#if __APPLE__
if (!ends_with(dirp->d_name, ".dylib")) continue;
#else
if (!ends_with(dirp->d_name, ".so")) continue;
#endif
if (load_plugin(path + dirp->d_name)) ++ loaded;
}
closedir(dp);
......
......@@ -85,7 +85,7 @@ namespace Sass {
size_t length() const { return end - begin; }
std::string ws_before() const { return std::string(prefix, begin); }
std::string to_string() const { return std::string(begin, end); }
const std::string to_string() const { return std::string(begin, end); }
std::string time_wspace() const {
std::string str(to_string());
std::string whitespaces(" \t\f\v\n\r");
......
#include "sass.hpp"
#include <cctype>
#include <cstddef>
#include <iostream>
#include <iomanip>
#include "util.hpp"
......@@ -1420,6 +1419,28 @@ namespace Sass {
>(src);
}
const char* list_terminator(const char* src) {
return alternatives <
exactly<';'>,
exactly<'}'>,
exactly<'{'>,
exactly<')'>,
exactly<']'>,
exactly<':'>,
end_of_file,
exactly<ellipsis>,
default_flag,
global_flag
>(src);
};
const char* space_list_terminator(const char* src) {
return alternatives <
exactly<','>,
list_terminator
>(src);
};
// const char* real_uri_prefix(const char* src) {
// return alternatives<
......
......@@ -355,6 +355,10 @@ namespace Sass {
const char* ie_keyword_arg_value(const char* src);
const char* ie_keyword_arg_property(const char* src);
// characters that terminate parsing of a list
const char* list_terminator(const char* src);
const char* space_list_terminator(const char* src);
// match url()
const char* H(const char* src);
const char* W(const char* src);
......
......@@ -6,13 +6,12 @@
namespace Sass {
Remove_Placeholders::Remove_Placeholders(Context& ctx)
: ctx(ctx)
Remove_Placeholders::Remove_Placeholders()
{ }
void Remove_Placeholders::operator()(Block_Ptr b) {
for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Ptr st = &b->at(i);
Statement_Ptr st = b->at(i);
st->perform(this);
}
}
......@@ -34,18 +33,18 @@ namespace Sass {
void Remove_Placeholders::operator()(Ruleset_Ptr r) {
// Create a new selector group without placeholders
Selector_List_Obj sl = SASS_MEMORY_CAST(Selector_List, r->selector());
Selector_List_Obj sl = Cast<Selector_List>(r->selector());
if (sl) {
// Set the new placeholder selector list
r->selector(remove_placeholders(&sl));
r->selector(remove_placeholders(sl));
// Remove placeholders in wrapped selectors
for (Complex_Selector_Obj cs : sl->elements()) {
while (cs) {
if (cs->head()) {
for (Simple_Selector_Obj& ss : cs->head()->elements()) {
if (Wrapped_Selector_Ptr ws = SASS_MEMORY_CAST(Wrapped_Selector, ss)) {
if (Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, ws->selector())) {
if (Wrapped_Selector_Ptr ws = Cast<Wrapped_Selector>(ss)) {
if (Selector_List_Ptr sl = Cast<Selector_List>(ws->selector())) {
Selector_List_Ptr clean = remove_placeholders(sl);
// also clean superflous parent selectors
// probably not really the correct place
......@@ -72,10 +71,10 @@ namespace Sass {
}
void Remove_Placeholders::operator()(Media_Block_Ptr m) {
operator()(&m->block());
operator()(m->block());
}
void Remove_Placeholders::operator()(Supports_Block_Ptr m) {
operator()(&m->block());
operator()(m->block());
}
void Remove_Placeholders::operator()(Directive_Ptr a) {
......
......@@ -9,19 +9,15 @@
namespace Sass {
class Context;
class Remove_Placeholders : public Operation_CRTP<void, Remove_Placeholders> {
Context& ctx;
void fallback_impl(AST_Node_Ptr n) {}
public:
Selector_List_Ptr remove_placeholders(Selector_List_Ptr);
public:
Remove_Placeholders(Context&);
Remove_Placeholders();
~Remove_Placeholders() { }
void operator()(Block_Ptr);
......
......@@ -7,6 +7,23 @@
#include "sass.h"
#include "file.hpp"
#include "util.hpp"
#include "sass_context.hpp"
#include "sass_functions.hpp"
namespace Sass {
// helper to convert string list to vector
std::vector<std::string> list2vec(struct string_list* cur)
{
std::vector<std::string> list;
while (cur) {
list.push_back(cur->string);
cur = cur->next;
}
return list;
}
}
extern "C" {
using namespace Sass;
......@@ -49,11 +66,50 @@ extern "C" {
return sass_copy_c_string(unquoted.c_str());
}
char* ADDCALL sass_compiler_find_include (const char* file, struct Sass_Compiler* compiler)
{
// get the last import entry to get current base directory
Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
// create the vector with paths to lookup
std::vector<std::string> paths(1 + incs.size());
paths.push_back(File::dir_name(import->abs_path));
paths.insert( paths.end(), incs.begin(), incs.end() );
// now resolve the file path relative to lookup paths
std::string resolved(File::find_include(file, paths));
return sass_copy_c_string(resolved.c_str());
}
char* ADDCALL sass_compiler_find_file (const char* file, struct Sass_Compiler* compiler)
{
// get the last import entry to get current base directory
Sass_Import_Entry import = sass_compiler_get_last_import(compiler);
const std::vector<std::string>& incs = compiler->cpp_ctx->include_paths;
// create the vector with paths to lookup
std::vector<std::string> paths(1 + incs.size());
paths.push_back(File::dir_name(import->abs_path));
paths.insert( paths.end(), incs.begin(), incs.end() );
// now resolve the file path relative to lookup paths
std::string resolved(File::find_file(file, paths));
return sass_copy_c_string(resolved.c_str());
}
// Make sure to free the returned value!
// Incs array has to be null terminated!
char* ADDCALL sass_resolve_file (const char* file, const char* paths[])
// this has the original resolve logic for sass include
char* ADDCALL sass_find_include (const char* file, struct Sass_Options* opt)
{
std::string resolved(File::find_file(file, paths));
std::vector<std::string> vec(list2vec(opt->include_paths));
std::string resolved(File::find_include(file, vec));
return sass_copy_c_string(resolved.c_str());
}
// Make sure to free the returned value!
// Incs array has to be null terminated!
char* ADDCALL sass_find_file (const char* file, struct Sass_Options* opt)
{
std::vector<std::string> vec(list2vec(opt->include_paths));
std::string resolved(File::find_file(file, vec));
return sass_copy_c_string(resolved.c_str());
}
......
......@@ -272,10 +272,14 @@ extern "C" {
#define IMPLEMENT_SASS_OPTION_ACCESSOR(type, option) \
type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return options->option; } \
void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) { options->option = option; }
#define IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(type, option, def) \
type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return safe_str(options->option, def); } \
#define IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \
type ADDCALL sass_option_get_##option (struct Sass_Options* options) { return safe_str(options->option, def); }
#define IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def) \
void ADDCALL sass_option_set_##option (struct Sass_Options* options, type option) \
{ free(options->option); options->option = option || def ? sass_copy_c_string(option ? option : def) : 0; }
#define IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(type, option, def) \
IMPLEMENT_SASS_OPTION_STRING_GETTER(type, option, def) \
IMPLEMENT_SASS_OPTION_STRING_SETTER(type, option, def)
#define IMPLEMENT_SASS_CONTEXT_GETTER(type, option) \
type ADDCALL sass_context_get_##option (struct Sass_Context* ctx) { return ctx->option; }
......@@ -468,7 +472,7 @@ extern "C" {
if (compiler->c_ctx->error_status)
return compiler->c_ctx->error_status;
// parse the context we have set up (file or data)
compiler->root = &sass_parse_block(compiler);
compiler->root = sass_parse_block(compiler);
// success
return 0;
}
......@@ -674,6 +678,10 @@ extern "C" {
size_t ADDCALL sass_compiler_get_import_stack_size(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.size(); }
Sass_Import_Entry ADDCALL sass_compiler_get_last_import(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->import_stack.back(); }
Sass_Import_Entry ADDCALL sass_compiler_get_import_entry(struct Sass_Compiler* compiler, size_t idx) { return compiler->cpp_ctx->import_stack[idx]; }
// Getters for Sass_Compiler options (query function stack)
size_t ADDCALL sass_compiler_get_callee_stack_size(struct Sass_Compiler* compiler) { return compiler->cpp_ctx->callee_stack.size(); }
Sass_Callee_Entry ADDCALL sass_compiler_get_last_callee(struct Sass_Compiler* compiler) { return &compiler->cpp_ctx->callee_stack.back(); }
Sass_Callee_Entry ADDCALL sass_compiler_get_callee_entry(struct Sass_Compiler* compiler, size_t idx) { return &compiler->cpp_ctx->callee_stack[idx]; }
// Calculate the size of the stored null terminated array
size_t ADDCALL sass_context_get_included_files_size (struct Sass_Context* ctx)
......@@ -693,10 +701,10 @@ extern "C" {
IMPLEMENT_SASS_OPTION_ACCESSOR(Sass_Importer_List, c_headers);
IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, indent);
IMPLEMENT_SASS_OPTION_ACCESSOR(const char*, linefeed);
IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, plugin_path, 0);
IMPLEMENT_SASS_OPTION_STRING_SETTER(const char*, include_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, input_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, output_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, plugin_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, include_path, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file, 0);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_root, 0);
......@@ -740,6 +748,23 @@ extern "C" {
}
// Push function for include paths (no manipulation support for now)
size_t ADDCALL sass_option_get_include_path_size(struct Sass_Options* options)
{
size_t len = 0;
struct string_list* cur = options->include_paths;
while (cur) { len ++; cur = cur->next; }
return len;
}
// Push function for include paths (no manipulation support for now)
const char* ADDCALL sass_option_get_include_path(struct Sass_Options* options, size_t i)
{
struct string_list* cur = options->include_paths;
while (i) { i--; cur = cur->next; }
return cur->string;
}
// Push function for plugin paths (no manipulation support for now)
void ADDCALL sass_option_push_plugin_path(struct Sass_Options* options, const char* path)
{
......
#ifndef SASS_SASS_CONTEXT_H
#define SASS_SASS_CONTEXT_H
#include "sass.h"
#include "sass.hpp"
#include "context.hpp"
#include "sass/base.h"
#include "sass/context.h"
#include "ast_fwd_decl.hpp"
// sass config options structure
......@@ -33,7 +32,7 @@ struct Sass_Options : Sass_Output_Options {
char* input_path;
// The output path is used for source map
// generation. Libsass will not write to
// generation. LibSass will not write to
// this file, it is just used to create
// information in source-maps etc.
char* output_path;
......
......@@ -2,6 +2,7 @@
#include <cstring>
#include "util.hpp"
#include "context.hpp"
#include "values.hpp"
#include "sass/functions.h"
#include "sass_functions.hpp"
......@@ -17,12 +18,30 @@ extern "C" {
{
Sass_Function_Entry cb = (Sass_Function_Entry) calloc(1, sizeof(Sass_Function));
if (cb == 0) return 0;
cb->signature = signature;
cb->signature = strdup(signature);
cb->function = function;
cb->cookie = cookie;
return cb;
}
void ADDCALL sass_delete_function(Sass_Function_Entry entry)
{
free(entry->signature);
free(entry);
}
// Deallocator for the allocated memory
void ADDCALL sass_delete_function_list(Sass_Function_List list)
{
Sass_Function_List it = list;
if (list == 0) return;
while(*list) {
sass_delete_function(*list);
++list;
}
free(it);
}
// Setters and getters for callbacks on function lists
Sass_Function_Entry ADDCALL sass_function_get_list_entry(Sass_Function_List list, size_t pos) { return list[pos]; }
void sass_function_set_list_entry(Sass_Function_List list, size_t pos, Sass_Function_Entry cb) { list[pos] = cb; }
......@@ -57,6 +76,18 @@ extern "C" {
return (Sass_Importer_List) calloc(length + 1, sizeof(Sass_Importer_Entry));
}
// Deallocator for the allocated memory
void ADDCALL sass_delete_importer_list(Sass_Importer_List list)
{
Sass_Importer_List it = list;
if (list == 0) return;
while(*list) {
sass_delete_importer(*list);
++list;
}
free(it);
}
Sass_Importer_Entry ADDCALL sass_importer_get_list_entry(Sass_Importer_List list, size_t idx) { return list[idx]; }
void ADDCALL sass_importer_set_list_entry(Sass_Importer_List list, size_t idx, Sass_Importer_Entry cb) { list[idx] = cb; }
......@@ -126,6 +157,37 @@ extern "C" {
free(import);
}
// Getter for callee entry
const char* ADDCALL sass_callee_get_name(Sass_Callee_Entry entry) { return entry->name; }
const char* ADDCALL sass_callee_get_path(Sass_Callee_Entry entry) { return entry->path; }
size_t ADDCALL sass_callee_get_line(Sass_Callee_Entry entry) { return entry->line; }
size_t ADDCALL sass_callee_get_column(Sass_Callee_Entry entry) { return entry->column; }
enum Sass_Callee_Type ADDCALL sass_callee_get_type(Sass_Callee_Entry entry) { return entry->type; }
Sass_Env_Frame ADDCALL sass_callee_get_env (Sass_Callee_Entry entry) { return &entry->env; }
// Getters and Setters for environments (lexical, local and global)
union Sass_Value* ADDCALL sass_env_get_lexical (Sass_Env_Frame env, const char* name) {
Expression_Ptr ex = Cast<Expression>((*env->frame)[name]);
return ex != NULL ? ast_node_to_sass_value(ex) : NULL;
}
void ADDCALL sass_env_set_lexical (Sass_Env_Frame env, const char* name, union Sass_Value* val) {
(*env->frame)[name] = sass_value_to_ast_node(val);
}
union Sass_Value* ADDCALL sass_env_get_local (Sass_Env_Frame env, const char* name) {
Expression_Ptr ex = Cast<Expression>(env->frame->get_local(name));
return ex != NULL ? ast_node_to_sass_value(ex) : NULL;
}
void ADDCALL sass_env_set_local (Sass_Env_Frame env, const char* name, union Sass_Value* val) {
env->frame->set_local(name, sass_value_to_ast_node(val));
}
union Sass_Value* ADDCALL sass_env_get_global (Sass_Env_Frame env, const char* name) {
Expression_Ptr ex = Cast<Expression>(env->frame->get_global(name));
return ex != NULL ? ast_node_to_sass_value(ex) : NULL;
}
void ADDCALL sass_env_set_global (Sass_Env_Frame env, const char* name, union Sass_Value* val) {
env->frame->set_global(name, sass_value_to_ast_node(val));
}
// Getter for import entry
const char* ADDCALL sass_import_get_imp_path(Sass_Import_Entry entry) { return entry->imp_path; }
const char* ADDCALL sass_import_get_abs_path(Sass_Import_Entry entry) { return entry->abs_path; }
......
......@@ -2,10 +2,12 @@
#define SASS_SASS_FUNCTIONS_H
#include "sass.h"
#include "environment.hpp"
#include "functions.hpp"
// Struct to hold custom function callback
struct Sass_Function {
const char* signature;
char* signature;
Sass_Function_Fn function;
void* cookie;
};
......@@ -22,6 +24,22 @@ struct Sass_Import {
size_t column;
};
// External environments
struct Sass_Env {
// links to parent frames
Sass::Env* frame;
};
// External call entry
struct Sass_Callee {
const char* name;
const char* path;
size_t line;
size_t column;
enum Sass_Callee_Type type;
struct Sass_Env env;
};
// Struct to hold importer callback
struct Sass_Importer {
Sass_Importer_Fn importer;
......
......@@ -40,7 +40,7 @@ namespace Sass {
bool operator()(const Node& one, const Node& two, Node& out) const {
// TODO: Is this the correct C++ interpretation?
// block ||= proc {|a, b| a == b && a}
if (nodesEqual(one, two, true)) {
if (one == two) {
out = one;
return true;
}
......
......@@ -54,6 +54,8 @@ extern "C" {
size_t ADDCALL sass_list_get_length(const union Sass_Value* v) { return v->list.length; }
enum Sass_Separator ADDCALL sass_list_get_separator(const union Sass_Value* v) { return v->list.separator; }
void ADDCALL sass_list_set_separator(union Sass_Value* v, enum Sass_Separator separator) { v->list.separator = separator; }
bool ADDCALL sass_list_get_is_bracketed(const union Sass_Value* v) { return v->list.is_bracketed; }
void ADDCALL sass_list_set_is_bracketed(union Sass_Value* v, bool is_bracketed) { v->list.is_bracketed = is_bracketed; }
// Getters and setters for Sass_List values
union Sass_Value* ADDCALL sass_list_get_value(const union Sass_Value* v, size_t i) { return v->list.values[i]; }
void ADDCALL sass_list_set_value(union Sass_Value* v, size_t i, union Sass_Value* value) { v->list.values[i] = value; }
......@@ -130,13 +132,14 @@ extern "C" {
return v;
}
union Sass_Value* ADDCALL sass_make_list(size_t len, enum Sass_Separator sep)
union Sass_Value* ADDCALL sass_make_list(size_t len, enum Sass_Separator sep, bool is_bracketed)
{
union Sass_Value* v = (Sass_Value*) calloc(1, sizeof(Sass_Value));
if (v == 0) return 0;
v->list.tag = SASS_LIST;
v->list.length = len;
v->list.separator = sep;
v->list.is_bracketed = is_bracketed;
v->list.values = (union Sass_Value**) calloc(len, sizeof(union Sass_Value*));
if (v->list.values == 0) { free(v); return 0; }
return v;
......@@ -247,7 +250,7 @@ extern "C" {
return sass_string_is_quoted(val) ? sass_make_qstring(val->string.value) : sass_make_string(val->string.value);
} break;
case SASS_LIST: {
union Sass_Value* list = sass_make_list(val->list.length, val->list.separator);
union Sass_Value* list = sass_make_list(val->list.length, val->list.separator, val->list.is_bracketed);
for (i = 0; i < list->list.length; i++) {
list->list.values[i] = sass_clone_value(val->list.values[i]);
}
......@@ -294,40 +297,40 @@ extern "C" {
// see if it's a relational expression
switch(op) {
case Sass_OP::EQ: return sass_make_boolean(Eval::eq(&lhs, &rhs));
case Sass_OP::NEQ: return sass_make_boolean(!Eval::eq(&lhs, &rhs));
case Sass_OP::GT: return sass_make_boolean(!Eval::lt(&lhs, &rhs, "gt") && !Eval::eq(&lhs, &rhs));
case Sass_OP::GTE: return sass_make_boolean(!Eval::lt(&lhs, &rhs, "gte"));
case Sass_OP::LT: return sass_make_boolean(Eval::lt(&lhs, &rhs, "lt"));
case Sass_OP::LTE: return sass_make_boolean(Eval::lt(&lhs, &rhs, "lte") || Eval::eq(&lhs, &rhs));
case Sass_OP::AND: return ast_node_to_sass_value(lhs->is_false() ? &lhs : &rhs);
case Sass_OP::OR: return ast_node_to_sass_value(lhs->is_false() ? &rhs : &lhs);
case Sass_OP::EQ: return sass_make_boolean(Eval::eq(lhs, rhs));
case Sass_OP::NEQ: return sass_make_boolean(!Eval::eq(lhs, rhs));
case Sass_OP::GT: return sass_make_boolean(!Eval::lt(lhs, rhs, "gt") && !Eval::eq(lhs, rhs));
case Sass_OP::GTE: return sass_make_boolean(!Eval::lt(lhs, rhs, "gte"));
case Sass_OP::LT: return sass_make_boolean(Eval::lt(lhs, rhs, "lt"));
case Sass_OP::LTE: return sass_make_boolean(Eval::lt(lhs, rhs, "lte") || Eval::eq(lhs, rhs));
case Sass_OP::AND: return ast_node_to_sass_value(lhs->is_false() ? lhs : rhs);
case Sass_OP::OR: return ast_node_to_sass_value(lhs->is_false() ? rhs : lhs);
default: break;
}
if (sass_value_is_number(a) && sass_value_is_number(b)) {
Number_Ptr_Const l_n = SASS_MEMORY_CAST(Number, lhs);
Number_Ptr_Const r_n = SASS_MEMORY_CAST(Number, rhs);
Number_Ptr_Const l_n = Cast<Number>(lhs);
Number_Ptr_Const r_n = Cast<Number>(rhs);
rv = Eval::op_numbers(op, *l_n, *r_n, options);
}
else if (sass_value_is_number(a) && sass_value_is_color(a)) {
Number_Ptr_Const l_n = SASS_MEMORY_CAST(Number, lhs);
Color_Ptr_Const r_c = SASS_MEMORY_CAST(Color, rhs);
Number_Ptr_Const l_n = Cast<Number>(lhs);
Color_Ptr_Const r_c = Cast<Color>(rhs);
rv = Eval::op_number_color(op, *l_n, *r_c, options);
}
else if (sass_value_is_color(a) && sass_value_is_number(b)) {
Color_Ptr_Const l_c = SASS_MEMORY_CAST(Color, lhs);
Number_Ptr_Const r_n = SASS_MEMORY_CAST(Number, rhs);
Color_Ptr_Const l_c = Cast<Color>(lhs);
Number_Ptr_Const r_n = Cast<Number>(rhs);
rv = Eval::op_color_number(op, *l_c, *r_n, options);
}
else if (sass_value_is_color(a) && sass_value_is_color(b)) {
Color_Ptr_Const l_c = SASS_MEMORY_CAST(Color, lhs);
Color_Ptr_Const r_c = SASS_MEMORY_CAST(Color, rhs);
Color_Ptr_Const l_c = Cast<Color>(lhs);
Color_Ptr_Const r_c = Cast<Color>(rhs);
rv = Eval::op_colors(op, *l_c, *r_c, options);
}
else /* convert other stuff to string and apply operation */ {
Value_Ptr l_v = SASS_MEMORY_CAST(Value, lhs);
Value_Ptr r_v = SASS_MEMORY_CAST(Value, rhs);
Value_Ptr l_v = Cast<Value>(lhs);
Value_Ptr r_v = Cast<Value>(rhs);
rv = Eval::op_strings(op, *l_v, *r_v, options);
}
......
......@@ -35,6 +35,7 @@ struct Sass_String {
struct Sass_List {
enum Sass_Tag tag;
enum Sass_Separator separator;
bool is_bracketed;
size_t length;
// null terminated "array"
union Sass_Value** values;
......@@ -78,4 +79,4 @@ struct Sass_MapPair {
union Sass_Value* value;
};
#endif
\ No newline at end of file
#endif
......@@ -2,7 +2,6 @@
#include <string>
#include <sstream>
#include <iostream>
#include <cstddef>
#include <iomanip>
#include "ast.hpp"
......
......@@ -4,22 +4,20 @@
namespace Sass {
void Subset_Map::put(const Compound_Selector_Obj& sel, const Subset_Map_Val& value)
void Subset_Map::put(const Compound_Selector_Obj& sel, const SubSetMapPair& value)
{
if (sel->empty()) throw std::runtime_error("internal error: subset map keys may not be empty");
size_t index = values_.size();
values_.push_back(value);
for (size_t i = 0, S = sel->length(); i < S; ++i)
{
hash_[(*sel)[i]].push_back(std::make_pair(&sel, index));
hash_[(*sel)[i]].push_back(std::make_pair(sel, index));
}
}
std::vector<Subset_Map_Val> Subset_Map::get_kv(const Compound_Selector_Obj& sel)
std::vector<SubSetMapPair> Subset_Map::get_kv(const Compound_Selector_Obj& sel)
{
// std::vector<Subset_Map_Key> s = sel->to_str_vec();
// std::set<std::string> dict(s.begin(), s.end());
std::unordered_set<Simple_Selector_Obj, HashSimpleSelector, CompareSimpleSelector> dict(sel->begin(), sel->end());
SimpleSelectorDict dict(sel->begin(), sel->end()); // XXX Set
std::vector<size_t> indices;
for (size_t i = 0, S = sel->length(); i < S; ++i) {
if (!hash_.count((*sel)[i])) {
......@@ -42,14 +40,14 @@ namespace Sass {
std::vector<size_t>::iterator indices_end = unique(indices.begin(), indices.end());
indices.resize(distance(indices.begin(), indices_end));
std::vector<Subset_Map_Val> results;
std::vector<SubSetMapPair> results;
for (size_t i = 0, S = indices.size(); i < S; ++i) {
results.push_back(values_[indices[i]]);
}
return results;
}
std::vector<Subset_Map_Val> Subset_Map::get_v(const Compound_Selector_Obj& sel)
std::vector<SubSetMapPair> Subset_Map::get_v(const Compound_Selector_Obj& sel)
{
return get_kv(sel);
}
......
......@@ -60,15 +60,15 @@ namespace Sass {
class Subset_Map {
private:
std::vector<Subset_Map_Val> values_;
std::map<Simple_Selector_Obj, std::vector<std::pair<Compound_Selector_Obj, size_t> > > hash_;
std::vector<SubSetMapPair> values_;
std::map<Simple_Selector_Obj, std::vector<std::pair<Compound_Selector_Obj, size_t> >, OrderNodes > hash_;
public:
void put(const Compound_Selector_Obj& sel, const Subset_Map_Val& value);
std::vector<Subset_Map_Val> get_kv(const Compound_Selector_Obj& s);
std::vector<Subset_Map_Val> get_v(const Compound_Selector_Obj& s);
void put(const Compound_Selector_Obj& sel, const SubSetMapPair& value);
std::vector<SubSetMapPair> get_kv(const Compound_Selector_Obj& s);
std::vector<SubSetMapPair> get_v(const Compound_Selector_Obj& s);
bool empty() { return values_.empty(); }
void clear() { values_.clear(); hash_.clear(); }
const std::vector<Subset_Map_Val> values(void) { return values_; }
const std::vector<SubSetMapPair> values(void) { return values_; }
};
}
......
......@@ -36,7 +36,7 @@ namespace Sass {
union Sass_Value* To_C::operator()(List_Ptr l)
{
union Sass_Value* v = sass_make_list(l->length(), l->separator());
union Sass_Value* v = sass_make_list(l->length(), l->separator(), l->is_bracketed());
for (size_t i = 0, L = l->length(); i < L; ++i) {
sass_list_set_value(v, i, (*l)[i]->perform(this));
}
......@@ -57,7 +57,7 @@ namespace Sass {
union Sass_Value* To_C::operator()(Arguments_Ptr a)
{
union Sass_Value* v = sass_make_list(a->length(), SASS_COMMA);
union Sass_Value* v = sass_make_list(a->length(), SASS_COMMA, false);
for (size_t i = 0, L = a->length(); i < L; ++i) {
sass_list_set_value(v, i, (*a)[i]->perform(this));
}
......
......@@ -445,7 +445,7 @@ namespace Sass {
Block_Obj b = r->block();
Selector_List_Ptr sl = SASS_MEMORY_CAST(Selector_List, r->selector());
Selector_List_Ptr sl = Cast<Selector_List>(r->selector());
bool hasSelectors = sl ? sl->length() > 0 : false;
if (!hasSelectors) {
......@@ -456,16 +456,16 @@ namespace Sass {
bool hasPrintableChildBlocks = false;
for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i);
if (dynamic_cast<Directive_Ptr>(&stm)) {
if (Cast<Directive>(stm)) {
return true;
} else if (Declaration_Ptr d = dynamic_cast<Declaration_Ptr>(&stm)) {
} else if (Declaration_Ptr d = Cast<Declaration>(stm)) {
return isPrintable(d, style);
} else if (dynamic_cast<Has_Block_Ptr>(&stm)) {
Block_Obj pChildBlock = ((Has_Block_Ptr)&stm)->block();
if (isPrintable(&pChildBlock, style)) {
} else if (Has_Block_Ptr p = Cast<Has_Block>(stm)) {
Block_Obj pChildBlock = p->block();
if (isPrintable(pChildBlock, style)) {
hasPrintableChildBlocks = true;
}
} else if (Comment_Ptr c = dynamic_cast<Comment_Ptr>(&stm)) {
} else if (Comment_Ptr c = Cast<Comment>(stm)) {
// keep for uncompressed
if (style != COMPRESSED) {
hasDeclarations = true;
......@@ -499,8 +499,8 @@ namespace Sass {
bool isPrintable(Declaration_Ptr d, Sass_Output_Style style)
{
Expression_Obj val = d->value();
if (String_Quoted_Obj sq = SASS_MEMORY_CAST(String_Quoted, val)) return isPrintable(&sq, style);
if (String_Constant_Obj sc = SASS_MEMORY_CAST(String_Constant, val)) return isPrintable(&sc, style);
if (String_Quoted_Obj sq = Cast<String_Quoted>(val)) return isPrintable(sq.ptr(), style);
if (String_Constant_Obj sc = Cast<String_Constant>(val)) return isPrintable(sc.ptr(), style);
return true;
}
......@@ -511,18 +511,16 @@ namespace Sass {
Block_Obj b = f->block();
// bool hasSelectors = f->selector() && static_cast<Selector_List_Ptr>(f->selector())->length() > 0;
bool hasDeclarations = false;
bool hasPrintableChildBlocks = false;
for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i);
if (dynamic_cast<Declaration_Ptr>(&stm) || dynamic_cast<Directive_Ptr>(&stm)) {
if (Cast<Declaration>(stm) || Cast<Directive>(stm)) {
hasDeclarations = true;
}
else if (dynamic_cast<Has_Block_Ptr>(&stm)) {
Block_Obj pChildBlock = ((Has_Block_Ptr)&stm)->block();
if (isPrintable(&pChildBlock, style)) {
else if (Has_Block_Ptr b = Cast<Has_Block>(stm)) {
Block_Obj pChildBlock = b->block();
if (isPrintable(pChildBlock, style)) {
hasPrintableChildBlocks = true;
}
}
......@@ -542,34 +540,32 @@ namespace Sass {
if (b == 0) return false;
for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i);
if (dynamic_cast<Directive_Ptr>(&stm)) return true;
else if (dynamic_cast<Declaration_Ptr>(&stm)) return true;
else if (dynamic_cast<Comment_Ptr>(&stm)) {
Comment_Ptr c = (Comment_Ptr) &stm;
if (Cast<Directive>(stm)) return true;
else if (Cast<Declaration>(stm)) return true;
else if (Comment_Ptr c = Cast<Comment>(stm)) {
if (isPrintable(c, style)) {
return true;
}
}
else if (dynamic_cast<Ruleset_Ptr>(&stm)) {
Ruleset_Ptr r = (Ruleset_Ptr) &stm;
else if (Ruleset_Ptr r = Cast<Ruleset>(stm)) {
if (isPrintable(r, style)) {
return true;
}
}
else if (dynamic_cast<Supports_Block_Ptr>(&stm)) {
Supports_Block_Ptr f = (Supports_Block_Ptr) &stm;
else if (Supports_Block_Ptr f = Cast<Supports_Block>(stm)) {
if (isPrintable(f, style)) {
return true;
}
}
else if (dynamic_cast<Media_Block_Ptr>(&stm)) {
Media_Block_Ptr m = (Media_Block_Ptr) &stm;
else if (Media_Block_Ptr m = Cast<Media_Block>(stm)) {
if (isPrintable(m, style)) {
return true;
}
}
else if (dynamic_cast<Has_Block_Ptr>(&stm) && isPrintable(((Has_Block_Ptr)&stm)->block(), style)) {
return true;
else if (Has_Block_Ptr b = Cast<Has_Block>(stm)) {
if (isPrintable(b->block(), style)) {
return true;
}
}
}
return false;
......@@ -596,35 +592,33 @@ namespace Sass {
for (size_t i = 0, L = b->length(); i < L; ++i) {
Statement_Obj stm = b->at(i);
if (dynamic_cast<Declaration_Ptr>(&stm) || dynamic_cast<Directive_Ptr>(&stm)) {
if (Cast<Declaration>(stm) || Cast<Directive>(stm)) {
return true;
}
else if (dynamic_cast<Comment_Ptr>(&stm)) {
Comment_Ptr c = (Comment_Ptr) &stm;
else if (Comment_Ptr c = Cast<Comment>(stm)) {
if (isPrintable(c, style)) {
return true;
}
}
else if (dynamic_cast<Ruleset_Ptr>(&stm)) {
Ruleset_Ptr r = (Ruleset_Ptr) &stm;
else if (Ruleset_Ptr r = Cast<Ruleset>(stm)) {
if (isPrintable(r, style)) {
return true;
}
}
else if (dynamic_cast<Supports_Block_Ptr>(&stm)) {
Supports_Block_Ptr f = (Supports_Block_Ptr) &stm;
else if (Supports_Block_Ptr f = Cast<Supports_Block>(stm)) {
if (isPrintable(f, style)) {
return true;
}
}
else if (dynamic_cast<Media_Block_Ptr>(&stm)) {
Media_Block_Ptr m = (Media_Block_Ptr) &stm;
else if (Media_Block_Ptr m = Cast<Media_Block>(stm)) {
if (isPrintable(m, style)) {
return true;
}
}
else if (dynamic_cast<Has_Block_Ptr>(&stm) && isPrintable(((Has_Block_Ptr)&stm)->block(), style)) {
return true;
else if (Has_Block_Ptr b = Cast<Has_Block>(stm)) {
if (isPrintable(b->block(), style)) {
return true;
}
}
}
......
......@@ -11,32 +11,32 @@ namespace Sass {
{
if (val->concrete_type() == Expression::NUMBER)
{
Number_Ptr_Const res = dynamic_cast<Number_Ptr_Const>(val);
Number_Ptr_Const res = Cast<Number>(val);
return sass_make_number(res->value(), res->unit().c_str());
}
else if (val->concrete_type() == Expression::COLOR)
{
Color_Ptr_Const col = dynamic_cast<Color_Ptr_Const>(val);
Color_Ptr_Const col = Cast<Color>(val);
return sass_make_color(col->r(), col->g(), col->b(), col->a());
}
else if (val->concrete_type() == Expression::LIST)
{
List_Ptr_Const l = dynamic_cast<List_Ptr_Const>(val);
union Sass_Value* list = sass_make_list(l->size(), l->separator());
List_Ptr_Const l = Cast<List>(val);
union Sass_Value* list = sass_make_list(l->size(), l->separator(), l->is_bracketed());
for (size_t i = 0, L = l->length(); i < L; ++i) {
Expression_Obj obj = l->at(i);
auto val = ast_node_to_sass_value(&obj);
auto val = ast_node_to_sass_value(obj);
sass_list_set_value(list, i, val);
}
return list;
}
else if (val->concrete_type() == Expression::MAP)
{
Map_Ptr_Const m = dynamic_cast<Map_Ptr_Const>(val);
Map_Ptr_Const m = Cast<Map>(val);
union Sass_Value* map = sass_make_map(m->length());
size_t i = 0; for (Expression_Obj key : m->keys()) {
sass_map_set_key(map, i, ast_node_to_sass_value(&key));
sass_map_set_value(map, i, ast_node_to_sass_value(&m->at(key)));
sass_map_set_key(map, i, ast_node_to_sass_value(key));
sass_map_set_value(map, i, ast_node_to_sass_value(m->at(key)));
++ i;
}
return map;
......@@ -47,16 +47,16 @@ namespace Sass {
}
else if (val->concrete_type() == Expression::BOOLEAN)
{
Boolean_Ptr_Const res = dynamic_cast<Boolean_Ptr_Const>(val);
Boolean_Ptr_Const res = Cast<Boolean>(val);
return sass_make_boolean(res->value());
}
else if (val->concrete_type() == Expression::STRING)
{
if (String_Quoted_Ptr_Const qstr = dynamic_cast<String_Quoted_Ptr_Const>(val))
if (String_Quoted_Ptr_Const qstr = Cast<String_Quoted>(val))
{
return sass_make_qstring(qstr->value().c_str());
}
else if (String_Constant_Ptr_Const cstr = dynamic_cast<String_Constant_Ptr_Const>(val))
else if (String_Constant_Ptr_Const cstr = Cast<String_Constant>(val))
{
return sass_make_string(cstr->value().c_str());
}
......@@ -106,6 +106,7 @@ namespace Sass {
for (size_t i = 0, L = sass_list_get_length(val); i < L; ++i) {
l->append(sass_value_to_ast_node(sass_list_get_value(val, i)));
}
l->is_bracketed(sass_list_get_is_bracketed(val));
return l;
}
break;
......
......@@ -69,6 +69,7 @@
<ItemGroup Label="LibSass Sources">
<ClCompile Include="$(LIBSASS_SRC_DIR)\ast.cpp" />
<ClCompile Include="$(LIBSASS_SRC_DIR)\memory\SharedPtr.cpp" />
<ClCompile Include="$(LIBSASS_SRC_DIR)\ast_fwd_decl.cpp" />
<ClCompile Include="$(LIBSASS_SRC_DIR)\base64vlq.cpp" />
<ClCompile Include="$(LIBSASS_SRC_DIR)\bind.cpp" />
<ClCompile Condition="$(VisualStudioVersion) &lt; 14.0" Include="$(LIBSASS_SRC_DIR)\c99func.c" />
......
......@@ -218,6 +218,9 @@
<ClCompile Include="$(LIBSASS_SRC_DIR)\memory\SharedPtr.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="$(LIBSASS_SRC_DIR)\ast_fwd_decl.cpp">
<Filter>Sources</Filter>
</ClCompile>
<ClCompile Include="$(LIBSASS_SRC_DIR)\base64vlq.cpp">
<Filter>Sources</Filter>
</ClCompile>
......
......@@ -8,6 +8,7 @@ namespace SassTypes
Sass_Value* List::construct(const std::vector<v8::Local<v8::Value>> raw_val, Sass_Value **out) {
size_t length = 0;
bool comma = true;
bool is_bracketed = false;
if (raw_val.size() >= 1) {
if (!raw_val[0]->IsNumber()) {
......@@ -25,7 +26,7 @@ namespace SassTypes
}
}
return *out = sass_make_list(length, comma ? SASS_COMMA : SASS_SPACE);
return *out = sass_make_list(length, comma ? SASS_COMMA : SASS_SPACE, is_bracketed);
}
void List::initPrototype(v8::Local<v8::FunctionTemplate> proto) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment