Skip to content

Commit 4f8bdd2

Browse files
committed
Implement capture_stderr C-API option
As an embeddable library we should try to play nice with our parents resources. It is therefore desirable to have a way to capture messages on stderr. This makes it easier and safer to use libsass in eg. threaded environments. Core errors (mainly memory allocation problems) and dev/debug data is still printed to stderr directly.
1 parent 28bbd0e commit 4f8bdd2

15 files changed

+129
-47
lines changed

docs/api-context-internal.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ struct Sass_Options : Sass_Output_Options {
5151
// Treat source_string as sass (as opposed to scss)
5252
bool is_indented_syntax_src;
5353

54+
// If this options is set, nothing will be printed to stderr anymore
55+
// The aggregated output on stderr can be fetched via stderr_string
56+
bool suppress_stderr;
57+
5458
// The input path is used for source map
5559
// generation. It can be used to define
5660
// something with string compilation or to
@@ -105,6 +109,9 @@ struct Sass_Context : Sass_Options
105109
// generated output data
106110
char* output_string;
107111

112+
// messages on stderr
113+
char* stderr_string;
114+
108115
// generated source map json
109116
char* source_map_string;
110117

docs/api-context.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ bool omit_source_map_url;
4646
bool is_indented_syntax_src;
4747
```
4848
```C
49+
// If this options is set, nothing will be printed to stderr anymore
50+
// The aggregated output on stderr can be fetched via stderr_string
51+
bool suppress_stderr;
52+
```
53+
```C
4954
// The input path is used for source map
5055
// generating. It can be used to define
5156
// something with string compilation or to
@@ -111,6 +116,10 @@ enum Sass_Input_Style type;
111116
char* output_string;
112117
```
113118
```C
119+
// messages on stderr
120+
char* stderr_string;
121+
```
122+
```C
114123
// generated source map json
115124
char* source_map_string;
116125
```
@@ -197,6 +206,7 @@ void sass_data_context_set_options (struct Sass_Data_Context* data_ctx, struct S
197206

198207
// Getters for Sass_Context values
199208
const char* sass_context_get_output_string (struct Sass_Context* ctx);
209+
const char* sass_context_get_stderr_string (struct Sass_Context* ctx);
200210
int sass_context_get_error_status (struct Sass_Context* ctx);
201211
const char* sass_context_get_error_json (struct Sass_Context* ctx);
202212
const char* sass_context_get_error_text (struct Sass_Context* ctx);
@@ -262,6 +272,7 @@ void sass_option_set_source_map_contents (struct Sass_Options* options, bool sou
262272
void sass_option_set_source_map_file_urls (struct Sass_Options* options, bool source_map_file_urls);
263273
void sass_option_set_omit_source_map_url (struct Sass_Options* options, bool omit_source_map_url);
264274
void sass_option_set_is_indented_syntax_src (struct Sass_Options* options, bool is_indented_syntax_src);
275+
void sass_option_set_suppress_stderr (struct Sass_Options* options, bool suppress_stderr);
265276
void sass_option_set_indent (struct Sass_Options* options, const char* indent);
266277
void sass_option_set_linefeed (struct Sass_Options* options, const char* linefeed);
267278
void sass_option_set_input_path (struct Sass_Options* options, const char* input_path);

include/sass/context.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ ADDAPI void ADDCALL sass_option_set_source_map_contents (struct Sass_Options* op
9696
ADDAPI void ADDCALL sass_option_set_source_map_file_urls (struct Sass_Options* options, bool source_map_file_urls);
9797
ADDAPI void ADDCALL sass_option_set_omit_source_map_url (struct Sass_Options* options, bool omit_source_map_url);
9898
ADDAPI void ADDCALL sass_option_set_is_indented_syntax_src (struct Sass_Options* options, bool is_indented_syntax_src);
99+
ADDAPI void ADDCALL sass_option_set_suppress_stderr (struct Sass_Options* options, bool suppress_stderr);
99100
ADDAPI void ADDCALL sass_option_set_indent (struct Sass_Options* options, const char* indent);
100101
ADDAPI void ADDCALL sass_option_set_linefeed (struct Sass_Options* options, const char* linefeed);
101102
ADDAPI void ADDCALL sass_option_set_input_path (struct Sass_Options* options, const char* input_path);
@@ -111,6 +112,7 @@ ADDAPI void ADDCALL sass_option_set_c_functions (struct Sass_Options* options, S
111112

112113
// Getters for Sass_Context values
113114
ADDAPI const char* ADDCALL sass_context_get_output_string (struct Sass_Context* ctx);
115+
ADDAPI const char* ADDCALL sass_context_get_stderr_string (struct Sass_Context* ctx);
114116
ADDAPI int ADDCALL sass_context_get_error_status (struct Sass_Context* ctx);
115117
ADDAPI const char* ADDCALL sass_context_get_error_json (struct Sass_Context* ctx);
116118
ADDAPI const char* ADDCALL sass_context_get_error_text (struct Sass_Context* ctx);

src/bind.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111

1212
namespace Sass {
1313

14-
void bind(std::string type, std::string name, Parameters_Obj ps, Arguments_Obj as, Env* env, Eval* eval, Backtraces& traces)
14+
void bind(std::string type, std::string name, Parameters_Obj ps, Arguments_Obj as, Context* ctx, Env* env, Eval* eval, Backtraces& traces)
1515
{
1616
std::string callee(type + " " + name);
1717

@@ -194,7 +194,9 @@ namespace Sass {
194194
msg << (LP == 1 ? " argument" : " arguments");
195195
msg << " but " << arg_count;
196196
msg << (arg_count == 1 ? " was passed" : " were passed.");
197-
deprecated_bind(msg.str(), as->pstate());
197+
// ToDo: we only need ctx here to capture the message on stderr
198+
// ToDo: once deprecation is gone, remove it from method args
199+
ctx->print_stderr(deprecated_bind(msg.str(), as->pstate()));
198200

199201
while (arglist->length() > LP - ip) {
200202
arglist->elements().erase(arglist->elements().end() - 1);

src/bind.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
namespace Sass {
1010

11-
void bind(std::string type, std::string name, Parameters_Obj, Arguments_Obj, Env*, Eval*, Backtraces& traces);
11+
void bind(std::string type, std::string name, Parameters_Obj, Arguments_Obj, Context* ctx, Env*, Eval*, Backtraces& traces);
1212

1313
}
1414

src/context.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,8 @@ namespace Sass {
7676
head_imports(0),
7777
plugins(),
7878
emitter(c_options),
79+
CERR(std::cerr),
80+
STDERR(),
7981

8082
ast_gc(),
8183
strings(),
@@ -142,6 +144,14 @@ namespace Sass {
142144
sort (c_importers.begin(), c_importers.end(), sort_importers);
143145
}
144146

147+
void Context::print_stderr(const std::string& msg)
148+
{
149+
STDERR << msg;
150+
if (!c_options.suppress_stderr) {
151+
CERR << msg;
152+
}
153+
}
154+
145155
Context::~Context()
146156
{
147157
// resources were allocated by malloc

src/context.hpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#define SASS_CONTEXT_H
33

44
#include <string>
5+
#include <sstream>
56
#include <vector>
67
#include <map>
78

@@ -44,6 +45,9 @@ namespace Sass {
4445
Plugins plugins;
4546
Output emitter;
4647

48+
std::ostream& CERR;
49+
std::ostringstream STDERR;
50+
4751
// generic ast node garbage container
4852
// used to avoid possible circular refs
4953
CallStack ast_gc;
@@ -104,6 +108,8 @@ namespace Sass {
104108
Sass_Output_Style output_style() { return c_options.output_style; };
105109
std::vector<std::string> get_included_files(bool skip = false, size_t headers = 0);
106110

111+
void print_stderr(const std::string& msg);
112+
107113
private:
108114
void collect_plugin_paths(const char* paths_str);
109115
void collect_plugin_paths(string_list* paths_array);

src/error_handling.cpp

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -134,66 +134,77 @@ namespace Sass {
134134

135135
}
136136

137-
138-
void warn(std::string msg, ParserState pstate)
137+
std::string warn(std::string msg, ParserState pstate)
139138
{
140-
std::cerr << "Warning: " << msg << std::endl;
139+
std::ostringstream sstrm;
140+
sstrm << "Warning: " << msg << std::endl;
141+
return sstrm.str();
141142
}
142143

143-
void warning(std::string msg, ParserState pstate)
144+
std::string warning(std::string msg, ParserState pstate)
144145
{
145146
std::string cwd(Sass::File::get_cwd());
146147
std::string abs_path(Sass::File::rel2abs(pstate.path, cwd, cwd));
147148
std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
148149
std::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.path));
149150

150-
std::cerr << "WARNING on line " << pstate.line+1 << ", column " << pstate.column+1 << " of " << output_path << ":" << std::endl;
151-
std::cerr << msg << std::endl << std::endl;
151+
std::ostringstream sstrm;
152+
sstrm << "WARNING on line " << pstate.line + 1;
153+
sstrm << ", column " << pstate.column + 1;
154+
sstrm << " of " << output_path << std::endl;
155+
sstrm << msg << std::endl;
156+
sstrm << std::endl;
157+
return sstrm.str();
152158
}
153159

154-
void warn(std::string msg, ParserState pstate, Backtrace* bt)
160+
std::string warn(std::string msg, ParserState pstate, Backtrace* bt)
155161
{
156-
warn(msg, pstate);
162+
return warn(msg, pstate);
157163
}
158164

159-
void deprecated_function(std::string msg, ParserState pstate)
165+
std::string deprecated_function(std::string msg, ParserState pstate)
160166
{
161167
std::string cwd(Sass::File::get_cwd());
162168
std::string abs_path(Sass::File::rel2abs(pstate.path, cwd, cwd));
163169
std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
164170
std::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.path));
165171

166-
std::cerr << "DEPRECATION WARNING: " << msg << std::endl;
167-
std::cerr << "will be an error in future versions of Sass." << std::endl;
168-
std::cerr << " on line " << pstate.line+1 << " of " << output_path << std::endl;
172+
std::ostringstream sstrm;
173+
sstrm << "DEPRECATION WARNING: " << msg << std::endl;
174+
sstrm << "will be an error in future versions of Sass." << std::endl;
175+
sstrm << " on line " << pstate.line+1 << " of " << output_path << std::endl;
176+
return sstrm.str();
169177
}
170178

171-
void deprecated(std::string msg, std::string msg2, bool with_column, ParserState pstate)
179+
std::string deprecated(std::string msg, std::string msg2, bool with_column, ParserState pstate)
172180
{
173181
std::string cwd(Sass::File::get_cwd());
174182
std::string abs_path(Sass::File::rel2abs(pstate.path, cwd, cwd));
175183
std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
176184
std::string output_path(Sass::File::path_for_console(rel_path, pstate.path, pstate.path));
177185

178-
std::cerr << "DEPRECATION WARNING on line " << pstate.line + 1;
179-
if (with_column) std::cerr << ", column " << pstate.column + pstate.offset.column + 1;
180-
if (output_path.length()) std::cerr << " of " << output_path;
181-
std::cerr << ":" << std::endl;
182-
std::cerr << msg << std::endl;
183-
if (msg2.length()) std::cerr << msg2 << std::endl;
184-
std::cerr << std::endl;
186+
std::ostringstream sstrm;
187+
sstrm << "DEPRECATION WARNING on line " << pstate.line + 1;
188+
if (output_path.length()) sstrm << " of " << output_path;
189+
sstrm << ":" << std::endl;
190+
sstrm << msg << " and will be an error in future versions of Sass." << std::endl;
191+
if (msg2.length()) sstrm << msg2 << std::endl;
192+
sstrm << std::endl;
193+
return sstrm.str();
185194
}
186195

187-
void deprecated_bind(std::string msg, ParserState pstate)
196+
std::string deprecated_bind(std::string msg, ParserState pstate)
188197
{
189198
std::string cwd(Sass::File::get_cwd());
190199
std::string abs_path(Sass::File::rel2abs(pstate.path, cwd, cwd));
191200
std::string rel_path(Sass::File::abs2rel(pstate.path, cwd, cwd));
192201
std::string output_path(Sass::File::path_for_console(rel_path, abs_path, pstate.path));
193202

194-
std::cerr << "WARNING: " << msg << std::endl;
195-
std::cerr << " on line " << pstate.line+1 << " of " << output_path << std::endl;
196-
std::cerr << "This will be an error in future versions of Sass." << std::endl;
203+
std::ostringstream sstrm;
204+
sstrm << "WARNING: " << msg << std::endl;
205+
sstrm << " on line " << pstate.line+1 << " of " << output_path << std::endl;
206+
sstrm << "This will be an error in future versions of Sass." << std::endl;
207+
return sstrm.str();
197208
}
198209

199210
// should be replaced with error with backtraces

src/error_handling.hpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -212,14 +212,13 @@ namespace Sass {
212212

213213
}
214214

215-
void warn(std::string msg, ParserState pstate);
216-
void warn(std::string msg, ParserState pstate, Backtrace* bt);
217-
void warning(std::string msg, ParserState pstate);
218-
219-
void deprecated_function(std::string msg, ParserState pstate);
220-
void deprecated(std::string msg, std::string msg2, bool with_column, ParserState pstate);
221-
void deprecated_bind(std::string msg, ParserState pstate);
222-
// void deprecated(std::string msg, ParserState pstate, Backtrace* bt);
215+
std::string warn(std::string msg, ParserState pstate);
216+
std::string warn(std::string msg, ParserState pstate, Backtrace* bt);
217+
std::string warning(std::string msg, ParserState pstate);
218+
219+
std::string deprecated_function(std::string msg, ParserState pstate);
220+
std::string deprecated(std::string msg, std::string msg2, bool with_column, ParserState pstate);
221+
std::string deprecated_bind(std::string msg, ParserState pstate);
223222

224223
void coreError(std::string msg, ParserState pstate);
225224
void error(std::string msg, ParserState pstate, Backtraces& traces);

src/eval.cpp

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -389,9 +389,11 @@ namespace Sass {
389389

390390
std::string result(unquote(message->to_sass()));
391391
std::cerr << "WARNING: " << result << std::endl;
392+
std::ostringstream sstrm;
392393
traces.push_back(Backtrace(w->pstate()));
393-
std::cerr << traces_to_string(traces, " ");
394-
std::cerr << std::endl;
394+
sstrm << traces_to_string(traces, " ");
395+
sstrm << std::endl;
396+
ctx.print_stderr(sstrm.str());
395397
options().output_style = outstyle;
396398
traces.pop_back();
397399
return 0;
@@ -485,8 +487,11 @@ namespace Sass {
485487
std::string output_path(Sass::File::path_for_console(rel_path, abs_path, d->pstate().path));
486488
options().output_style = outstyle;
487489

488-
std::cerr << output_path << ":" << d->pstate().line+1 << " DEBUG: " << result;
489-
std::cerr << std::endl;
490+
std::ostringstream sstrm;
491+
sstrm << output_path << ":" << d->pstate().line+1 << " DEBUG: " << result;
492+
sstrm << std::endl;
493+
ctx.print_stderr(sstrm.str());
494+
490495
return 0;
491496
}
492497

@@ -1048,7 +1053,7 @@ namespace Sass {
10481053
env_stack().push_back(&fn_env);
10491054

10501055
if (func || body) {
1051-
bind(std::string("Function"), c->name(), params, args, &fn_env, this, traces);
1056+
bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this, traces);
10521057
std::string msg(", in function `" + c->name() + "`");
10531058
traces.push_back(Backtrace(c->pstate(), msg));
10541059
callee_stack().push_back({
@@ -1088,7 +1093,7 @@ namespace Sass {
10881093

10891094
// populates env with default values for params
10901095
std::string ff(c->name());
1091-
bind(std::string("Function"), c->name(), params, args, &fn_env, this, traces);
1096+
bind(std::string("Function"), c->name(), params, args, &ctx, &fn_env, this, traces);
10921097
std::string msg(", in function `" + c->name() + "`");
10931098
traces.push_back(Backtrace(c->pstate(), msg));
10941099
callee_stack().push_back({

0 commit comments

Comments
 (0)