Skip to content

Commit

Permalink
Merge pull request sass#926 from mgreter/bugfix/issue_855
Browse files Browse the repository at this point in the history
Fix parsing and output of unknown at-rules (Fixes sass#855)
  • Loading branch information
mgreter committed Mar 8, 2015
2 parents dd4187a + 8c98da8 commit 77c1b23
Show file tree
Hide file tree
Showing 20 changed files with 106 additions and 10 deletions.
8 changes: 7 additions & 1 deletion ast.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,13 @@ namespace Sass {
At_Rule(ParserState pstate, string kwd, Selector* sel = 0, Block* b = 0)
: Has_Block(pstate, b), keyword_(kwd), selector_(sel), value_(0) // set value manually if needed
{ statement_type(DIRECTIVE); }
bool bubbles() { return true; }
bool bubbles() { return is_keyframes() || is_media(); }
bool is_media() {
return keyword_.compare("@-webkit-media") == 0 ||
keyword_.compare("@-moz-media") == 0 ||
keyword_.compare("@-o-media") == 0 ||
keyword_.compare("@media") == 0;
}
bool is_keyframes() {
return keyword_.compare("@-webkit-keyframes") == 0 ||
keyword_.compare("@-moz-keyframes") == 0 ||
Expand Down
1 change: 1 addition & 0 deletions context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ namespace Sass {
source_comments (initializers.source_comments()),
output_style (initializers.output_style()),
source_map_file (make_canonical_path(initializers.source_map_file())),
source_map_root (initializers.source_map_root()), // pass-through
source_map_embed (initializers.source_map_embed()),
source_map_contents (initializers.source_map_contents()),
omit_source_map_url (initializers.omit_source_map_url()),
Expand Down
2 changes: 2 additions & 0 deletions context.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ namespace Sass {
bool source_comments; // for inline debug comments in css output
Output_Style output_style; // output style for the generated css code
string source_map_file; // path to source map file (enables feature)
string source_map_root; // path for sourceRoot property (pass-through)
bool source_map_embed; // embed in sourceMappingUrl (as data-url)
bool source_map_contents; // insert included contents into source map
bool omit_source_map_url; // disable source map comment in css output
Expand Down Expand Up @@ -90,6 +91,7 @@ namespace Sass {
KWD_ARG(Data, bool, source_comments);
KWD_ARG(Data, Output_Style, output_style);
KWD_ARG(Data, string, source_map_file);
KWD_ARG(Data, string, source_map_root);
KWD_ARG(Data, bool, omit_source_map_url);
KWD_ARG(Data, bool, is_indented_syntax_src);
KWD_ARG(Data, size_t, precision);
Expand Down
4 changes: 2 additions & 2 deletions debugger.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
" <" << prettyprint(selector->pstate().token.ws_before()) << "> X <" << prettyprint(selector->pstate().token.ws_after()) << ">" << endl;
} else if (dynamic_cast<Selector_Placeholder*>(node)) {
Selector_Placeholder* selector = dynamic_cast<Selector_Placeholder*>(node);
cerr << ind << "Selector_Placeholder " << selector << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << endl;
cerr << ind << "Selector_Placeholder [" << selector->name() << "] " << selector << (selector->has_line_break() ? " [line-break]": " -") << (selector->has_line_feed() ? " [line-feed]": " -") << endl;
} else if (dynamic_cast<Selector_Reference*>(node)) {
Selector_Reference* selector = dynamic_cast<Selector_Reference*>(node);
cerr << ind << "Selector_Reference " << selector << " @ref " << selector->selector() << endl;
Expand Down Expand Up @@ -161,7 +161,7 @@ inline void debug_ast(AST_Node* node, string ind = "", Env* env = 0)
debug_ast(block->value(), ind + " value: ", env);
} else if (dynamic_cast<At_Rule*>(node)) {
At_Rule* block = dynamic_cast<At_Rule*>(node);
cerr << ind << "At_Rule " << block << " " << block->tabs() << endl;
cerr << ind << "At_Rule " << block << " [" << block->keyword() << "] " << block->tabs() << endl;
debug_ast(block->value(), ind + "+", env);
debug_ast(block->selector(), ind + "~", env);
if (block->block()) for(auto i : block->block()->elements()) { debug_ast(i, ind + " ", env); }
Expand Down
1 change: 1 addition & 0 deletions emitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace Sass {
scheduled_linefeed(0),
scheduled_delimiter(false),
in_comment(false),
in_at_rule(false),
in_media_block(false),
in_declaration(false),
in_declaration_list(false)
Expand Down
1 change: 1 addition & 0 deletions emitter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace Sass {

public:
bool in_comment;
bool in_at_rule;
bool in_media_block;
bool in_declaration;
bool in_declaration_list;
Expand Down
4 changes: 3 additions & 1 deletion inspect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ namespace Sass {
append_token(at_rule->keyword(), at_rule);
if (at_rule->selector()) {
append_mandatory_space();
in_at_rule = true;
at_rule->selector()->perform(this);
in_at_rule = false;
}
if (at_rule->block()) {
at_rule->block()->perform(this);
Expand Down Expand Up @@ -836,7 +838,7 @@ namespace Sass {
{
if (g->empty()) return;
for (size_t i = 0, L = g->length(); i < L; ++i) {
if (i == 0) append_indentation();
if (!in_at_rule && i == 0) append_indentation();
(*g)[i]->perform(this);
if (i < L - 1) {
append_comma_separator();
Expand Down
2 changes: 2 additions & 0 deletions output.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,9 @@ namespace Sass {
append_token(kwd, a);
if (s) {
append_mandatory_space();
in_at_rule = true;
s->perform(this);
in_at_rule = false;
}
else if (v) {
append_mandatory_space();
Expand Down
10 changes: 8 additions & 2 deletions parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,9 +199,15 @@ namespace Sass {
while (*includes) {
struct Sass_Import* include = *includes;
const char *file = sass_import_get_path(include);
char *source = sass_import_take_source(include);
char* source = sass_import_take_source(include);
size_t line = sass_import_get_error_line(include);
size_t column = sass_import_get_error_column(include);
const char* message = sass_import_get_error_message(include);
// char *srcmap = sass_import_take_srcmap(include);
if (source) {
if (message) {
if (line == string::npos && column == string::npos) error(message, pstate);
else error(message, ParserState(message, Position(line, column)));
} else if (source) {
if (file) {
ctx.add_source(file, inc_path, source);
imp->files().push_back(file);
Expand Down
4 changes: 2 additions & 2 deletions position.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,8 @@ namespace Sass {
public: // c-tor
ParserState(string path);
ParserState(string path, const size_t file);
ParserState(string path, Position position, Offset offset);
ParserState(string path, Token token, Position position, Offset offset);
ParserState(string path, Position position, Offset offset = Offset(0, 0));
ParserState(string path, Token token, Position position, Offset offset = Offset(0, 0));

public: // down casts
Offset off() { return *this; };
Expand Down
4 changes: 3 additions & 1 deletion prelexer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ namespace Sass {

// Match any single character.
const char* any_char(const char* src) { return *src ? src+1 : src; }
// Match word boundary (look ahead)
const char* word_boundary(const char* src) { return !*src || isspace(*src) || ispunct(*src) || !Sass::Util::isAscii(*src) ? src : 0 ; }

// Match a single character satisfying the ctype predicates.
const char* space(const char* src) { return std::isspace(*src) ? src+1 : 0; }
Expand Down Expand Up @@ -288,7 +290,7 @@ namespace Sass {
}

const char* extend(const char* src) {
return exactly<extend_kwd>(src);
return sequence < exactly<extend_kwd>, word_boundary >(src);
}


Expand Down
2 changes: 2 additions & 0 deletions prelexer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ namespace Sass {
const char* any_char_except(const char* src) {
return (*src && *src != c) ? src+1 : 0;
}
// Match word boundary (look ahead)
const char* word_boundary(const char* src);

// Matches zero characters (always succeeds without consuming input).
// const char* epsilon(const char*);
Expand Down
9 changes: 9 additions & 0 deletions sass.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,15 @@
#include <stddef.h>
#include <stdbool.h>

#ifdef __GNUC__
#define DEPRECATED(func) func __attribute__ ((deprecated))
#elif defined(_MSC_VER)
#define DEPRECATED(func) __declspec(deprecated) func
#else
#pragma message("WARNING: You need to implement DEPRECATED for this compiler")
#define DEPRECATED(func) func
#endif

#ifdef _WIN32

/* You should define ADD_EXPORTS *only* when building the DLL. */
Expand Down
18 changes: 18 additions & 0 deletions sass_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ extern "C" {
// Used to create sourceMappingUrl
char* source_map_file;

// option for sourceRoot property
char* source_map_root;

// Custom functions that can be called from sccs code
Sass_C_Function_List c_functions;

Expand All @@ -118,6 +121,7 @@ extern "C" {
// error status
int error_status;
char* error_json;
char* error_text;
char* error_message;
// error position
char* error_file;
Expand Down Expand Up @@ -229,6 +233,7 @@ extern "C" {
msg_stream << e.pstate.path << ":" << e.pstate.line+1 << ": " << e.message << endl;
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup(e.message.c_str());
c_ctx->error_status = 1;
c_ctx->error_file = copy_c_str(e.pstate.path.c_str());
c_ctx->error_line = e.pstate.line+1;
Expand All @@ -245,6 +250,7 @@ extern "C" {
json_append_member(json_err, "message", json_mkstring(ba.what()));
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup(ba.what());
c_ctx->error_status = 2;
c_ctx->output_string = 0;
c_ctx->source_map_string = 0;
Expand All @@ -258,6 +264,7 @@ extern "C" {
json_append_member(json_err, "message", json_mkstring(e.what()));
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup(e.what());
c_ctx->error_status = 3;
c_ctx->output_string = 0;
c_ctx->source_map_string = 0;
Expand All @@ -271,6 +278,7 @@ extern "C" {
json_append_member(json_err, "message", json_mkstring(e.c_str()));
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup(e.c_str());
c_ctx->error_status = 4;
c_ctx->output_string = 0;
c_ctx->source_map_string = 0;
Expand All @@ -284,6 +292,7 @@ extern "C" {
json_append_member(json_err, "message", json_mkstring("unknown"));
c_ctx->error_json = json_stringify(json_err, " ");;
c_ctx->error_message = copy_c_str(msg_stream.str().c_str());
c_ctx->error_text = strdup("unknown");
c_ctx->error_status = 5;
c_ctx->output_string = 0;
c_ctx->source_map_string = 0;
Expand Down Expand Up @@ -343,6 +352,7 @@ extern "C" {
.is_indented_syntax_src(c_ctx->is_indented_syntax_src)
.source_comments(c_ctx->source_comments)
.source_map_file(safe_str(c_ctx->source_map_file))
.source_map_root(safe_str(c_ctx->source_map_root))
.source_map_embed(c_ctx->source_map_embed)
.source_map_contents(c_ctx->source_map_contents)
.omit_source_map_url(c_ctx->omit_source_map_url)
Expand Down Expand Up @@ -374,6 +384,7 @@ extern "C" {

// reset error status
c_ctx->error_json = 0;
c_ctx->error_text = 0;
c_ctx->error_message = 0;
c_ctx->error_status = 0;
// reset error position
Expand Down Expand Up @@ -651,23 +662,27 @@ extern "C" {
if (ctx->output_string) free(ctx->output_string);
if (ctx->source_map_string) free(ctx->source_map_string);
if (ctx->error_message) free(ctx->error_message);
if (ctx->error_text) free(ctx->error_text);
if (ctx->error_json) free(ctx->error_json);
if (ctx->error_file) free(ctx->error_file);
if (ctx->input_path) free(ctx->input_path);
if (ctx->output_path) free(ctx->output_path);
if (ctx->include_path) free(ctx->include_path);
if (ctx->source_map_file) free(ctx->source_map_file);
if (ctx->source_map_root) free(ctx->source_map_root);
free_string_array(ctx->included_files);
// play safe and reset properties
ctx->output_string = 0;
ctx->source_map_string = 0;
ctx->error_message = 0;
ctx->error_text = 0;
ctx->error_json = 0;
ctx->error_file = 0;
ctx->input_path = 0;
ctx->output_path = 0;
ctx->include_path = 0;
ctx->source_map_file = 0;
ctx->source_map_root = 0;
ctx->included_files = 0;
// now clear the options
sass_clear_options(ctx);
Expand Down Expand Up @@ -714,11 +729,13 @@ extern "C" {
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, plugin_path);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, include_path);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_file);
IMPLEMENT_SASS_OPTION_STRING_ACCESSOR(const char*, source_map_root);

// Create getter and setters for context
IMPLEMENT_SASS_CONTEXT_GETTER(int, error_status);
IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_json);
IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_message);
IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_text);
IMPLEMENT_SASS_CONTEXT_GETTER(const char*, error_file);
IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_line);
IMPLEMENT_SASS_CONTEXT_GETTER(size_t, error_column);
Expand All @@ -729,6 +746,7 @@ extern "C" {
// Take ownership of memory (value on context is set to 0)
IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_json);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_message);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_text);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, error_file);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, output_string);
IMPLEMENT_SASS_CONTEXT_TAKER(char*, source_map_string);
Expand Down
4 changes: 4 additions & 0 deletions sass_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ ADDAPI const char* ADDCALL sass_option_get_output_path (struct Sass_Options* opt
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_C_Function_List ADDCALL sass_option_get_c_functions (struct Sass_Options* options);
ADDAPI Sass_C_Import_Callback ADDCALL sass_option_get_importer (struct Sass_Options* options);

Expand All @@ -91,6 +92,7 @@ ADDAPI void ADDCALL sass_option_set_output_path (struct Sass_Options* options, c
ADDAPI void ADDCALL sass_option_set_plugin_path (struct Sass_Options* options, const char* plugin_path);
ADDAPI void ADDCALL sass_option_set_include_path (struct Sass_Options* options, const char* include_path);
ADDAPI void ADDCALL sass_option_set_source_map_file (struct Sass_Options* options, const char* source_map_file);
ADDAPI void ADDCALL sass_option_set_source_map_root (struct Sass_Options* options, const char* source_map_root);
ADDAPI void ADDCALL sass_option_set_c_functions (struct Sass_Options* options, Sass_C_Function_List c_functions);
ADDAPI void ADDCALL sass_option_set_importer (struct Sass_Options* options, Sass_C_Import_Callback importer);

Expand All @@ -99,6 +101,7 @@ ADDAPI void ADDCALL sass_option_set_importer (struct Sass_Options* options, Sass
ADDAPI const char* ADDCALL sass_context_get_output_string (struct Sass_Context* ctx);
ADDAPI int ADDCALL sass_context_get_error_status (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_error_json (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_error_text (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_error_message (struct Sass_Context* ctx);
ADDAPI const char* ADDCALL sass_context_get_error_file (struct Sass_Context* ctx);
ADDAPI size_t ADDCALL sass_context_get_error_line (struct Sass_Context* ctx);
Expand All @@ -108,6 +111,7 @@ ADDAPI char** ADDCALL sass_context_get_included_files (struct Sass_Context* ctx)

// Take ownership of memory (value on context is set to 0)
ADDAPI char* ADDCALL sass_context_take_error_json (struct Sass_Context* ctx);
ADDAPI char* ADDCALL sass_context_take_error_text (struct Sass_Context* ctx);
ADDAPI char* ADDCALL sass_context_take_error_message (struct Sass_Context* ctx);
ADDAPI char* ADDCALL sass_context_take_error_file (struct Sass_Context* ctx);
ADDAPI char* ADDCALL sass_context_take_output_string (struct Sass_Context* ctx);
Expand Down
24 changes: 24 additions & 0 deletions sass_functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ extern "C" {
char* base;
char* source;
char* srcmap;
// error handling
char* error;
size_t line;
size_t column;
};

// Struct to hold importer callback
Expand Down Expand Up @@ -90,6 +94,9 @@ extern "C" {
v->base = base ? Sass::copy_c_str(base) : 0;
v->source = source;
v->srcmap = srcmap;
v->error = 0;
v->line = -1;
v->column = -1;
return v;
}

Expand All @@ -99,6 +106,17 @@ extern "C" {
return sass_make_import(path, path, source, srcmap);
}

// Upgrade a normal import entry to throw an error (original path can be re-used by error reporting)
struct Sass_Import* ADDCALL sass_import_set_error(struct Sass_Import* import, const char* error, size_t line, size_t col)
{
if (import == 0) return 0;
if (import->error) free(import->error);
import->error = error ? strdup(error) : 0;
import->line = line ? line : -1;
import->column = col ? col : -1;
return import;
}

// Setters and getters for entries on the import list
void ADDCALL sass_import_set_list_entry(struct Sass_Import** list, size_t idx, struct Sass_Import* entry) { list[idx] = entry; }
struct Sass_Import* ADDCALL sass_import_get_list_entry(struct Sass_Import** list, size_t idx) { return list[idx]; }
Expand All @@ -122,6 +140,7 @@ extern "C" {
free(import->base);
free(import->source);
free(import->srcmap);
free(import->error);
free(import);
}

Expand All @@ -131,6 +150,11 @@ extern "C" {
const char* ADDCALL sass_import_get_source(struct Sass_Import* entry) { return entry->source; }
const char* ADDCALL sass_import_get_srcmap(struct Sass_Import* entry) { return entry->srcmap; }

// Getter for import error entry
size_t ADDCALL sass_import_get_error_line(struct Sass_Import* entry) { return entry->line; }
size_t ADDCALL sass_import_get_error_column(struct Sass_Import* entry) { return entry->column; }
const char* ADDCALL sass_import_get_error_message(struct Sass_Import* entry) { return entry->error; }

// Explicit functions to take ownership of the memory
// Resets our own property since we do not know if it is still alive
char* ADDCALL sass_import_take_source(struct Sass_Import* entry) { char* ptr = entry->source; entry->source = 0; return ptr; }
Expand Down
Loading

0 comments on commit 77c1b23

Please sign in to comment.