Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor C API for more robust ABI #635

Merged
merged 13 commits into from
Nov 17, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,11 @@ SOURCES = \
prelexer.cpp \
remove_placeholders.cpp \
sass.cpp \
sass_interface.cpp \
sass_util.cpp \
sass_values.cpp \
sass_context.cpp \
sass_functions.cpp \
sass_interface.cpp \
sass2scss.cpp \
source_map.cpp \
to_c.cpp \
Expand Down
9 changes: 6 additions & 3 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,11 @@ libsass_la_SOURCES = \
prelexer.cpp \
remove_placeholders.cpp \
sass.cpp \
sass_interface.cpp \
sass_util.cpp \
sass_values.cpp \
sass_context.cpp \
sass_functions.cpp \
sass_interface.cpp \
sass2scss.cpp \
source_map.cpp \
to_c.cpp \
Expand All @@ -50,13 +53,13 @@ libsass_la_SOURCES = \
util.cpp

libsass_la_CXXFLAGS = $(AM_CXXFLAGS) -std=c++0x
libsass_la_LDFLAGS = -no-undefined -version-info 0:0:0
libsass_la_LDFLAGS = -no-undefined -version-info 0:9:0

if ENABLE_COVERAGE
libsass_la_LDFLAGS += -lgcov
endif

include_HEADERS = sass2scss.h sass_interface.h sass.h
include_HEADERS = sass2scss.h sass_context.h sass_functions.h sass_values.h sass.h

if ENABLE_TESTS

Expand Down
4 changes: 2 additions & 2 deletions ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@
#include "environment.hpp"
#endif

#ifndef SASS
#include "sass.h"
#endif
#include "sass_values.h"
#include "sass_functions.h"

#include "units.hpp"

Expand Down
2 changes: 1 addition & 1 deletion ast_def_macros.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ virtual Statement* perform(Operation<Statement*>* op) { return (*op)(this); }\
virtual Expression* perform(Operation<Expression*>* op) { return (*op)(this); }\
virtual Selector* perform(Operation<Selector*>* op) { return (*op)(this); }\
virtual string perform(Operation<string>* op) { return (*op)(this); }\
virtual Sass_Value perform(Operation<Sass_Value>* op) { return (*op)(this); }
virtual Sass_Value* perform(Operation<Sass_Value*>* op) { return (*op)(this); }

