sassc 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
|