Skip to content

Commit

Permalink
Merge pull request #635 from mgreter/api/c-interface
Browse files Browse the repository at this point in the history
Refactor C API for more robust ABI
  • Loading branch information
mgreter committed Nov 17, 2014

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature.
2 parents e51afa8 + c2ca466 commit c0dbb43
Showing 25 changed files with 1,677 additions and 568 deletions.
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -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 \
9 changes: 6 additions & 3 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -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 \
@@ -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

4 changes: 2 additions & 2 deletions ast.hpp
Original file line number Diff line number Diff line change
@@ -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"

2 changes: 1 addition & 1 deletion ast_def_macros.hpp
Original file line number Diff line number Diff line change
@@ -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:\
152 changes: 88 additions & 64 deletions context.cpp
Original file line number Diff line number Diff line change
@@ -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()),
@@ -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()),
@@ -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());

@@ -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;
@@ -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);
@@ -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) {
@@ -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);
@@ -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)
@@ -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()
@@ -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;
}
23 changes: 17 additions & 6 deletions context.hpp
Original file line number Diff line number Diff line change
@@ -24,6 +24,8 @@
#define BUFFERSIZE 255
#include "b64/encode.h"

#include "sass_functions.h"

struct Sass_C_Function_Descriptor;

namespace Sass {
@@ -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
@@ -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;

@@ -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);
@@ -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();

Loading

0 comments on commit c0dbb43

Please sign in to comment.