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

source code of gtk/subprojects/libsass/src/fn_utils.cpp