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.
Files changed (111) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +1 -1
  3. data/ext/libsass/.gitignore +13 -6
  4. data/ext/libsass/Makefile +42 -26
  5. data/ext/libsass/Makefile.am +43 -30
  6. data/ext/libsass/Readme.md +4 -2
  7. data/ext/libsass/appveyor.yml +10 -14
  8. data/ext/libsass/ast.cpp +54 -44
  9. data/ext/libsass/ast.hpp +404 -236
  10. data/ext/libsass/ast_def_macros.hpp +5 -0
  11. data/ext/libsass/ast_factory.hpp +6 -3
  12. data/ext/libsass/ast_fwd_decl.hpp +12 -0
  13. data/ext/libsass/b64/encode.h +2 -2
  14. data/ext/libsass/backtrace.hpp +13 -17
  15. data/ext/libsass/base64vlq.hpp +4 -1
  16. data/ext/libsass/bind.cpp +12 -15
  17. data/ext/libsass/bind.hpp +6 -6
  18. data/ext/libsass/color_names.hpp +4 -1
  19. data/ext/libsass/configure.ac +7 -21
  20. data/ext/libsass/constants.cpp +6 -4
  21. data/ext/libsass/constants.hpp +10 -4
  22. data/ext/libsass/context.cpp +89 -58
  23. data/ext/libsass/context.hpp +28 -35
  24. data/ext/libsass/contextualize.cpp +20 -10
  25. data/ext/libsass/contextualize.hpp +8 -23
  26. data/ext/libsass/contrib/libsass.spec +66 -0
  27. data/ext/libsass/cssize.cpp +547 -0
  28. data/ext/libsass/cssize.hpp +82 -0
  29. data/ext/libsass/debug.hpp +3 -3
  30. data/ext/libsass/debugger.hpp +358 -0
  31. data/ext/libsass/emitter.cpp +255 -0
  32. data/ext/libsass/emitter.hpp +83 -0
  33. data/ext/libsass/environment.hpp +7 -3
  34. data/ext/libsass/error_handling.cpp +11 -14
  35. data/ext/libsass/error_handling.hpp +9 -7
  36. data/ext/libsass/eval.cpp +253 -161
  37. data/ext/libsass/eval.hpp +13 -13
  38. data/ext/libsass/expand.cpp +135 -64
  39. data/ext/libsass/expand.hpp +11 -13
  40. data/ext/libsass/extend.cpp +66 -20
  41. data/ext/libsass/extend.hpp +6 -11
  42. data/ext/libsass/file.cpp +31 -26
  43. data/ext/libsass/file.hpp +6 -1
  44. data/ext/libsass/functions.cpp +270 -287
  45. data/ext/libsass/functions.hpp +8 -11
  46. data/ext/libsass/inspect.cpp +385 -255
  47. data/ext/libsass/inspect.hpp +15 -26
  48. data/ext/libsass/kwd_arg_macros.hpp +5 -0
  49. data/ext/libsass/mapping.hpp +4 -3
  50. data/ext/libsass/memory_manager.hpp +5 -2
  51. data/ext/libsass/node.cpp +50 -50
  52. data/ext/libsass/node.hpp +26 -27
  53. data/ext/libsass/operation.hpp +15 -4
  54. data/ext/libsass/output.cpp +401 -0
  55. data/ext/libsass/output.hpp +56 -0
  56. data/ext/libsass/parser.cpp +573 -399
  57. data/ext/libsass/parser.hpp +122 -88
  58. data/ext/libsass/paths.hpp +7 -2
  59. data/ext/libsass/plugins.cpp +155 -0
  60. data/ext/libsass/plugins.hpp +56 -0
  61. data/ext/libsass/position.cpp +128 -0
  62. data/ext/libsass/position.hpp +108 -11
  63. data/ext/libsass/prelexer.cpp +184 -110
  64. data/ext/libsass/prelexer.hpp +131 -24
  65. data/ext/libsass/remove_placeholders.cpp +1 -1
  66. data/ext/libsass/remove_placeholders.hpp +6 -6
  67. data/ext/libsass/sass.cpp +3 -3
  68. data/ext/libsass/sass.h +12 -4
  69. data/ext/libsass/sass2scss.cpp +3 -2
  70. data/ext/libsass/sass2scss.h +5 -0
  71. data/ext/libsass/sass_context.cpp +136 -37
  72. data/ext/libsass/sass_context.h +19 -10
  73. data/ext/libsass/sass_functions.cpp +29 -2
  74. data/ext/libsass/sass_functions.h +8 -2
  75. data/ext/libsass/sass_interface.cpp +32 -23
  76. data/ext/libsass/sass_interface.h +9 -4
  77. data/ext/libsass/sass_util.cpp +19 -23
  78. data/ext/libsass/sass_util.hpp +28 -27
  79. data/ext/libsass/sass_values.cpp +6 -4
  80. data/ext/libsass/sass_values.h +3 -3
  81. data/ext/libsass/script/ci-build-libsass +13 -1
  82. data/ext/libsass/script/ci-report-coverage +2 -1
  83. data/ext/libsass/source_map.cpp +79 -28
  84. data/ext/libsass/source_map.hpp +35 -16
  85. data/ext/libsass/subset_map.hpp +6 -4
  86. data/ext/libsass/to_c.hpp +4 -4
  87. data/ext/libsass/to_string.cpp +13 -8
  88. data/ext/libsass/to_string.hpp +6 -4
  89. data/ext/libsass/units.cpp +2 -1
  90. data/ext/libsass/units.hpp +6 -1
  91. data/ext/libsass/utf8_string.cpp +0 -5
  92. data/ext/libsass/utf8_string.hpp +3 -2
  93. data/ext/libsass/util.cpp +461 -49
  94. data/ext/libsass/util.hpp +34 -13
  95. data/ext/libsass/version.sh +10 -0
  96. data/ext/libsass/win/libsass.filters +20 -11
  97. data/ext/libsass/win/libsass.vcxproj +11 -8
  98. data/lib/sassc/importer.rb +1 -8
  99. data/lib/sassc/native.rb +7 -0
  100. data/lib/sassc/native/native_context_api.rb +5 -5
  101. data/lib/sassc/version.rb +1 -1
  102. data/test/native_test.rb +1 -1
  103. metadata +14 -10
  104. data/ext/libsass/copy_c_str.cpp +0 -13
  105. data/ext/libsass/copy_c_str.hpp +0 -5
  106. data/ext/libsass/output_compressed.cpp +0 -401
  107. data/ext/libsass/output_compressed.hpp +0 -95
  108. data/ext/libsass/output_nested.cpp +0 -364
  109. data/ext/libsass/output_nested.hpp +0 -108
  110. data/ext/libsass/test-driver +0 -127
  111. data/ext/libsass/token.hpp +0 -32
