sassc 2.3.0 → 2.4.0
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +5 -0
- data/ext/libsass/VERSION +1 -1
- data/ext/libsass/include/sass/context.h +3 -0
- data/ext/libsass/src/MurmurHash2.hpp +91 -0
- data/ext/libsass/src/ast.cpp +117 -117
- data/ext/libsass/src/ast.hpp +160 -162
- data/ext/libsass/src/ast_def_macros.hpp +10 -10
- data/ext/libsass/src/ast_fwd_decl.cpp +2 -2
- data/ext/libsass/src/ast_fwd_decl.hpp +61 -52
- data/ext/libsass/src/ast_helpers.hpp +5 -5
- data/ext/libsass/src/ast_sel_cmp.cpp +18 -18
- data/ext/libsass/src/ast_sel_super.cpp +52 -52
- data/ext/libsass/src/ast_sel_unify.cpp +16 -16
- data/ext/libsass/src/ast_sel_weave.cpp +62 -62
- data/ext/libsass/src/ast_selectors.cpp +87 -77
- data/ext/libsass/src/ast_selectors.hpp +72 -62
- data/ext/libsass/src/ast_supports.cpp +35 -35
- data/ext/libsass/src/ast_supports.hpp +29 -29
- data/ext/libsass/src/ast_values.cpp +58 -58
- data/ext/libsass/src/ast_values.hpp +75 -75
- data/ext/libsass/src/backtrace.cpp +9 -9
- data/ext/libsass/src/backtrace.hpp +5 -5
- data/ext/libsass/src/base64vlq.cpp +2 -2
- data/ext/libsass/src/base64vlq.hpp +1 -1
- data/ext/libsass/src/bind.cpp +17 -17
- data/ext/libsass/src/bind.hpp +1 -1
- data/ext/libsass/src/c2ast.cpp +3 -3
- data/ext/libsass/src/c2ast.hpp +1 -1
- data/ext/libsass/src/check_nesting.cpp +36 -36
- data/ext/libsass/src/check_nesting.hpp +2 -2
- data/ext/libsass/src/color_maps.cpp +5 -5
- data/ext/libsass/src/color_maps.hpp +1 -1
- data/ext/libsass/src/context.cpp +63 -60
- data/ext/libsass/src/context.hpp +33 -33
- data/ext/libsass/src/cssize.cpp +30 -29
- data/ext/libsass/src/cssize.hpp +13 -13
- data/ext/libsass/src/dart_helpers.hpp +5 -5
- data/ext/libsass/src/debugger.hpp +127 -128
- data/ext/libsass/src/emitter.cpp +12 -12
- data/ext/libsass/src/emitter.hpp +10 -10
- data/ext/libsass/src/environment.cpp +27 -27
- data/ext/libsass/src/environment.hpp +24 -24
- data/ext/libsass/src/error_handling.cpp +42 -42
- data/ext/libsass/src/error_handling.hpp +38 -50
- data/ext/libsass/src/eval.cpp +138 -132
- data/ext/libsass/src/eval.hpp +17 -17
- data/ext/libsass/src/eval_selectors.cpp +3 -3
- data/ext/libsass/src/expand.cpp +70 -64
- data/ext/libsass/src/expand.hpp +12 -12
- data/ext/libsass/src/extender.cpp +55 -53
- data/ext/libsass/src/extender.hpp +14 -14
- data/ext/libsass/src/file.cpp +66 -58
- data/ext/libsass/src/file.hpp +23 -25
- data/ext/libsass/src/fn_colors.cpp +9 -9
- data/ext/libsass/src/fn_lists.cpp +18 -18
- data/ext/libsass/src/fn_maps.cpp +3 -3
- data/ext/libsass/src/fn_miscs.cpp +15 -15
- data/ext/libsass/src/fn_numbers.cpp +7 -7
- data/ext/libsass/src/fn_selectors.cpp +8 -8
- data/ext/libsass/src/fn_strings.cpp +34 -22
- data/ext/libsass/src/fn_utils.cpp +29 -26
- data/ext/libsass/src/fn_utils.hpp +10 -10
- data/ext/libsass/src/inspect.cpp +35 -34
- data/ext/libsass/src/inspect.hpp +21 -21
- data/ext/libsass/src/lexer.cpp +3 -1
- data/ext/libsass/src/listize.cpp +2 -2
- data/ext/libsass/src/mapping.hpp +1 -0
- data/ext/libsass/src/memory.hpp +12 -0
- data/ext/libsass/src/memory/allocator.cpp +48 -0
- data/ext/libsass/src/memory/allocator.hpp +138 -0
- data/ext/libsass/src/memory/config.hpp +20 -0
- data/ext/libsass/src/memory/memory_pool.hpp +186 -0
- data/ext/libsass/src/memory/{SharedPtr.cpp → shared_ptr.cpp} +2 -2
- data/ext/libsass/src/memory/{SharedPtr.hpp → shared_ptr.hpp} +18 -6
- data/ext/libsass/src/operation.hpp +44 -44
- data/ext/libsass/src/operators.cpp +18 -18
- data/ext/libsass/src/operators.hpp +11 -11
- data/ext/libsass/src/ordered_map.hpp +18 -18
- data/ext/libsass/src/output.cpp +16 -16
- data/ext/libsass/src/output.hpp +5 -5
- data/ext/libsass/src/parser.cpp +327 -345
- data/ext/libsass/src/parser.hpp +77 -87
- data/ext/libsass/src/parser_selectors.cpp +6 -6
- data/ext/libsass/src/permutate.hpp +39 -15
- data/ext/libsass/src/plugins.cpp +7 -7
- data/ext/libsass/src/plugins.hpp +8 -8
- data/ext/libsass/src/position.cpp +7 -26
- data/ext/libsass/src/position.hpp +44 -21
- data/ext/libsass/src/remove_placeholders.cpp +4 -4
- data/ext/libsass/src/remove_placeholders.hpp +3 -3
- data/ext/libsass/src/sass.cpp +16 -15
- data/ext/libsass/src/sass.hpp +9 -5
- data/ext/libsass/src/sass_context.cpp +52 -34
- data/ext/libsass/src/sass_values.cpp +8 -10
- data/ext/libsass/src/settings.hpp +19 -0
- data/ext/libsass/src/source.cpp +69 -0
- data/ext/libsass/src/source.hpp +95 -0
- data/ext/libsass/src/source_data.hpp +32 -0
- data/ext/libsass/src/source_map.cpp +22 -18
- data/ext/libsass/src/source_map.hpp +12 -9
- data/ext/libsass/src/units.cpp +19 -19
- data/ext/libsass/src/units.hpp +8 -8
- data/ext/libsass/src/utf8_string.cpp +9 -10
- data/ext/libsass/src/utf8_string.hpp +7 -6
- data/ext/libsass/src/util.cpp +38 -38
- data/ext/libsass/src/util.hpp +18 -18
- data/ext/libsass/src/util_string.cpp +13 -13
- data/ext/libsass/src/util_string.hpp +9 -8
- data/ext/libsass/src/values.cpp +12 -12
- data/lib/sassc/native.rb +3 -5
- data/lib/sassc/version.rb +1 -1
- data/test/native_test.rb +4 -4
- metadata +14 -5
- data/lib/sassc/native/lib_c.rb +0 -21
@@ -14,7 +14,7 @@ namespace Sass {
|
|
14
14
|
// there is one edge case where this could give false positives
|
15
15
|
// test could contain a (non-ascii) char exactly 32 below literal
|
16
16
|
// ##########################################################################
|
17
|
-
bool equalsLiteral(const char* lit, const
|
17
|
+
bool equalsLiteral(const char* lit, const sass::string& test) {
|
18
18
|
// Work directly on characters
|
19
19
|
const char* src = test.c_str();
|
20
20
|
// There is a small chance that the search string
|
@@ -27,19 +27,19 @@ namespace Sass {
|
|
27
27
|
return *lit == 0;
|
28
28
|
}
|
29
29
|
|
30
|
-
void ascii_str_tolower(
|
30
|
+
void ascii_str_tolower(sass::string* s) {
|
31
31
|
for (auto& ch : *s) {
|
32
32
|
ch = ascii_tolower(static_cast<unsigned char>(ch));
|
33
33
|
}
|
34
34
|
}
|
35
35
|
|
36
|
-
void ascii_str_toupper(
|
36
|
+
void ascii_str_toupper(sass::string* s) {
|
37
37
|
for (auto& ch : *s) {
|
38
38
|
ch = ascii_toupper(static_cast<unsigned char>(ch));
|
39
39
|
}
|
40
40
|
}
|
41
41
|
|
42
|
-
|
42
|
+
sass::string rtrim(sass::string str) {
|
43
43
|
auto it = std::find_if_not(str.rbegin(), str.rend(), ascii_isspace);
|
44
44
|
str.erase(str.rend() - it);
|
45
45
|
return str;
|
@@ -49,7 +49,7 @@ namespace Sass {
|
|
49
49
|
// Returns [name] without a vendor prefix.
|
50
50
|
// If [name] has no vendor prefix, it's returned as-is.
|
51
51
|
// ###########################################################################
|
52
|
-
|
52
|
+
sass::string unvendor(const sass::string& name)
|
53
53
|
{
|
54
54
|
if (name.size() < 2) return name;
|
55
55
|
if (name[0] != '-') return name;
|
@@ -61,13 +61,13 @@ namespace Sass {
|
|
61
61
|
}
|
62
62
|
// EO unvendor
|
63
63
|
|
64
|
-
|
65
|
-
|
64
|
+
sass::string normalize_newlines(const sass::string& str) {
|
65
|
+
sass::string result;
|
66
66
|
result.reserve(str.size());
|
67
67
|
std::size_t pos = 0;
|
68
68
|
while (true) {
|
69
69
|
const std::size_t newline = str.find_first_of("\n\f\r", pos);
|
70
|
-
if (newline ==
|
70
|
+
if (newline == sass::string::npos) break;
|
71
71
|
result.append(str, pos, newline - pos);
|
72
72
|
result += '\n';
|
73
73
|
if (str[newline] == '\r' && str[newline + 1] == '\n') {
|
@@ -77,18 +77,18 @@ namespace Sass {
|
|
77
77
|
pos = newline + 1;
|
78
78
|
}
|
79
79
|
}
|
80
|
-
result.append(str, pos,
|
80
|
+
result.append(str, pos, sass::string::npos);
|
81
81
|
return result;
|
82
82
|
}
|
83
83
|
|
84
|
-
|
85
|
-
|
84
|
+
sass::string normalize_underscores(const sass::string& str) {
|
85
|
+
sass::string normalized = str;
|
86
86
|
std::replace(normalized.begin(), normalized.end(), '_', '-');
|
87
87
|
return normalized;
|
88
88
|
}
|
89
89
|
|
90
|
-
|
91
|
-
|
90
|
+
sass::string normalize_decimals(const sass::string& str) {
|
91
|
+
sass::string normalized;
|
92
92
|
if (!str.empty() && str[0] == '.') {
|
93
93
|
normalized.reserve(str.size() + 1);
|
94
94
|
normalized += '0';
|
@@ -1,6 +1,7 @@
|
|
1
1
|
#ifndef SASS_UTIL_STRING_H
|
2
2
|
#define SASS_UTIL_STRING_H
|
3
3
|
|
4
|
+
#include "sass.hpp"
|
4
5
|
#include <string>
|
5
6
|
|
6
7
|
namespace Sass {
|
@@ -14,18 +15,18 @@ namespace Sass {
|
|
14
15
|
// there is one edge case where this could give false positives
|
15
16
|
// test could contain a (non-ascii) char exactly 32 below literal
|
16
17
|
// ##########################################################################
|
17
|
-
bool equalsLiteral(const char* lit, const
|
18
|
+
bool equalsLiteral(const char* lit, const sass::string& test);
|
18
19
|
|
19
20
|
// ###########################################################################
|
20
21
|
// Returns [name] without a vendor prefix.
|
21
22
|
// If [name] has no vendor prefix, it's returned as-is.
|
22
23
|
// ###########################################################################
|
23
|
-
|
24
|
+
sass::string unvendor(const sass::string& name);
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
sass::string rtrim(sass::string str);
|
27
|
+
sass::string normalize_newlines(const sass::string& str);
|
28
|
+
sass::string normalize_underscores(const sass::string& str);
|
29
|
+
sass::string normalize_decimals(const sass::string& str);
|
29
30
|
char opening_bracket_for(char closing_bracket);
|
30
31
|
char closing_bracket_for(char opening_bracket);
|
31
32
|
|
@@ -58,14 +59,14 @@ namespace Sass {
|
|
58
59
|
return c;
|
59
60
|
}
|
60
61
|
|
61
|
-
void ascii_str_tolower(
|
62
|
+
void ascii_str_tolower(sass::string* s);
|
62
63
|
|
63
64
|
inline char ascii_toupper(unsigned char c) {
|
64
65
|
if (c >= 'a' && c <= 'z') return c - 32;
|
65
66
|
return c;
|
66
67
|
}
|
67
68
|
|
68
|
-
void ascii_str_toupper(
|
69
|
+
void ascii_str_toupper(sass::string* s);
|
69
70
|
|
70
71
|
} // namespace Sass
|
71
72
|
} // namespace Util
|
data/ext/libsass/src/values.cpp
CHANGED
@@ -32,7 +32,7 @@ namespace Sass {
|
|
32
32
|
const List* l = Cast<List>(val);
|
33
33
|
union Sass_Value* list = sass_make_list(l->size(), l->separator(), l->is_bracketed());
|
34
34
|
for (size_t i = 0, L = l->length(); i < L; ++i) {
|
35
|
-
|
35
|
+
ExpressionObj obj = l->at(i);
|
36
36
|
auto val = ast_node_to_sass_value(obj);
|
37
37
|
sass_list_set_value(list, i, val);
|
38
38
|
}
|
@@ -42,7 +42,7 @@ namespace Sass {
|
|
42
42
|
{
|
43
43
|
const Map* m = Cast<Map>(val);
|
44
44
|
union Sass_Value* map = sass_make_map(m->length());
|
45
|
-
size_t i = 0; for (
|
45
|
+
size_t i = 0; for (ExpressionObj key : m->keys()) {
|
46
46
|
sass_map_set_key(map, i, ast_node_to_sass_value(key));
|
47
47
|
sass_map_set_value(map, i, ast_node_to_sass_value(m->at(key)));
|
48
48
|
++ i;
|
@@ -78,17 +78,17 @@ namespace Sass {
|
|
78
78
|
switch (sass_value_get_tag(val)) {
|
79
79
|
case SASS_NUMBER:
|
80
80
|
return SASS_MEMORY_NEW(Number,
|
81
|
-
|
81
|
+
SourceSpan("[C-VALUE]"),
|
82
82
|
sass_number_get_value(val),
|
83
83
|
sass_number_get_unit(val));
|
84
84
|
case SASS_BOOLEAN:
|
85
85
|
return SASS_MEMORY_NEW(Boolean,
|
86
|
-
|
86
|
+
SourceSpan("[C-VALUE]"),
|
87
87
|
sass_boolean_get_value(val));
|
88
88
|
case SASS_COLOR:
|
89
89
|
// ToDo: allow to also use HSLA colors!!
|
90
90
|
return SASS_MEMORY_NEW(Color_RGBA,
|
91
|
-
|
91
|
+
SourceSpan("[C-VALUE]"),
|
92
92
|
sass_color_get_r(val),
|
93
93
|
sass_color_get_g(val),
|
94
94
|
sass_color_get_b(val),
|
@@ -96,15 +96,15 @@ namespace Sass {
|
|
96
96
|
case SASS_STRING:
|
97
97
|
if (sass_string_is_quoted(val)) {
|
98
98
|
return SASS_MEMORY_NEW(String_Quoted,
|
99
|
-
|
99
|
+
SourceSpan("[C-VALUE]"),
|
100
100
|
sass_string_get_value(val));
|
101
101
|
}
|
102
102
|
return SASS_MEMORY_NEW(String_Constant,
|
103
|
-
|
103
|
+
SourceSpan("[C-VALUE]"),
|
104
104
|
sass_string_get_value(val));
|
105
105
|
case SASS_LIST: {
|
106
106
|
List* l = SASS_MEMORY_NEW(List,
|
107
|
-
|
107
|
+
SourceSpan("[C-VALUE]"),
|
108
108
|
sass_list_get_length(val),
|
109
109
|
sass_list_get_separator(val));
|
110
110
|
for (size_t i = 0, L = sass_list_get_length(val); i < L; ++i) {
|
@@ -114,7 +114,7 @@ namespace Sass {
|
|
114
114
|
return l;
|
115
115
|
}
|
116
116
|
case SASS_MAP: {
|
117
|
-
Map* m = SASS_MEMORY_NEW(Map,
|
117
|
+
Map* m = SASS_MEMORY_NEW(Map, SourceSpan("[C-VALUE]"));
|
118
118
|
for (size_t i = 0, L = sass_map_get_length(val); i < L; ++i) {
|
119
119
|
*m << std::make_pair(
|
120
120
|
sass_value_to_ast_node(sass_map_get_key(val, i)),
|
@@ -123,14 +123,14 @@ namespace Sass {
|
|
123
123
|
return m;
|
124
124
|
}
|
125
125
|
case SASS_NULL:
|
126
|
-
return SASS_MEMORY_NEW(Null,
|
126
|
+
return SASS_MEMORY_NEW(Null, SourceSpan("[C-VALUE]"));
|
127
127
|
case SASS_ERROR:
|
128
128
|
return SASS_MEMORY_NEW(Custom_Error,
|
129
|
-
|
129
|
+
SourceSpan("[C-VALUE]"),
|
130
130
|
sass_error_get_message(val));
|
131
131
|
case SASS_WARNING:
|
132
132
|
return SASS_MEMORY_NEW(Custom_Warning,
|
133
|
-
|
133
|
+
SourceSpan("[C-VALUE]"),
|
134
134
|
sass_warning_get_message(val));
|
135
135
|
default: break;
|
136
136
|
}
|
data/lib/sassc/native.rb
CHANGED
@@ -34,7 +34,6 @@ module SassC
|
|
34
34
|
require_relative "native/sass_input_style"
|
35
35
|
require_relative "native/sass_output_style"
|
36
36
|
require_relative "native/string_list"
|
37
|
-
require_relative "native/lib_c"
|
38
37
|
|
39
38
|
# Remove the redundant "sass_" from the beginning of every method name
|
40
39
|
def self.attach_function(*args)
|
@@ -53,10 +52,9 @@ module SassC
|
|
53
52
|
end
|
54
53
|
|
55
54
|
def self.native_string(string)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
data
|
55
|
+
m = FFI::MemoryPointer.from_string(string)
|
56
|
+
m.autorelease = false
|
57
|
+
m
|
60
58
|
end
|
61
59
|
|
62
60
|
require_relative "native/native_context_api"
|
data/lib/sassc/version.rb
CHANGED
data/test/native_test.rb
CHANGED
@@ -11,7 +11,7 @@ module SassC
|
|
11
11
|
|
12
12
|
class General < MiniTest::Test
|
13
13
|
def test_it_reports_the_libsass_version
|
14
|
-
assert_equal "3.6.
|
14
|
+
assert_equal "3.6.4", Native.version
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -185,9 +185,9 @@ module SassC
|
|
185
185
|
funct = FFI::Function.new(:pointer, [:pointer, :pointer, :pointer]) do |url, prev, cookie|
|
186
186
|
list = Native.make_import_list(2)
|
187
187
|
|
188
|
-
str = "$var: 5px
|
189
|
-
data =
|
190
|
-
data.
|
188
|
+
str = "$var: 5px;"
|
189
|
+
data = FFI::MemoryPointer.from_string(str)
|
190
|
+
data.autorelease = false
|
191
191
|
|
192
192
|
entry0 = Native.make_import_entry("fake_includ.scss", data, nil)
|
193
193
|
entry1 = Native.make_import_entry("not_included.scss", nil, nil)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sassc
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Boland
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-06-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: minitest
|
@@ -164,6 +164,7 @@ files:
|
|
164
164
|
- ext/libsass/include/sass/values.h
|
165
165
|
- ext/libsass/include/sass/version.h
|
166
166
|
- ext/libsass/include/sass2scss.h
|
167
|
+
- ext/libsass/src/MurmurHash2.hpp
|
167
168
|
- ext/libsass/src/ast.cpp
|
168
169
|
- ext/libsass/src/ast.hpp
|
169
170
|
- ext/libsass/src/ast2c.cpp
|
@@ -250,8 +251,13 @@ files:
|
|
250
251
|
- ext/libsass/src/listize.cpp
|
251
252
|
- ext/libsass/src/listize.hpp
|
252
253
|
- ext/libsass/src/mapping.hpp
|
253
|
-
- ext/libsass/src/memory
|
254
|
-
- ext/libsass/src/memory/
|
254
|
+
- ext/libsass/src/memory.hpp
|
255
|
+
- ext/libsass/src/memory/allocator.cpp
|
256
|
+
- ext/libsass/src/memory/allocator.hpp
|
257
|
+
- ext/libsass/src/memory/config.hpp
|
258
|
+
- ext/libsass/src/memory/memory_pool.hpp
|
259
|
+
- ext/libsass/src/memory/shared_ptr.cpp
|
260
|
+
- ext/libsass/src/memory/shared_ptr.hpp
|
255
261
|
- ext/libsass/src/operation.hpp
|
256
262
|
- ext/libsass/src/operators.cpp
|
257
263
|
- ext/libsass/src/operators.hpp
|
@@ -279,6 +285,10 @@ files:
|
|
279
285
|
- ext/libsass/src/sass_functions.hpp
|
280
286
|
- ext/libsass/src/sass_values.cpp
|
281
287
|
- ext/libsass/src/sass_values.hpp
|
288
|
+
- ext/libsass/src/settings.hpp
|
289
|
+
- ext/libsass/src/source.cpp
|
290
|
+
- ext/libsass/src/source.hpp
|
291
|
+
- ext/libsass/src/source_data.hpp
|
282
292
|
- ext/libsass/src/source_map.cpp
|
283
293
|
- ext/libsass/src/source_map.hpp
|
284
294
|
- ext/libsass/src/stylesheet.cpp
|
@@ -307,7 +317,6 @@ files:
|
|
307
317
|
- lib/sassc/import_handler.rb
|
308
318
|
- lib/sassc/importer.rb
|
309
319
|
- lib/sassc/native.rb
|
310
|
-
- lib/sassc/native/lib_c.rb
|
311
320
|
- lib/sassc/native/native_context_api.rb
|
312
321
|
- lib/sassc/native/native_functions_api.rb
|
313
322
|
- lib/sassc/native/sass2scss_api.rb
|
data/lib/sassc/native/lib_c.rb
DELETED
@@ -1,21 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module SassC
|
4
|
-
module Native
|
5
|
-
module LibC
|
6
|
-
extend FFI::Library
|
7
|
-
ffi_lib FFI::Library::LIBC
|
8
|
-
|
9
|
-
# memory allocators
|
10
|
-
attach_function :malloc, [:size_t], :pointer
|
11
|
-
# attach_function :calloc, [:size_t], :pointer
|
12
|
-
# attach_function :valloc, [:size_t], :pointer
|
13
|
-
# attach_function :realloc, [:pointer, :size_t], :pointer
|
14
|
-
# attach_function :free, [:pointer], :void
|
15
|
-
|
16
|
-
# memory movers
|
17
|
-
# attach_function :memcpy, [:pointer, :pointer, :size_t], :pointer
|
18
|
-
# attach_function :bcopy, [:pointer, :pointer, :size_t], :void
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|