/src/libsass/src/fn_utils.cpp
Line | Count | Source |
1 | | // sass.hpp must go before all system headers to get the |
2 | | // __EXTENSIONS__ fix on Solaris. |
3 | | #include "sass.hpp" |
4 | | |
5 | | #include "parser.hpp" |
6 | | #include "fn_utils.hpp" |
7 | | #include "util_string.hpp" |
8 | | |
9 | | namespace Sass { |
10 | | |
11 | | Definition* make_native_function(Signature sig, Native_Function func, Context& ctx) |
12 | 516 | { |
13 | 516 | SourceFile* source = SASS_MEMORY_NEW(SourceFile, "[built-in function]", sig, std::string::npos); |
14 | 516 | Parser sig_parser(source, ctx, ctx.traces); |
15 | 516 | sig_parser.lex<Prelexer::identifier>(); |
16 | 516 | sass::string name(Util::normalize_underscores(sig_parser.lexed)); |
17 | 516 | Parameters_Obj params = sig_parser.parse_parameters(); |
18 | 516 | return SASS_MEMORY_NEW(Definition, |
19 | 516 | SourceSpan(source), |
20 | 516 | sig, |
21 | 516 | name, |
22 | 516 | params, |
23 | 516 | func, |
24 | 516 | false); |
25 | 516 | } |
26 | | |
27 | | Definition* make_c_function(Sass_Function_Entry c_func, Context& ctx) |
28 | 0 | { |
29 | 0 | using namespace Prelexer; |
30 | 0 | const char* sig = sass_function_get_signature(c_func); |
31 | 0 | SourceFile* source = SASS_MEMORY_NEW(SourceFile, "[c function]", sig, std::string::npos); |
32 | 0 | Parser sig_parser(source, ctx, ctx.traces); |
33 | | // allow to overload generic callback plus @warn, @error and @debug with custom functions |
34 | 0 | sig_parser.lex < alternatives < identifier, exactly <'*'>, |
35 | 0 | exactly < Constants::warn_kwd >, |
36 | 0 | exactly < Constants::error_kwd >, |
37 | 0 | exactly < Constants::debug_kwd > |
38 | 0 | > >(); |
39 | 0 | sass::string name(Util::normalize_underscores(sig_parser.lexed)); |
40 | 0 | Parameters_Obj params = sig_parser.parse_parameters(); |
41 | 0 | return SASS_MEMORY_NEW(Definition, |
42 | 0 | SourceSpan(source), |
43 | 0 | sig, |
44 | 0 | name, |
45 | 0 | params, |
46 | 0 | c_func); |
47 | 0 | } |
48 | | |
49 | | namespace Functions { |
50 | | |
51 | | sass::string function_name(Signature sig) |
52 | 0 | { |
53 | 0 | sass::string str(sig); |
54 | 0 | return str.substr(0, str.find('(')); |
55 | 0 | } |
56 | | |
57 | | Map* get_arg_m(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces) |
58 | 0 | { |
59 | 0 | AST_Node* value = env[argname]; |
60 | 0 | if (Map* map = Cast<Map>(value)) return map; |
61 | 0 | List* list = Cast<List>(value); |
62 | 0 | if (list && list->length() == 0) { |
63 | 0 | return SASS_MEMORY_NEW(Map, pstate, 0); |
64 | 0 | } |
65 | 0 | return get_arg<Map>(argname, env, sig, pstate, traces); |
66 | 0 | } |
67 | | |
68 | | double get_arg_r(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, double lo, double hi) |
69 | 0 | { |
70 | 0 | Number* val = get_arg<Number>(argname, env, sig, pstate, traces); |
71 | 0 | Number tmpnr(val); |
72 | 0 | tmpnr.reduce(); |
73 | 0 | double v = tmpnr.value(); |
74 | 0 | if (!(lo <= v && v <= hi)) { |
75 | 0 | sass::ostream msg; |
76 | 0 | msg << "argument `" << argname << "` of `" << sig << "` must be between "; |
77 | 0 | msg << lo << " and " << hi; |
78 | 0 | error(msg.str(), pstate, traces); |
79 | 0 | } |
80 | 0 | return v; |
81 | 0 | } |
82 | | |
83 | | Number* get_arg_n(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces) |
84 | 0 | { |
85 | 0 | Number* val = get_arg<Number>(argname, env, sig, pstate, traces); |
86 | 0 | val = SASS_MEMORY_COPY(val); |
87 | 0 | val->reduce(); |
88 | 0 | return val; |
89 | 0 | } |
90 | | |
91 | | double get_arg_val(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces) |
92 | 0 | { |
93 | 0 | Number* val = get_arg<Number>(argname, env, sig, pstate, traces); |
94 | 0 | Number tmpnr(val); |
95 | 0 | tmpnr.reduce(); |
96 | 0 | return tmpnr.value(); |
97 | 0 | } |
98 | | |
99 | | double color_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces) |
100 | 0 | { |
101 | 0 | Number* val = get_arg<Number>(argname, env, sig, pstate, traces); |
102 | 0 | Number tmpnr(val); |
103 | 0 | tmpnr.reduce(); |
104 | 0 | if (tmpnr.unit() == "%") { |
105 | 0 | return std::min(std::max(tmpnr.value() * 255 / 100.0, 0.0), 255.0); |
106 | 0 | } else { |
107 | 0 | return std::min(std::max(tmpnr.value(), 0.0), 255.0); |
108 | 0 | } |
109 | 0 | } |
110 | | |
111 | 0 | double alpha_num(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces) { |
112 | 0 | Number* val = get_arg<Number>(argname, env, sig, pstate, traces); |
113 | 0 | Number tmpnr(val); |
114 | 0 | tmpnr.reduce(); |
115 | 0 | if (tmpnr.unit() == "%") { |
116 | 0 | return std::min(std::max(tmpnr.value(), 0.0), 100.0); |
117 | 0 | } else { |
118 | 0 | return std::min(std::max(tmpnr.value(), 0.0), 1.0); |
119 | 0 | } |
120 | 0 | } |
121 | | |
122 | 0 | SelectorListObj get_arg_sels(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx) { |
123 | 0 | ExpressionObj exp = ARG(argname, Expression); |
124 | 0 | if (exp->concrete_type() == Expression::NULL_VAL) { |
125 | 0 | sass::ostream msg; |
126 | 0 | msg << argname << ": null is not a valid selector: it must be a string,\n"; |
127 | 0 | msg << "a list of strings, or a list of lists of strings for `" << function_name(sig) << "'"; |
128 | 0 | error(msg.str(), exp->pstate(), traces); |
129 | 0 | } |
130 | 0 | if (String_Constant* str = Cast<String_Constant>(exp)) { |
131 | 0 | str->quote_mark(0); |
132 | 0 | } |
133 | 0 | sass::string exp_src = exp->to_string(ctx.c_options); |
134 | 0 | ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate()); |
135 | 0 | return Parser::parse_selector(source, ctx, traces, false); |
136 | 0 | } |
137 | | |
138 | 0 | CompoundSelectorObj get_arg_sel(const sass::string& argname, Env& env, Signature sig, SourceSpan pstate, Backtraces traces, Context& ctx) { |
139 | 0 | ExpressionObj exp = ARG(argname, Expression); |
140 | 0 | if (exp->concrete_type() == Expression::NULL_VAL) { |
141 | 0 | sass::ostream msg; |
142 | 0 | msg << argname << ": null is not a string for `" << function_name(sig) << "'"; |
143 | 0 | error(msg.str(), exp->pstate(), traces); |
144 | 0 | } |
145 | 0 | if (String_Constant* str = Cast<String_Constant>(exp)) { |
146 | 0 | str->quote_mark(0); |
147 | 0 | } |
148 | 0 | sass::string exp_src = exp->to_string(ctx.c_options); |
149 | 0 | ItplFile* source = SASS_MEMORY_NEW(ItplFile, exp_src.c_str(), exp->pstate()); |
150 | 0 | SelectorListObj sel_list = Parser::parse_selector(source, ctx, traces, false); |
151 | 0 | if (sel_list->length() == 0) return {}; |
152 | 0 | return sel_list->first()->first(); |
153 | 0 | } |
154 | | |
155 | | |
156 | | } |
157 | | |
158 | | } |