sassc 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/ext/libsass/.gitignore +13 -6
- data/ext/libsass/Makefile +42 -26
- data/ext/libsass/Makefile.am +43 -30
- data/ext/libsass/Readme.md +4 -2
- data/ext/libsass/appveyor.yml +10 -14
- data/ext/libsass/ast.cpp +54 -44
- data/ext/libsass/ast.hpp +404 -236
- data/ext/libsass/ast_def_macros.hpp +5 -0
- data/ext/libsass/ast_factory.hpp +6 -3
- data/ext/libsass/ast_fwd_decl.hpp +12 -0
- data/ext/libsass/b64/encode.h +2 -2
- data/ext/libsass/backtrace.hpp +13 -17
- data/ext/libsass/base64vlq.hpp +4 -1
- data/ext/libsass/bind.cpp +12 -15
- data/ext/libsass/bind.hpp +6 -6
- data/ext/libsass/color_names.hpp +4 -1
- data/ext/libsass/configure.ac +7 -21
- data/ext/libsass/constants.cpp +6 -4
- data/ext/libsass/constants.hpp +10 -4
- data/ext/libsass/context.cpp +89 -58
- data/ext/libsass/context.hpp +28 -35
- data/ext/libsass/contextualize.cpp +20 -10
- data/ext/libsass/contextualize.hpp +8 -23
- data/ext/libsass/contrib/libsass.spec +66 -0
- data/ext/libsass/cssize.cpp +547 -0
- data/ext/libsass/cssize.hpp +82 -0
- data/ext/libsass/debug.hpp +3 -3
- data/ext/libsass/debugger.hpp +358 -0
- data/ext/libsass/emitter.cpp +255 -0
- data/ext/libsass/emitter.hpp +83 -0
- data/ext/libsass/environment.hpp +7 -3
- data/ext/libsass/error_handling.cpp +11 -14
- data/ext/libsass/error_handling.hpp +9 -7
- data/ext/libsass/eval.cpp +253 -161
- data/ext/libsass/eval.hpp +13 -13
- data/ext/libsass/expand.cpp +135 -64
- data/ext/libsass/expand.hpp +11 -13
- data/ext/libsass/extend.cpp +66 -20
- data/ext/libsass/extend.hpp +6 -11
- data/ext/libsass/file.cpp +31 -26
- data/ext/libsass/file.hpp +6 -1
- data/ext/libsass/functions.cpp +270 -287
- data/ext/libsass/functions.hpp +8 -11
- data/ext/libsass/inspect.cpp +385 -255
- data/ext/libsass/inspect.hpp +15 -26
- data/ext/libsass/kwd_arg_macros.hpp +5 -0
- data/ext/libsass/mapping.hpp +4 -3
- data/ext/libsass/memory_manager.hpp +5 -2
- data/ext/libsass/node.cpp +50 -50
- data/ext/libsass/node.hpp +26 -27
- data/ext/libsass/operation.hpp +15 -4
- data/ext/libsass/output.cpp +401 -0
- data/ext/libsass/output.hpp +56 -0
- data/ext/libsass/parser.cpp +573 -399
- data/ext/libsass/parser.hpp +122 -88
- data/ext/libsass/paths.hpp +7 -2
- data/ext/libsass/plugins.cpp +155 -0
- data/ext/libsass/plugins.hpp +56 -0
- data/ext/libsass/position.cpp +128 -0
- data/ext/libsass/position.hpp +108 -11
- data/ext/libsass/prelexer.cpp +184 -110
- data/ext/libsass/prelexer.hpp +131 -24
- data/ext/libsass/remove_placeholders.cpp +1 -1
- data/ext/libsass/remove_placeholders.hpp +6 -6
- data/ext/libsass/sass.cpp +3 -3
- data/ext/libsass/sass.h +12 -4
- data/ext/libsass/sass2scss.cpp +3 -2
- data/ext/libsass/sass2scss.h +5 -0
- data/ext/libsass/sass_context.cpp +136 -37
- data/ext/libsass/sass_context.h +19 -10
- data/ext/libsass/sass_functions.cpp +29 -2
- data/ext/libsass/sass_functions.h +8 -2
- data/ext/libsass/sass_interface.cpp +32 -23
- data/ext/libsass/sass_interface.h +9 -4
- data/ext/libsass/sass_util.cpp +19 -23
- data/ext/libsass/sass_util.hpp +28 -27
- data/ext/libsass/sass_values.cpp +6 -4
- data/ext/libsass/sass_values.h +3 -3
- data/ext/libsass/script/ci-build-libsass +13 -1
- data/ext/libsass/script/ci-report-coverage +2 -1
- data/ext/libsass/source_map.cpp +79 -28
- data/ext/libsass/source_map.hpp +35 -16
- data/ext/libsass/subset_map.hpp +6 -4
- data/ext/libsass/to_c.hpp +4 -4
- data/ext/libsass/to_string.cpp +13 -8
- data/ext/libsass/to_string.hpp +6 -4
- data/ext/libsass/units.cpp +2 -1
- data/ext/libsass/units.hpp +6 -1
- data/ext/libsass/utf8_string.cpp +0 -5
- data/ext/libsass/utf8_string.hpp +3 -2
- data/ext/libsass/util.cpp +461 -49
- data/ext/libsass/util.hpp +34 -13
- data/ext/libsass/version.sh +10 -0
- data/ext/libsass/win/libsass.filters +20 -11
- data/ext/libsass/win/libsass.vcxproj +11 -8
- data/lib/sassc/importer.rb +1 -8
- data/lib/sassc/native.rb +7 -0
- data/lib/sassc/native/native_context_api.rb +5 -5
- data/lib/sassc/version.rb +1 -1
- data/test/native_test.rb +1 -1
- metadata +14 -10
- data/ext/libsass/copy_c_str.cpp +0 -13
- data/ext/libsass/copy_c_str.hpp +0 -5
- data/ext/libsass/output_compressed.cpp +0 -401
- data/ext/libsass/output_compressed.hpp +0 -95
- data/ext/libsass/output_nested.cpp +0 -364
- data/ext/libsass/output_nested.hpp +0 -108
- data/ext/libsass/test-driver +0 -127
- data/ext/libsass/token.hpp +0 -32
data/ext/libsass/parser.hpp
CHANGED
|
@@ -1,29 +1,15 @@
|
|
|
1
|
-
#
|
|
1
|
+
#ifndef SASS_PARSER_H
|
|
2
|
+
#define SASS_PARSER_H
|
|
2
3
|
|
|
3
|
-
#include <vector>
|
|
4
4
|
#include <map>
|
|
5
|
+
#include <vector>
|
|
6
|
+
#include <iostream>
|
|
5
7
|
|
|
6
|
-
#ifndef SASS_PRELEXER
|
|
7
|
-
#include "prelexer.hpp"
|
|
8
|
-
#endif
|
|
9
|
-
|
|
10
|
-
#ifndef SASS_TOKEN
|
|
11
|
-
#include "token.hpp"
|
|
12
|
-
#endif
|
|
13
|
-
|
|
14
|
-
#ifndef SASS_CONTEXT
|
|
15
|
-
#include "context.hpp"
|
|
16
|
-
#endif
|
|
17
|
-
|
|
18
|
-
#ifndef SASS_AST
|
|
19
8
|
#include "ast.hpp"
|
|
20
|
-
#endif
|
|
21
|
-
|
|
22
|
-
#ifndef SASS_POSITION
|
|
23
9
|
#include "position.hpp"
|
|
24
|
-
#
|
|
25
|
-
|
|
26
|
-
#include
|
|
10
|
+
#include "context.hpp"
|
|
11
|
+
#include "position.hpp"
|
|
12
|
+
#include "prelexer.hpp"
|
|
27
13
|
|
|
28
14
|
struct Selector_Lookahead {
|
|
29
15
|
const char* found;
|
|
@@ -36,7 +22,7 @@ namespace Sass {
|
|
|
36
22
|
using std::map;
|
|
37
23
|
using namespace Prelexer;
|
|
38
24
|
|
|
39
|
-
class Parser {
|
|
25
|
+
class Parser : public ParserState {
|
|
40
26
|
private:
|
|
41
27
|
void add_single_file (Import* imp, string import_path);
|
|
42
28
|
public:
|
|
@@ -45,26 +31,30 @@ namespace Sass {
|
|
|
45
31
|
enum Syntactic_Context { nothing, mixin_def, function_def };
|
|
46
32
|
|
|
47
33
|
Context& ctx;
|
|
34
|
+
vector<Block*> block_stack;
|
|
48
35
|
vector<Syntactic_Context> stack;
|
|
36
|
+
Media_Block* last_media_block;
|
|
49
37
|
const char* source;
|
|
50
38
|
const char* position;
|
|
51
39
|
const char* end;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
40
|
+
Position before_token;
|
|
41
|
+
Position after_token;
|
|
42
|
+
ParserState pstate;
|
|
43
|
+
int indentation;
|
|
55
44
|
|
|
56
45
|
|
|
57
46
|
Token lexed;
|
|
58
|
-
bool
|
|
47
|
+
bool in_at_root;
|
|
59
48
|
|
|
60
|
-
Parser(Context& ctx,
|
|
61
|
-
: ctx(ctx), stack(
|
|
62
|
-
source(0), position(0), end(0),
|
|
63
|
-
{
|
|
49
|
+
Parser(Context& ctx, const ParserState& pstate)
|
|
50
|
+
: ParserState(pstate), ctx(ctx), block_stack(0), stack(0), last_media_block(0),
|
|
51
|
+
source(0), position(0), end(0), before_token(pstate), after_token(pstate), pstate("[NULL]"), indentation(0)
|
|
52
|
+
{ in_at_root = false; stack.push_back(nothing); }
|
|
64
53
|
|
|
65
|
-
static Parser from_string(string src, Context& ctx,
|
|
66
|
-
static Parser from_c_str(const char* src, Context& ctx,
|
|
67
|
-
static Parser
|
|
54
|
+
// static Parser from_string(const string& src, Context& ctx, ParserState pstate = ParserState("[STRING]"));
|
|
55
|
+
static Parser from_c_str(const char* src, Context& ctx, ParserState pstate = ParserState("[CSTRING]"));
|
|
56
|
+
static Parser from_c_str(const char* beg, const char* end, Context& ctx, ParserState pstate = ParserState("[CSTRING]"));
|
|
57
|
+
static Parser from_token(Token t, Context& ctx, ParserState pstate = ParserState("[TOKEN]"));
|
|
68
58
|
|
|
69
59
|
#ifdef __clang__
|
|
70
60
|
|
|
@@ -78,102 +68,141 @@ namespace Sass {
|
|
|
78
68
|
|
|
79
69
|
#endif
|
|
80
70
|
|
|
71
|
+
|
|
72
|
+
bool peek_newline(const char* start = 0);
|
|
73
|
+
|
|
81
74
|
template <prelexer mx>
|
|
82
75
|
const char* peek(const char* start = 0)
|
|
83
76
|
{
|
|
84
77
|
if (!start) start = position;
|
|
85
|
-
const char*
|
|
78
|
+
const char* it_before_token;
|
|
86
79
|
if (mx == block_comment) {
|
|
87
|
-
|
|
80
|
+
it_before_token = // start;
|
|
88
81
|
zero_plus< alternatives<spaces, line_comment> >(start);
|
|
89
82
|
}
|
|
90
83
|
else if (/*mx == ancestor_of ||*/ mx == no_spaces) {
|
|
91
|
-
|
|
84
|
+
it_before_token = position;
|
|
92
85
|
}
|
|
93
|
-
else if (mx == spaces
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
return
|
|
86
|
+
else if (mx == spaces) {
|
|
87
|
+
it_before_token = mx(start);
|
|
88
|
+
if (it_before_token) {
|
|
89
|
+
return it_before_token;
|
|
97
90
|
}
|
|
98
91
|
else {
|
|
99
92
|
return 0;
|
|
100
93
|
}
|
|
101
94
|
}
|
|
102
95
|
else if (mx == optional_spaces) {
|
|
103
|
-
|
|
96
|
+
it_before_token = optional_spaces(start);
|
|
104
97
|
}
|
|
105
98
|
else if (mx == line_comment_prefix || mx == block_comment_prefix) {
|
|
106
|
-
|
|
99
|
+
it_before_token = position;
|
|
107
100
|
}
|
|
108
101
|
else {
|
|
109
|
-
|
|
102
|
+
it_before_token = optional_spaces_and_comments(start);
|
|
110
103
|
}
|
|
111
|
-
const char*
|
|
112
|
-
if (
|
|
113
|
-
return
|
|
104
|
+
const char* it_after_token = mx(it_before_token);
|
|
105
|
+
if (it_after_token) {
|
|
106
|
+
return it_after_token;
|
|
114
107
|
}
|
|
115
108
|
else {
|
|
116
109
|
return 0;
|
|
117
110
|
}
|
|
118
111
|
}
|
|
119
112
|
|
|
113
|
+
// white-space handling is built into the lexer
|
|
114
|
+
// this way you do not need to parse it yourself
|
|
115
|
+
// some matchers don't accept certain white-space
|
|
120
116
|
template <prelexer mx>
|
|
121
117
|
const char* lex()
|
|
122
118
|
{
|
|
123
|
-
|
|
119
|
+
|
|
120
|
+
// remeber interesting position
|
|
121
|
+
const char* wspace_start = position;
|
|
122
|
+
|
|
123
|
+
// advance position for next call
|
|
124
|
+
before_token = after_token;
|
|
125
|
+
|
|
126
|
+
// after optional whitespace
|
|
127
|
+
const char* it_before_token;
|
|
128
|
+
|
|
124
129
|
if (mx == block_comment) {
|
|
125
|
-
|
|
126
|
-
|
|
130
|
+
// a block comment can be preceded by spaces and/or line comments
|
|
131
|
+
it_before_token = zero_plus< alternatives<spaces, line_comment> >(position);
|
|
127
132
|
}
|
|
128
|
-
else if (mx == url) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
else if (mx == ancestor_of || mx == no_spaces) {
|
|
132
|
-
after_whitespace = position;
|
|
133
|
+
else if (mx == url || mx == no_spaces) {
|
|
134
|
+
// parse everything literally
|
|
135
|
+
it_before_token = position;
|
|
133
136
|
}
|
|
137
|
+
|
|
134
138
|
else if (mx == spaces) {
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
|
|
138
|
-
lexed = Token(position, after_whitespace);
|
|
139
|
-
return position = after_whitespace;
|
|
139
|
+
it_before_token = spaces(position);
|
|
140
|
+
if (it_before_token) {
|
|
141
|
+
return position = it_before_token;
|
|
140
142
|
}
|
|
141
143
|
else {
|
|
142
144
|
return 0;
|
|
143
145
|
}
|
|
144
146
|
}
|
|
147
|
+
|
|
148
|
+
else if (mx == optional_spaces_and_comments) {
|
|
149
|
+
it_before_token = position;
|
|
150
|
+
}
|
|
151
|
+
else if (mx == spaces_and_comments) {
|
|
152
|
+
it_before_token = position;
|
|
153
|
+
}
|
|
154
|
+
|
|
145
155
|
else if (mx == optional_spaces) {
|
|
146
|
-
|
|
156
|
+
// ToDo: what are optiona_spaces ???
|
|
157
|
+
it_before_token = optional_spaces(position);
|
|
147
158
|
}
|
|
148
159
|
else {
|
|
149
|
-
|
|
160
|
+
// most can be preceded by spaces and comments
|
|
161
|
+
it_before_token = optional_spaces_and_comments(position);
|
|
150
162
|
}
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if (previous_line != source_position.line) {
|
|
165
|
-
column = 1;
|
|
163
|
+
|
|
164
|
+
// now call matcher to get position after token
|
|
165
|
+
const char* it_after_token = mx(it_before_token);
|
|
166
|
+
// assertion that we got a valid match
|
|
167
|
+
if (it_after_token == 0) return 0;
|
|
168
|
+
|
|
169
|
+
// add whitespace after previous and before this token
|
|
170
|
+
while (position < it_before_token && *position) {
|
|
171
|
+
if (*position == '\n') {
|
|
172
|
+
++ before_token.line;
|
|
173
|
+
before_token.column = 0;
|
|
174
|
+
} else {
|
|
175
|
+
++ before_token.column;
|
|
166
176
|
}
|
|
177
|
+
++position;
|
|
178
|
+
}
|
|
167
179
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
lexed = Token(after_whitespace, after_token);
|
|
180
|
+
// copy position
|
|
181
|
+
after_token = before_token;
|
|
171
182
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
183
|
+
Offset size(0, 0);
|
|
184
|
+
|
|
185
|
+
// increase position to include current token
|
|
186
|
+
while (position < it_after_token && *position) {
|
|
187
|
+
if (*position == '\n') {
|
|
188
|
+
++ size.line;
|
|
189
|
+
size.column = 0;
|
|
190
|
+
} else {
|
|
191
|
+
++ size.column;
|
|
192
|
+
}
|
|
193
|
+
++position;
|
|
176
194
|
}
|
|
195
|
+
|
|
196
|
+
after_token = after_token + size;
|
|
197
|
+
|
|
198
|
+
// create parsed token string (public member)
|
|
199
|
+
lexed = Token(wspace_start, it_before_token, it_after_token, optional_spaces_and_comments(it_after_token) ? optional_spaces_and_comments(it_after_token) : it_after_token, before_token);
|
|
200
|
+
Position pos(before_token.file, before_token.line, before_token.column);
|
|
201
|
+
pstate = ParserState(path, lexed, pos, size);
|
|
202
|
+
|
|
203
|
+
// advance internal char iterator
|
|
204
|
+
return position = it_after_token;
|
|
205
|
+
|
|
177
206
|
}
|
|
178
207
|
|
|
179
208
|
#ifdef __clang__
|
|
@@ -182,7 +211,7 @@ namespace Sass {
|
|
|
182
211
|
|
|
183
212
|
#endif
|
|
184
213
|
|
|
185
|
-
void error(string msg, Position pos
|
|
214
|
+
void error(string msg, Position pos);
|
|
186
215
|
void read_bom();
|
|
187
216
|
|
|
188
217
|
Block* parse();
|
|
@@ -194,7 +223,7 @@ namespace Sass {
|
|
|
194
223
|
Arguments* parse_arguments();
|
|
195
224
|
Argument* parse_argument();
|
|
196
225
|
Assignment* parse_assignment();
|
|
197
|
-
Propset* parse_propset();
|
|
226
|
+
// Propset* parse_propset();
|
|
198
227
|
Ruleset* parse_ruleset(Selector_Lookahead lookahead);
|
|
199
228
|
Selector_Schema* parse_selector_schema(const char* end_of_selector);
|
|
200
229
|
Selector_List* parse_selector_group();
|
|
@@ -205,6 +234,7 @@ namespace Sass {
|
|
|
205
234
|
Simple_Selector* parse_pseudo_selector();
|
|
206
235
|
Attribute_Selector* parse_attribute_selector();
|
|
207
236
|
Block* parse_block();
|
|
237
|
+
bool parse_number_prefix();
|
|
208
238
|
Declaration* parse_declaration();
|
|
209
239
|
Expression* parse_map_value();
|
|
210
240
|
Expression* parse_map();
|
|
@@ -221,14 +251,14 @@ namespace Sass {
|
|
|
221
251
|
Function_Call* parse_calc_function();
|
|
222
252
|
Function_Call* parse_function_call();
|
|
223
253
|
Function_Call_Schema* parse_function_call_schema();
|
|
224
|
-
String* parse_interpolated_chunk(Token);
|
|
254
|
+
String* parse_interpolated_chunk(Token, bool constant = false);
|
|
225
255
|
String* parse_string();
|
|
226
256
|
String_Constant* parse_static_value();
|
|
227
257
|
String* parse_ie_property();
|
|
228
258
|
String* parse_ie_keyword_arg();
|
|
229
|
-
String_Schema* parse_value_schema();
|
|
259
|
+
String_Schema* parse_value_schema(const char* stop);
|
|
230
260
|
String* parse_identifier_schema();
|
|
231
|
-
String_Schema* parse_url_schema();
|
|
261
|
+
// String_Schema* parse_url_schema();
|
|
232
262
|
If* parse_if_directive(bool else_if = false);
|
|
233
263
|
For* parse_for_directive();
|
|
234
264
|
Each* parse_each_directive();
|
|
@@ -245,6 +275,8 @@ namespace Sass {
|
|
|
245
275
|
Feature_Query_Condition* parse_supports_conjunction();
|
|
246
276
|
Feature_Query_Condition* parse_supports_disjunction();
|
|
247
277
|
Feature_Query_Condition* parse_supports_declaration();
|
|
278
|
+
At_Root_Block* parse_at_root_block();
|
|
279
|
+
At_Root_Expression* parse_at_root_expression();
|
|
248
280
|
At_Rule* parse_at_rule();
|
|
249
281
|
Warning* parse_warning();
|
|
250
282
|
Error* parse_error();
|
|
@@ -262,3 +294,5 @@ namespace Sass {
|
|
|
262
294
|
|
|
263
295
|
size_t check_bom_chars(const char* src, const char *end, const unsigned char* bom, size_t len);
|
|
264
296
|
}
|
|
297
|
+
|
|
298
|
+
#endif
|
data/ext/libsass/paths.hpp
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
#
|
|
2
|
-
#
|
|
1
|
+
#ifndef SASS_PATHS_H
|
|
2
|
+
#define SASS_PATHS_H
|
|
3
|
+
|
|
3
4
|
#include <string>
|
|
5
|
+
#include <vector>
|
|
4
6
|
#include <sstream>
|
|
7
|
+
#include <iostream>
|
|
5
8
|
|
|
6
9
|
using namespace std;
|
|
7
10
|
|
|
@@ -67,3 +70,5 @@ namespace Sass {
|
|
|
67
70
|
}
|
|
68
71
|
|
|
69
72
|
}
|
|
73
|
+
|
|
74
|
+
#endif
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
#ifdef _WIN32
|
|
2
|
+
#include <windows.h>
|
|
3
|
+
#else
|
|
4
|
+
#include <sys/types.h>
|
|
5
|
+
#include <dirent.h>
|
|
6
|
+
#include <errno.h>
|
|
7
|
+
#include <dlfcn.h>
|
|
8
|
+
#endif
|
|
9
|
+
|
|
10
|
+
#include <iostream>
|
|
11
|
+
#include "output.hpp"
|
|
12
|
+
#include "plugins.hpp"
|
|
13
|
+
|
|
14
|
+
#define npos string::npos
|
|
15
|
+
|
|
16
|
+
namespace Sass {
|
|
17
|
+
|
|
18
|
+
Plugins::Plugins(void) { }
|
|
19
|
+
Plugins::~Plugins(void) { }
|
|
20
|
+
|
|
21
|
+
// check if plugin is compatible with this version
|
|
22
|
+
// plugins may be linked static against libsass
|
|
23
|
+
// we try to be compatible between major versions
|
|
24
|
+
inline bool compatibility(const char* their_version)
|
|
25
|
+
{
|
|
26
|
+
// const char* their_version = "3.1.2";
|
|
27
|
+
// first check if anyone has an unknown version
|
|
28
|
+
const char* our_version = libsass_version();
|
|
29
|
+
if (!strcmp(their_version, "[na]")) return false;
|
|
30
|
+
if (!strcmp(our_version, "[na]")) return false;
|
|
31
|
+
|
|
32
|
+
// find the position of the second dot
|
|
33
|
+
size_t pos = string(our_version).find('.', 0);
|
|
34
|
+
if (pos != npos) pos = string(our_version).find('.', pos + 1);
|
|
35
|
+
|
|
36
|
+
// if we do not have two dots we fallback to compare complete string
|
|
37
|
+
if (pos == npos) { return strcmp(their_version, our_version) ? 0 : 1; }
|
|
38
|
+
// otherwise only compare up to the second dot (major versions)
|
|
39
|
+
else { return strncmp(their_version, our_version, pos) ? 0 : 1; }
|
|
40
|
+
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// load one specific plugin
|
|
44
|
+
bool Plugins::load_plugin (const string& path)
|
|
45
|
+
{
|
|
46
|
+
|
|
47
|
+
typedef const char* (*__plugin_version__)(void);
|
|
48
|
+
typedef Sass_C_Function_List (*__plugin_load_fns__)(void);
|
|
49
|
+
|
|
50
|
+
if (LOAD_LIB(plugin, path))
|
|
51
|
+
{
|
|
52
|
+
// try to load initial function to query libsass version suppor
|
|
53
|
+
if (LOAD_LIB_FN(__plugin_version__, plugin_version, "libsass_get_version"))
|
|
54
|
+
{
|
|
55
|
+
// get the libsass version of the plugin
|
|
56
|
+
if (!compatibility(plugin_version())) return false;
|
|
57
|
+
// try to get import address for "libsass_load_functions"
|
|
58
|
+
if (LOAD_LIB_FN(__plugin_load_fns__, plugin_load_functions, "libsass_load_functions"))
|
|
59
|
+
{
|
|
60
|
+
Sass_C_Function_List fns = plugin_load_functions();
|
|
61
|
+
while (fns && *fns) { functions.push_back(*fns); ++ fns; }
|
|
62
|
+
}
|
|
63
|
+
// success
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
else
|
|
67
|
+
{
|
|
68
|
+
// print debug message to stderr (should not happen)
|
|
69
|
+
cerr << "failed loading 'libsass_support' in <" << path << ">" << endl;
|
|
70
|
+
if (const char* dlsym_error = dlerror()) cerr << dlsym_error << endl;
|
|
71
|
+
CLOSE_LIB(plugin);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
else
|
|
75
|
+
{
|
|
76
|
+
// print debug message to stderr (should not happen)
|
|
77
|
+
cerr << "failed loading plugin <" << path << ">" << endl;
|
|
78
|
+
if (const char* dlopen_error = dlerror()) cerr << dlopen_error << endl;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return false;
|
|
82
|
+
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
size_t Plugins::load_plugins(const string& path)
|
|
86
|
+
{
|
|
87
|
+
|
|
88
|
+
// count plugins
|
|
89
|
+
size_t loaded = 0;
|
|
90
|
+
|
|
91
|
+
#ifdef _WIN32
|
|
92
|
+
|
|
93
|
+
try
|
|
94
|
+
{
|
|
95
|
+
|
|
96
|
+
// use wchar (utf16)
|
|
97
|
+
WIN32_FIND_DATAW data;
|
|
98
|
+
// trailing slash is guaranteed
|
|
99
|
+
string globsrch(path + "*.dll");
|
|
100
|
+
// convert to wide chars (utf16) for system call
|
|
101
|
+
wstring wglobsrch(UTF_8::convert_to_utf16(globsrch));
|
|
102
|
+
HANDLE hFile = FindFirstFileW(wglobsrch.c_str(), &data);
|
|
103
|
+
// check if system called returned a result
|
|
104
|
+
// ToDo: maybe we should print a debug message
|
|
105
|
+
if (hFile == INVALID_HANDLE_VALUE) return -1;
|
|
106
|
+
|
|
107
|
+
// read directory
|
|
108
|
+
while (true)
|
|
109
|
+
{
|
|
110
|
+
try
|
|
111
|
+
{
|
|
112
|
+
// the system will report the filenames with wide chars (utf16)
|
|
113
|
+
string entry = UTF_8::convert_from_utf16(data.cFileName);
|
|
114
|
+
// check if file ending matches exactly
|
|
115
|
+
if (!ends_with(entry, ".dll")) continue;
|
|
116
|
+
// load the plugin and increase counter
|
|
117
|
+
if (load_plugin(path + entry)) ++ loaded;
|
|
118
|
+
// check if there should be more entries
|
|
119
|
+
if (GetLastError() == ERROR_NO_MORE_FILES) break;
|
|
120
|
+
// load next entry (check for return type)
|
|
121
|
+
if (!FindNextFileW(hFile, &data)) break;
|
|
122
|
+
}
|
|
123
|
+
catch (...)
|
|
124
|
+
{
|
|
125
|
+
// report the error to the console (should not happen)
|
|
126
|
+
// seems like we got strange data from the system call?
|
|
127
|
+
cerr << "filename in plugin path has invalid utf8?" << endl;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
catch (utf8::invalid_utf8)
|
|
132
|
+
{
|
|
133
|
+
// report the error to the console (should not happen)
|
|
134
|
+
// implementors should make sure to provide valid utf8
|
|
135
|
+
cerr << "plugin path contains invalid utf8" << endl;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
#else
|
|
139
|
+
|
|
140
|
+
DIR *dp;
|
|
141
|
+
struct dirent *dirp;
|
|
142
|
+
if((dp = opendir(path.c_str())) == NULL) return -1;
|
|
143
|
+
while ((dirp = readdir(dp)) != NULL) {
|
|
144
|
+
if (!ends_with(dirp->d_name, ".so")) continue;
|
|
145
|
+
if (load_plugin(path + dirp->d_name)) ++ loaded;
|
|
146
|
+
}
|
|
147
|
+
closedir(dp);
|
|
148
|
+
|
|
149
|
+
#endif
|
|
150
|
+
return loaded;
|
|
151
|
+
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
}
|
|
155
|
+
|