Commit e7824065 by Sam Saccone

update libsass

parent 60f66275
#define SASS_BACKTRACE
#include <sstream>
namespace Sass {
using namespace std;
struct Backtrace {
Backtrace* parent;
string path;
size_t line;
string caller;
Backtrace(Backtrace* prn, string pth, size_t ln, string c)
: parent(prn),
path(pth),
line(ln),
caller(c)
{ }
string to_string(bool warning = false)
{
stringstream ss;
Backtrace* this_point = this;
if (!warning) ss << endl << "Backtrace:";
// the first tracepoint (which is parent-less) is an empty placeholder
while (this_point->parent) {
ss << endl
<< "\t"
<< (warning ? " " : "")
<< this_point->path
<< ":"
<< this_point->line
<< this_point->parent->caller;
this_point = this_point->parent;
}
return ss.str();
}
};
}
\ No newline at end of file
......@@ -12,6 +12,7 @@ namespace Sass {
extern const char function_kwd[] = "@function";
extern const char return_kwd[] = "@return";
extern const char include_kwd[] = "@include";
extern const char content_kwd[] = "@content";
extern const char extend_kwd[] = "@extend";
extern const char if_kwd[] = "@if";
extern const char else_kwd[] = "@else";
......@@ -43,6 +44,7 @@ namespace Sass {
extern const char kHz_kwd[] = "kHz";
// css functions and keywords
extern const char charset_kwd[] = "@charset";
extern const char media_kwd[] = "@media";
extern const char only_kwd[] = "only";
extern const char rgb_kwd[] = "rgb(";
......@@ -83,6 +85,7 @@ namespace Sass {
extern const char rbrace[] = "}";
extern const char rparen[] = ")";
extern const char sign_chars[] = "-+";
extern const char hyphen[] = "-";
// type names
extern const char numeric_name[] = "numeric value";
......
......@@ -12,6 +12,7 @@ namespace Sass {
extern const char function_kwd[];
extern const char return_kwd[];
extern const char include_kwd[];
extern const char content_kwd[];
extern const char extend_kwd[];
extern const char if_kwd[];
extern const char else_kwd[];
......@@ -43,6 +44,7 @@ namespace Sass {
extern const char kHz_kwd[];
// css functions and keywords
extern const char charset_kwd[];
extern const char media_kwd[];
extern const char only_kwd[];
extern const char rgb_kwd[];
......@@ -83,6 +85,7 @@ namespace Sass {
extern const char rbrace[];
extern const char rparen[];
extern const char sign_chars[];
extern const char hyphen[];
// type names
extern const char numeric_name[];
......
#ifdef _WIN32
#include <direct.h>
#define getcwd _getcwd
#define PATH_SEP ';'
#else
#include <unistd.h>
#define PATH_SEP ':'
#endif
#include <cstring>
......@@ -27,7 +29,7 @@ namespace Sass {
if (paths_str) {
const char* beg = paths_str;
const char* end = Prelexer::find_first<':'>(beg);
const char* end = Prelexer::find_first<PATH_SEP>(beg);
while (end) {
string path(beg, end - beg);
......@@ -36,7 +38,7 @@ namespace Sass {
include_paths.push_back(path);
}
beg = end + 1;
end = Prelexer::find_first<':'>(beg);
end = Prelexer::find_first<PATH_SEP>(beg);
}
string path(beg);
......@@ -51,19 +53,20 @@ namespace Sass {
// }
}
Context::Context(const char* paths_str, const char* img_path_str)
Context::Context(const char* paths_str, const char* img_path_str, bool sc)
: global_env(Environment()),
function_env(map<string, Function>()),
extensions(multimap<Node, Node>()),
pending_extensions(vector<pair<Node, Node> >()),
source_refs(vector<char*>()),
source_refs(vector<const char*>()),
include_paths(vector<string>()),
color_names_to_values(map<string, Node>()),
color_values_to_names(map<Node, string>()),
new_Node(Node_Factory()),
image_path(0),
ref_count(0),
has_extensions(false)
has_extensions(false),
source_comments(sc)
{
register_functions();
collect_include_paths(paths_str);
......@@ -144,6 +147,7 @@ namespace Sass {
register_function(adjust_color_sig, adjust_color);
register_function(scale_color_sig, scale_color);
register_function(change_color_sig, change_color);
register_function(ie_hex_str_sig, ie_hex_str);
// String Functions
register_function(unquote_sig, unquote);
register_function(quote_sig, quote);
......
......@@ -23,7 +23,7 @@ namespace Sass {
map<string, Function> function_env;
multimap<Node, Node> extensions;
vector<pair<Node, Node> > pending_extensions;
vector<char*> source_refs; // all the source c-strings
vector<const char*> source_refs; // all the source c-strings
vector<string> include_paths;
map<string, Node> color_names_to_values;
map<Node, string> color_values_to_names;
......@@ -33,9 +33,10 @@ namespace Sass {
// string sass_path;
// string css_path;
bool has_extensions;
bool source_comments;
void collect_include_paths(const char* paths_str);
Context(const char* paths_str = 0, const char* img_path_str = 0);
Context(const char* paths_str = 0, const char* img_path_str = 0, bool sc = false);
~Context();
void register_function(Signature sig, Primitive ip);
......
......@@ -37,24 +37,40 @@ namespace Sass {
const char* path_str = path.c_str();
struct stat st;
string tmp;
// Resolution order for ambiguous imports:
// (1) filename as given
// (2) underscore + given
// (3) underscore + given + extension
// (4) given + extension
// if the file as given isn't found ...
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
tmp = path + ".scss";
path_str = tmp.c_str();
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
// then try "_" + given
const char *full_path_str = path.c_str();
const char *file_name_str = Prelexer::folders(full_path_str);
tmp = Token::make(full_path_str, file_name_str).to_string() +
"_" +
string(file_name_str);
string folder(Token::make(full_path_str, file_name_str).to_string());
string partial_filename("_" + string(file_name_str));
tmp = folder + partial_filename;
path_str = tmp.c_str();
// if "_" + given isn't found ...
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
// then try "_" + given + ".scss"
tmp += ".scss";
path_str = tmp.c_str();
// if "_" + given + ".scss" isn't found ...
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
tmp = tmp + ".scss";
// then try given + ".scss"
string non_partial_filename(string(file_name_str) + ".scss");
tmp = folder + non_partial_filename;
path_str = tmp.c_str();
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode))
// if we still can't find the file, then throw an error
if (stat(path_str, &st) == -1 || S_ISDIR(st.st_mode)) {
throw path;
}
}
}
}
f = std::fopen(path_str, "rb");
size_t len = st.st_size;
char* source = new char[len + 1];
......@@ -70,7 +86,7 @@ namespace Sass {
string include_path(path_str, file_name_str - path_str);
Document doc(ctx);
doc.path = path;
doc.path = path_str;
doc.line = 1;
doc.root = ctx.new_Node(Node::root, path, 1, 0);
doc.lexed = Token::make();
......@@ -79,14 +95,11 @@ namespace Sass {
doc.end = end;
doc.position = source;
doc.context.source_refs.push_back(source);
if (!include_path.empty()) {
doc.context.include_paths.push_back(include_path);
}
return doc;
}
Document Document::make_from_source_chars(Context& ctx, char* src, string path, bool own_source)
Document Document::make_from_source_chars(Context& ctx, const char* src, string path, bool own_source)
{
Document doc(ctx);
doc.path = path;
......@@ -110,7 +123,7 @@ namespace Sass {
doc.root = ctx.new_Node(Node::root, path, 1, 0);
doc.lexed = Token::make();
doc.own_source = false;
doc.source = const_cast<char*>(t.begin);
doc.source = t.begin;
doc.end = t.end;
doc.position = doc.source;
......@@ -134,11 +147,14 @@ namespace Sass {
root.echo(output);
break;
case nested:
root.emit_nested_css(output, 0, true);
root.emit_nested_css(output, 0, true, false, context.source_comments);
break;
case expanded:
root.emit_expanded_css(output, "");
break;
case compressed:
root.emit_compressed_css(output);
break;
default:
break;
}
......
......@@ -29,7 +29,7 @@ namespace Sass {
enum CSS_Style { nested, expanded, compact, compressed, echo };
string path;
char* source;
const char* source;
const char* position;
const char* end;
size_t line;
......@@ -48,7 +48,7 @@ namespace Sass {
~Document();
static Document make_from_file(Context& ctx, string path);
static Document make_from_source_chars(Context& ctx, char* src, string path = "", bool own_source = false);
static Document make_from_source_chars(Context& ctx, const char* src, string path = "", bool own_source = false);
static Document make_from_token(Context& ctx, Token t, string path = "", size_t line_number = 1);
template <prelexer mx>
......@@ -133,7 +133,7 @@ namespace Sass {
Node parse_function_definition();
Node parse_parameters();
Node parse_parameter(Node::Type);
Node parse_mixin_call();
Node parse_mixin_call(Node::Type inside_of = Node::none);
Node parse_arguments();
Node parse_argument(Node::Type);
Node parse_assignment();
......
......@@ -10,19 +10,23 @@
#include "context.hpp"
#endif
#ifndef SASS_BACKTRACE
#include "backtrace.hpp"
#endif
namespace Sass {
using std::map;
void expand(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name = false);
Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool function_name = false);
Node eval_arguments(Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx);
Node eval_function(string name, Node stm, Environment& bindings, Node_Factory& new_Node, Context& ctx, bool toplevel = false);
Node reduce(Node list, size_t head, Node acc, Node_Factory& new_Node);
Node accumulate(Node::Type op, Node acc, Node rhs, Node_Factory& new_Node);
double operate(Node op, double lhs, double rhs);
void expand(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, Backtrace& bt, bool function_name = false, const Node content = Node());
void re_expand(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, Backtrace& bt, bool function_name, const Node content);
Node eval(Node expr, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, Backtrace& bt, bool function_name = false);
Node eval_arguments(Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, Backtrace& bt);
Node eval_function(string name, Node stm, Environment& bindings, Node_Factory& new_Node, Context& ctx, Backtrace& bt, bool toplevel = false);
Node reduce(Node list, size_t head, Node acc, Node_Factory& new_Node, Backtrace& bt);
double operate(Node op, double lhs, double rhs, Backtrace& bt);
Node apply_mixin(Node mixin, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, bool dynamic_scope = false);
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, string& path, size_t line);
Node apply_mixin(Node mixin, const Node args, const Node content, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, Backtrace& bt, bool dynamic_scope = false);
Node apply_function(const Function& f, const Node args, Node prefix, Environment& env, map<string, Function>& f_env, Node_Factory& new_Node, Context& ctx, Backtrace& bt, string& path, size_t line);
Node expand_selector(Node sel, Node pre, Node_Factory& new_Node);
Node expand_backref(Node sel, Node pre);
void extend(Node expr, multimap<Node, Node>& extension_requests, Node_Factory& new_Node);
......
......@@ -19,6 +19,7 @@ namespace Sass {
{
case block:
case mixin_call:
case mixin_content:
case root:
case if_directive:
case for_through_directive:
......@@ -35,6 +36,7 @@ namespace Sass {
switch (at(i).type())
{
case mixin_call:
case mixin_content:
case block:
case if_directive:
case for_through_directive:
......@@ -44,6 +46,7 @@ namespace Sass {
Node expn(at(i));
if (expn.has_expansions()) expn.flatten();
ip_->has_statements |= expn.has_statements();
ip_->has_comments |= expn.has_comments();
ip_->has_blocks |= expn.has_blocks();
ip_->has_expansions |= expn.has_expansions();
// TO DO: make this more efficient -- replace with a dummy node instead of erasing
......
......@@ -142,6 +142,7 @@ namespace Sass {
numeric_percentage,
numeric_dimension,
numeric_color,
ie_hex_str,
boolean,
important,
......@@ -154,6 +155,7 @@ namespace Sass {
function_call,
mixin,
mixin_call,
mixin_content,
parameters,
arguments,
......@@ -183,6 +185,7 @@ namespace Sass {
bool has_children() const;
bool has_statements() const;
bool has_comments() const;
bool has_blocks() const;
bool has_expansions() const;
bool has_backref() const;
......@@ -237,11 +240,12 @@ namespace Sass {
bool operator>(Node rhs) const;
bool operator>=(Node rhs) const;
string to_string(Type inside_of = none) const;
void emit_nested_css(stringstream& buf, size_t depth, bool at_toplevel = false, bool in_media_query = false);
void emit_propset(stringstream& buf, size_t depth, const string& prefix);
string to_string(Type inside_of = none, const string space = " ") const;
void emit_nested_css(stringstream& buf, size_t depth, bool at_toplevel = false, bool in_media_query = false, bool source_comments = false);
void emit_propset(stringstream& buf, size_t depth, const string& prefix, const bool compressed = false);
void echo(stringstream& buf, size_t depth = 0);
void emit_expanded_css(stringstream& buf, const string& prefix);
void emit_compressed_css(stringstream& buf);
};
......@@ -264,6 +268,7 @@ namespace Sass {
bool has_children;
bool has_statements;
bool has_comments;
bool has_blocks;
bool has_expansions;
bool has_backref;
......@@ -281,6 +286,7 @@ namespace Sass {
type(Node::none), */
has_children(false),
has_statements(false),
has_comments(false),
has_blocks(false),
has_expansions(false),
has_backref(false),
......@@ -349,9 +355,13 @@ namespace Sass {
{
children.push_back(n);
has_children = true;
if (n.is_null()) return;
switch (n.type())
{
case Node::comment:
case Node::comment: {
has_comments = true;
} break;
case Node::css_import:
case Node::rule:
case Node::propset:
......@@ -372,7 +382,8 @@ namespace Sass {
case Node::for_to_directive:
case Node::each_directive:
case Node::while_directive:
case Node::mixin_call: {
case Node::mixin_call:
case Node::mixin_content: {
has_expansions = true;
} break;
......@@ -391,7 +402,8 @@ namespace Sass {
has_children = true;
switch (n.type())
{
case Node::comment:
case Node::comment: has_comments = true; break;
case Node::css_import:
case Node::rule:
case Node::propset: has_statements = true; break;
......@@ -404,7 +416,8 @@ namespace Sass {
case Node::for_to_directive:
case Node::each_directive:
case Node::while_directive:
case Node::mixin_call: has_expansions = true; break;
case Node::mixin_call:
case Node::mixin_content: has_expansions = true; break;
case Node::backref: has_backref = true; break;
......@@ -440,6 +453,7 @@ namespace Sass {
inline bool Node::has_children() const { return ip_->has_children; }
inline bool Node::has_statements() const { return ip_->has_statements; }
inline bool Node::has_comments() const { return ip_->has_comments; }
inline bool Node::has_blocks() const { return ip_->has_blocks; }
inline bool Node::has_expansions() const { return ip_->has_expansions; }
inline bool Node::has_backref() const { return ip_->has_backref; }
......
......@@ -26,9 +26,7 @@ namespace Sass {
Node operator()(Node::Type type, string file, size_t line, Token t);
// for making boolean values or interior nodes that have children
Node operator()(Node::Type type, string file, size_t line, size_t size);
// // for making nodes representing boolean values
// Node operator()(Node::Type type, string file, size_t line, bool b);
// for making nodes representing numbers
// for making nodes representing numbers and numeric percentages
Node operator()(string file, size_t line, double v, Node::Type type = Node::number);
// for making nodes representing numeric dimensions (e.g. 5px, 3em)
Node operator()(string file, size_t line, double v, const Token& t);
......
......@@ -138,6 +138,10 @@ namespace Sass {
return exactly<include_kwd>(src);
}
const char* content(const char* src) {
return exactly<content_kwd>(src);
}
const char* extend(const char* src) {
return exactly<extend_kwd>(src);
}
......@@ -383,5 +387,32 @@ namespace Sass {
const char* folders(const char* src) {
return zero_plus< folder >(src);
}
const char* chunk(const char* src) {
char inside_str = 0;
const char* p = src;
size_t depth = 0;
while (true) {
if (!*p) {
return 0;
}
else if (!inside_str && (*p == '"' || *p == '\'')) {
inside_str = *p;
}
else if (*p == inside_str && *(p-1) != '\\') {
inside_str = 0;
}
else if (*p == '(' && !inside_str) {
++depth;
}
else if (*p == ')' && !inside_str) {
if (depth == 0) return p;
else --depth;
}
++p;
}
// unreachable
return 0;
}
}
}
\ No newline at end of file
......@@ -317,6 +317,7 @@ namespace Sass {
const char* function(const char* src);
const char* return_directive(const char* src);
const char* include(const char* src);
const char* content(const char* src);
const char* extend(const char* src);
const char* if_directive(const char* src);
......@@ -447,5 +448,7 @@ namespace Sass {
}
return counter;
}
const char* chunk(const char* src);
}
}
......@@ -45,13 +45,15 @@ extern "C" {
static char* process_document(Sass::Document& doc, int style)
{
using namespace Sass;
Backtrace root_trace(0, "", 0, "");
doc.parse_scss();
expand(doc.root,
Node(),
doc.context.global_env,
doc.context.function_env,
doc.context.new_Node,
doc.context);
doc.context,
root_trace);
// extend_selectors(doc.context.pending_extensions, doc.context.extensions, doc.context.new_Node);
if (doc.context.has_extensions) extend(doc.root, doc.context.extensions, doc.context.new_Node);
string output(doc.emit_css(static_cast<Document::CSS_Style>(style)));
......@@ -64,7 +66,7 @@ extern "C" {
{
using namespace Sass;
try {
Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path);
Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path, c_ctx->options.source_comments);
// cpp_ctx.image_path = c_ctx->options.image_path;
// Document doc(0, c_ctx->input_string, cpp_ctx);
Document doc(Document::make_from_source_chars(cpp_ctx, c_ctx->source_string));
......@@ -74,7 +76,7 @@ extern "C" {
}
catch (Error& e) {
stringstream msg_stream;
msg_stream << "ERROR -- " << e.path << ", line " << e.line << ": " << e.message << endl;
msg_stream << e.path << ":" << e.line << ": error: " << e.message << endl;
string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str());
......@@ -84,7 +86,7 @@ extern "C" {
}
catch(bad_alloc& ba) {
stringstream msg_stream;
msg_stream << "ERROR -- unable to allocate memory: " << ba.what() << endl;
msg_stream << "Unable to allocate memory: " << ba.what() << endl;
string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str());
......@@ -99,22 +101,16 @@ extern "C" {
int sass_compile_file(sass_file_context* c_ctx)
{
using namespace Sass;
Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path, c_ctx->options.source_comments);
try {
Context cpp_ctx(c_ctx->options.include_paths, c_ctx->options.image_path);
// Document doc(c_ctx->input_path, 0, cpp_ctx);
// string path_string(c_ctx->options.image_path);
// path_string = "'" + path_string + "/";
// cpp_ctx.image_path = c_ctx->options.image_path;
Document doc(Document::make_from_file(cpp_ctx, string(c_ctx->input_path)));
// cerr << "MADE A DOC AND CONTEXT OBJ" << endl;
// cerr << "REGISTRY: " << doc.context.registry.size() << endl;
c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
c_ctx->error_message = 0;
c_ctx->error_status = 0;
}
catch (Error& e) {
stringstream msg_stream;
msg_stream << "ERROR -- " << e.path << ", line " << e.line << ": " << e.message << endl;
msg_stream << e.path << ":" << e.line << ": error: " << e.message << endl;
string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str());
......@@ -124,7 +120,30 @@ extern "C" {
}
catch(bad_alloc& ba) {
stringstream msg_stream;
msg_stream << "ERROR -- unable to allocate memory: " << ba.what() << endl;
msg_stream << "Unable to allocate memory: " << ba.what() << endl;
string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str());
c_ctx->error_status = 1;
c_ctx->output_string = 0;
c_ctx->error_message = msg_str;
}
catch(string& bad_path) {
for (vector<string>::iterator path = cpp_ctx.include_paths.begin(); path < cpp_ctx.include_paths.end(); ++path) {
try {
Document doc(Document::make_from_file(cpp_ctx, *path + string(c_ctx->input_path)));
c_ctx->output_string = process_document(doc, c_ctx->options.output_style);
c_ctx->error_message = 0;
c_ctx->error_status = 0;
return 0;
}
catch (string& bad_path) {
// continue looping
}
}
// couldn't find the specified file in the include paths; report an error
stringstream msg_stream;
msg_stream << "error reading file \"" << bad_path << "\"" << endl;
string msg(msg_stream.str());
char* msg_str = (char*) malloc(msg.size() + 1);
strcpy(msg_str, msg.c_str());
......
#include <node.h>
#define SASS_INTERFACE
#ifdef __cplusplus
extern "C" {
......@@ -11,18 +11,17 @@ extern "C" {
struct sass_options {
int output_style;
int source_comments; // really want a bool, but C doesn't have them
char* include_paths;
char* image_path;
};
struct sass_context {
char* source_string;
const char* source_string;
char* output_string;
struct sass_options options;
int error_status;
char* error_message;
uv_work_t request;
v8::Persistent<v8::Function> callback;
};
struct sass_file_context {
......
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