@@ -1,29 +1,15 @@
1
- #define SASS_PARSER
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
- #endif
25
-
26
- #include <iostream>
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
- string path;
53
- size_t column;
54
- Position source_position;
40
+ Position before_token;
41
+ Position after_token;
42
+ ParserState pstate;
43
+ int indentation;
55
44
 
56
45
 
57
46
  Token lexed;
58
- bool dequote;
47
+ bool in_at_root;
59
48
 
60
- Parser(Context& ctx, string path, Position source_position)
61
- : ctx(ctx), stack(vector<Syntactic_Context>()),
62
- source(0), position(0), end(0), path(path), column(1), source_position(source_position)
63
- { dequote = false; stack.push_back(nothing); }
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, string path = "", Position source_position = Position());
66
- static Parser from_c_str(const char* src, Context& ctx, string path = "", Position source_position = Position());
67
- static Parser from_token(Token t, Context& ctx, string path = "", Position source_position = Position());
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* after_whitespace;
78
+ const char* it_before_token;
86
79
  if (mx == block_comment) {
87
- after_whitespace = // start;
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
- after_whitespace = position;
84
+ it_before_token = position;
92
85
  }
93
- else if (mx == spaces || mx == ancestor_of) {
94
- after_whitespace = mx(start);
95
- if (after_whitespace) {
96
- return after_whitespace;
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
- after_whitespace = optional_spaces(start);
96
+ it_before_token = optional_spaces(start);
104
97
  }
105
98
  else if (mx == line_comment_prefix || mx == block_comment_prefix) {
106
- after_whitespace = position;
99
+ it_before_token = position;
107
100
  }
108
101
  else {
109
- after_whitespace = spaces_and_comments(start);
102
+ it_before_token = optional_spaces_and_comments(start);
110
103
  }
111
- const char* after_token = mx(after_whitespace);
112
- if (after_token) {
113
- return after_token;
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
- const char* after_whitespace;
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
- after_whitespace = // position;
126
- zero_plus< alternatives<spaces, line_comment> >(position);
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
- after_whitespace = position;
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
- after_whitespace = spaces(position);
136
- if (after_whitespace) {
137
- source_position.line += count_interval<'\n'>(position, after_whitespace);
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
- after_whitespace = optional_spaces(position);
156
+ // ToDo: what are optiona_spaces ???
157
+ it_before_token = optional_spaces(position);
147
158
  }
148
159
  else {
149
- after_whitespace = spaces_and_comments(position);
160
+ // most can be preceded by spaces and comments
161
+ it_before_token = optional_spaces_and_comments(position);
150
162
  }
151
- const char* after_token = mx(after_whitespace);
152
- if (after_token) {
153
- size_t previous_line = source_position.line;
154
- source_position.line += count_interval<'\n'>(position, after_token);
155
-
156
- size_t whitespace = 0;
157
- const char* ptr = after_whitespace - 1;
158
- while (ptr >= position) {
159
- if (*ptr == '\n')
160
- break;
161
- whitespace++;
162
- ptr--;
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
- source_position.column = column + whitespace;
169
- column += after_token - after_whitespace + whitespace;
170
- lexed = Token(after_whitespace, after_token);
180
+ // copy position
181
+ after_token = before_token;
171
182
 
172
- return position = after_token;
173
- }
174
- else {
175
- return 0;
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 = Position());
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
@@ -1,7 +1,10 @@
1
- #include <vector>
2
- #include <iostream>
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
+