#define ADD_PROPERTY(type, name)\
protected:\
Expand Down
152 changes: 88 additions & 64 deletions context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,9 @@ namespace Sass {
queue (vector<pair<string, const char*> >()),
style_sheets (map<string, Block*>()),
source_map (resolve_relative_path(initializers.output_path(), initializers.source_map_file(), get_cwd())),
c_functions (vector<Sass_C_Function_Descriptor>()),
c_functions (vector<Sass_C_Function_Callback>()),
image_path (initializers.image_path()),
input_path (make_canonical_path(initializers.input_path())),
output_path (make_canonical_path(initializers.output_path())),
source_comments (initializers.source_comments()),
output_style (initializers.output_style()),
Expand All @@ -62,6 +63,7 @@ namespace Sass {
source_map_contents (initializers.source_map_contents()),
omit_source_map_url (initializers.omit_source_map_url()),
is_indented_syntax_src (initializers.is_indented_syntax_src()),
importer (initializers.importer()),
names_to_colors (map<string, Color*>()),
colors_to_names (map<int, string>()),
precision (initializers.precision()),
Expand All @@ -70,6 +72,12 @@ namespace Sass {
{
cwd = get_cwd();

// enforce some safe defaults
// used to create relative file links
if (input_path == "") input_path = "stdin";
if (output_path == "") output_path = "stdout";

include_paths.push_back(cwd);
collect_include_paths(initializers.include_paths_c_str());
collect_include_paths(initializers.include_paths_array());

Expand Down Expand Up @@ -110,7 +118,6 @@ namespace Sass {

void Context::collect_include_paths(const char* paths_str)
{
include_paths.push_back(cwd);

if (paths_str) {
const char* beg = paths_str;
Expand All @@ -134,23 +141,17 @@ namespace Sass {
}
}

void Context::collect_include_paths(const char* paths_array[])
void Context::collect_include_paths(const char** paths_array)
{
include_paths.push_back(get_cwd());
if (*include_paths.back().rbegin() != '/') include_paths.back() += '/';

// if (paths_array) {
// for (size_t i = 0; paths_array[i]; ++i) {
// string path(paths_array[i]);
// if (!path.empty()) {
// if (*path.rbegin() != '/') path += '/';
// include_paths.push_back(path);
// }
// }
// }
if (paths_array) {
for (size_t i = 0; paths_array[i]; i++) {
collect_include_paths(paths_array[i]);
}
}
}

void Context::add_source(const string& load_path, const string& abs_path, const char* contents)
void Context::add_source(string load_path, string abs_path, const char* contents)
{
sources.push_back(contents);
included_files.push_back(abs_path);
Expand Down Expand Up @@ -209,10 +210,39 @@ namespace Sass {
void register_function(Context&, Signature sig, Native_Function f, size_t arity, Env* env);
void register_overload_stub(Context&, string name, Env* env);
void register_built_in_functions(Context&, Env* env);
void register_c_functions(Context&, Env* env, Sass_C_Function_Descriptor*);
void register_c_function(Context&, Env* env, Sass_C_Function_Descriptor);
void register_c_functions(Context&, Env* env, Sass_C_Function_List);
void register_c_function(Context&, Env* env, Sass_C_Function_Callback);

char* Context::compile_file()
char* Context::compile_block(Block* root)
{
char* result = 0;
if (!root) return 0;
switch (output_style) {
case COMPRESSED: {
Output_Compressed output_compressed(this);
root->perform(&output_compressed);
string output = output_compressed.get_buffer();
if (source_map_file != "" && !omit_source_map_url) {
output += format_source_mapping_url(source_map_file);
}
result = copy_c_str(output.c_str());
} break;

default: {
Output_Nested output_nested(source_comments, this);
root->perform(&output_nested);
string output = output_nested.get_buffer();
if (source_map_file != "" && !omit_source_map_url) {
output += "\n" + format_source_mapping_url(source_map_file);
}
result = copy_c_str(output.c_str());

} break;
}
return result;
}

Block* Context::parse_file()
{
Block* root = 0;
for (size_t i = 0; i < queue.size(); ++i) {
Expand All @@ -225,7 +255,7 @@ namespace Sass {
Backtrace backtrace(0, "", Position(), "");
register_built_in_functions(*this, &tge);
for (size_t i = 0, S = c_functions.size(); i < S; ++i) {
register_c_function(*this, &tge, c_functions[i]);
register_c_function(*this, &tge, c_functions[i]);
}
Eval eval(*this, &tge, &backtrace);
Contextualize contextualize(*this, &eval, &tge, &backtrace);
Expand All @@ -242,31 +272,32 @@ namespace Sass {
Remove_Placeholders remove_placeholders(*this);
root->perform(&remove_placeholders);

char* result = 0;
switch (output_style) {
case COMPRESSED: {
Output_Compressed output_compressed(this);
root->perform(&output_compressed);
string output = output_compressed.get_buffer();
if (source_map_file != "" && !omit_source_map_url) {
output += format_source_mapping_url(source_map_file);
}
result = copy_c_str(output.c_str());
} break;

default: {
Output_Nested output_nested(source_comments, this);
root->perform(&output_nested);
string output = output_nested.get_buffer();
if (source_map_file != "" && !omit_source_map_url) {
output += "\n" + format_source_mapping_url(source_map_file);
}
result = copy_c_str(output.c_str());
return root;
}

} break;
Block* Context::parse_string()
{
if (!source_c_str) return 0;
queue.clear();
if(is_indented_syntax_src) {
char * contents = sass2scss(source_c_str, SASS2SCSS_PRETTIFY_1);
add_source(input_path, input_path, contents);
return parse_file();
}
add_source(input_path, input_path, strdup(source_c_str));
return parse_file();
}

return result;
char* Context::compile_file()
{
// returns NULL if something fails
return compile_block(parse_file());
}

char* Context::compile_string()
{
// returns NULL if something fails
return compile_block(parse_string());
}

string Context::format_source_mapping_url(const string& file)
Expand All @@ -293,27 +324,15 @@ namespace Sass {
return result;
}

// allow to optionally overwrite the input path
// default argument for input_path is string("stdin")
// usefull to influence the source-map generating etc.
char* Context::compile_string(const string& input_path)
{
if (!source_c_str) return 0;
queue.clear();
if(is_indented_syntax_src) {
char * contents = sass2scss(source_c_str, SASS2SCSS_PRETTIFY_1);
add_source(input_path, input_path, contents);
return compile_file();
}
add_source(input_path, input_path, strdup(source_c_str));
return compile_file();
}

std::vector<std::string> Context::get_included_files()
std::vector<std::string> Context::get_included_files(size_t skip)
{
std::sort(included_files.begin(), included_files.end());
included_files.erase( std::unique( included_files.begin(), included_files.end() ), included_files.end());
return included_files;
vector<string> includes = included_files;
std::sort( includes.begin() + skip, includes.end() );
includes.erase( std::unique( includes.begin(), includes.end() ), includes.end() );
// the skip solution seems more robust, as we may have real files named stdin
// includes.erase( std::remove( includes.begin(), includes.end(), "stdin" ), includes.end() );
return includes;
}

string Context::get_cwd()
Expand Down Expand Up @@ -448,16 +467,21 @@ namespace Sass {
register_function(ctx, image_url_sig, image_url, env);
}

void register_c_functions(Context& ctx, Env* env, Sass_C_Function_Descriptor* descrs)
void register_c_functions(Context& ctx, Env* env, Sass_C_Function_List descrs)
{
while (descrs->signature && descrs->function) {
while (descrs && *descrs) {
register_c_function(ctx, env, *descrs);
++descrs;
}
}
void register_c_function(Context& ctx, Env* env, Sass_C_Function_Descriptor descr)
void register_c_function(Context& ctx, Env* env, Sass_C_Function_Callback descr)
{
Definition* def = make_c_function(descr.signature, descr.function, descr.cookie, ctx);
Definition* def = make_c_function(
sass_function_get_signature(descr),
sass_function_get_function(descr),
sass_function_get_cookie(descr),
ctx
);
def->environment(env);
(*env)[def->name() + "[f]"] = def;
}
Expand Down
23 changes: 17 additions & 6 deletions context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#define BUFFERSIZE 255
#include "b64/encode.h"

#include "sass_functions.h"

struct Sass_C_Function_Descriptor;

namespace Sass {
Expand Down Expand Up @@ -58,9 +60,10 @@ namespace Sass {
vector<pair<string, const char*> > queue; // queue of files to be parsed
map<string, Block*> style_sheets; // map of paths to ASTs
SourceMap source_map;
vector<Sass_C_Function_Descriptor> c_functions;
vector<Sass_C_Function_Callback> c_functions;

string image_path; // for the image-url Sass function
string input_path; // for relative paths in src-map
string output_path; // for relative paths to the output
bool source_comments; // for inline debug comments in css output
Output_Style output_style; // output style for the generated css code
Expand All @@ -70,6 +73,9 @@ namespace Sass {
bool omit_source_map_url; // disable source map comment in css output
bool is_indented_syntax_src; // treat source string as sass

// overload import calls
Sass_C_Import_Callback importer;

map<string, Color*> names_to_colors;
map<int, string> colors_to_names;

Expand All @@ -79,6 +85,7 @@ namespace Sass {
KWD_ARG_SET(Data) {
KWD_ARG(Data, const char*, source_c_str);
KWD_ARG(Data, string, entry_point);
KWD_ARG(Data, string, input_path);
KWD_ARG(Data, string, output_path);
KWD_ARG(Data, string, image_path);
KWD_ARG(Data, const char*, include_paths_c_str);
Expand All @@ -93,26 +100,30 @@ namespace Sass {
KWD_ARG(Data, bool, _skip_source_map_update);
KWD_ARG(Data, bool, source_map_embed);
KWD_ARG(Data, bool, source_map_contents);
KWD_ARG(Data, Sass_C_Import_Callback, importer);
};

Context(Data);
~Context();
void collect_include_paths(const char* paths_str);
void collect_include_paths(const char* paths_array[]);
void setup_color_map();
string add_file(string);
Block* parse_file();
string add_file(string, string);
Block* parse_string();
void add_source(string, string, const char*);
// allow to optionally overwrite the input path
// default argument for input_path is string("stdin")
// usefull to influence the source-map generating etc.
char* compile_string(const string& input_path = "stdin");
char* compile_file();
char* compile_string();
char* compile_block(Block* root);
char* generate_source_map();

vector<string> get_included_files();
vector<string> get_included_files(size_t skip = 0);

private:
void add_source(const string &load_path, const string &abs_path, const char* contents);
void collect_include_paths(const char* paths_str);
void collect_include_paths(const char** paths_array);
string format_source_mapping_url(const string& file);
string get_cwd();

Expand Down
Loading