mirror of
https://git.savannah.gnu.org/git/bison.git
synced 2026-03-20 09:43:03 +00:00
Fix bug that mistakes braced code in a declaration in the rules section
to be a rule action. Mentioned at <http://lists.gnu.org/archive/html/bison-patches/2006-06/msg00105.html>. * src/scan-gram.l: Move midrule action detection from the start of the scanning of any braced code to... * src/parse-gram.y (rhs): ... the parsing of braced code as a rule action. For readability, use $2 and @2 rather than the equivalent global variables. * tests/regression.at (Braced code in declaration in rules section): New test to catch the error fixed by the above patch. Work on code readability some. * src/scan-code.l (current_rule): Get rid of this misleading and redundant declaration: it's actually extern'ed in reader.h. (YY_DECL, code_lex, handle_action_dollar, handle_action_at, translate_action): Add a rule argument and use it instead of the global current_rule. (translate_rule_action): This already receives current_rule through an argument, so pass it on to translate_action instead of assigning current_rule to current_rule. (translate_symbol_action, translate_code): Pass rule = NULL to translate_action.
This commit is contained in:
25
ChangeLog
25
ChangeLog
@@ -1,3 +1,28 @@
|
|||||||
|
2006-06-24 Joel E. Denny <jdenny@ces.clemson.edu>
|
||||||
|
|
||||||
|
Fix bug that mistakes braced code in a declaration in the rules section
|
||||||
|
to be a rule action. Mentioned at
|
||||||
|
<http://lists.gnu.org/archive/html/bison-patches/2006-06/msg00105.html>.
|
||||||
|
* src/scan-gram.l: Move midrule action detection from the start of the
|
||||||
|
scanning of any braced code to...
|
||||||
|
* src/parse-gram.y (rhs): ... the parsing of braced code as a rule
|
||||||
|
action. For readability, use $2 and @2 rather than the equivalent
|
||||||
|
global variables.
|
||||||
|
* tests/regression.at (Braced code in declaration in rules section):
|
||||||
|
New test to catch the error fixed by the above patch.
|
||||||
|
|
||||||
|
Work on code readability some.
|
||||||
|
* src/scan-code.l (current_rule): Get rid of this misleading and
|
||||||
|
redundant declaration: it's actually extern'ed in reader.h.
|
||||||
|
(YY_DECL, code_lex, handle_action_dollar, handle_action_at,
|
||||||
|
translate_action): Add a rule argument and use it instead of the global
|
||||||
|
current_rule.
|
||||||
|
(translate_rule_action): This already receives current_rule through an
|
||||||
|
argument, so pass it on to translate_action instead of assigning
|
||||||
|
current_rule to current_rule.
|
||||||
|
(translate_symbol_action, translate_code): Pass rule = NULL to
|
||||||
|
translate_action.
|
||||||
|
|
||||||
2006-06-23 Joel E. Denny <jdenny@ces.clemson.edu>
|
2006-06-23 Joel E. Denny <jdenny@ces.clemson.edu>
|
||||||
|
|
||||||
Rename %before-definitions to %start-header and %after-definitions to
|
Rename %before-definitions to %start-header and %after-definitions to
|
||||||
|
|||||||
@@ -654,8 +654,8 @@ static const yytype_uint16 yyrline[] =
|
|||||||
305, 309, 323, 324, 328, 350, 350, 355, 355, 360,
|
305, 309, 323, 324, 328, 350, 350, 355, 355, 360,
|
||||||
370, 385, 386, 387, 391, 392, 397, 398, 403, 407,
|
370, 385, 386, 387, 391, 392, 397, 398, 403, 407,
|
||||||
412, 418, 424, 435, 436, 445, 446, 452, 453, 454,
|
412, 418, 424, 435, 436, 445, 446, 452, 453, 454,
|
||||||
461, 461, 465, 466, 467, 472, 473, 475, 478, 480,
|
461, 461, 465, 466, 467, 472, 473, 475, 481, 483,
|
||||||
482, 495, 497, 506, 511, 512, 517, 526, 531, 533
|
485, 498, 500, 509, 514, 515, 520, 529, 534, 536
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2173,32 +2173,35 @@ yyreduce:
|
|||||||
|
|
||||||
case 77:
|
case 77:
|
||||||
#line 476 "parse-gram.y"
|
#line 476 "parse-gram.y"
|
||||||
{ grammar_current_rule_action_append (gram_last_string,
|
{
|
||||||
gram_last_braced_code_loc); }
|
if (current_rule && current_rule->action)
|
||||||
|
grammar_midrule_action ();
|
||||||
|
grammar_current_rule_action_append ((yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)]));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 78:
|
case 78:
|
||||||
#line 479 "parse-gram.y"
|
#line 482 "parse-gram.y"
|
||||||
{ grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); }
|
{ grammar_current_rule_prec_set ((yyvsp[(3) - (3)].symbol), (yylsp[(3) - (3)])); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 79:
|
case 79:
|
||||||
#line 481 "parse-gram.y"
|
#line 484 "parse-gram.y"
|
||||||
{ grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); }
|
{ grammar_current_rule_dprec_set ((yyvsp[(3) - (3)].integer), (yylsp[(3) - (3)])); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 80:
|
case 80:
|
||||||
#line 483 "parse-gram.y"
|
#line 486 "parse-gram.y"
|
||||||
{ grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); }
|
{ grammar_current_rule_merge_set ((yyvsp[(3) - (3)].uniqstr), (yylsp[(3) - (3)])); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 81:
|
case 81:
|
||||||
#line 496 "parse-gram.y"
|
#line 499 "parse-gram.y"
|
||||||
{ (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
|
{ (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 82:
|
case 82:
|
||||||
#line 498 "parse-gram.y"
|
#line 501 "parse-gram.y"
|
||||||
{
|
{
|
||||||
(yyval.symbol) = symbol_get (char_name ((yyvsp[(1) - (1)].character)), (yylsp[(1) - (1)]));
|
(yyval.symbol) = symbol_get (char_name ((yyvsp[(1) - (1)].character)), (yylsp[(1) - (1)]));
|
||||||
symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
|
symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
|
||||||
@@ -2207,12 +2210,12 @@ yyreduce:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 83:
|
case 83:
|
||||||
#line 506 "parse-gram.y"
|
#line 509 "parse-gram.y"
|
||||||
{ (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
|
{ (yyval.symbol) = symbol_from_uniqstr ((yyvsp[(1) - (1)].uniqstr), (yylsp[(1) - (1)])); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 86:
|
case 86:
|
||||||
#line 518 "parse-gram.y"
|
#line 521 "parse-gram.y"
|
||||||
{
|
{
|
||||||
(yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)]));
|
(yyval.symbol) = symbol_get (quotearg_style (c_quoting_style, (yyvsp[(1) - (1)].chars)), (yylsp[(1) - (1)]));
|
||||||
symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
|
symbol_class_set ((yyval.symbol), token_sym, (yylsp[(1) - (1)]), false);
|
||||||
@@ -2220,12 +2223,12 @@ yyreduce:
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 87:
|
case 87:
|
||||||
#line 527 "parse-gram.y"
|
#line 530 "parse-gram.y"
|
||||||
{ (yyval.chars) = (yyvsp[(1) - (1)].chars); }
|
{ (yyval.chars) = (yyvsp[(1) - (1)].chars); }
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 89:
|
case 89:
|
||||||
#line 534 "parse-gram.y"
|
#line 537 "parse-gram.y"
|
||||||
{
|
{
|
||||||
muscle_code_grow ("epilogue", translate_code ((yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)])), (yylsp[(2) - (2)]));
|
muscle_code_grow ("epilogue", translate_code ((yyvsp[(2) - (2)].chars), (yylsp[(2) - (2)])), (yylsp[(2) - (2)]));
|
||||||
gram_scanner_last_string_free ();
|
gram_scanner_last_string_free ();
|
||||||
@@ -2234,7 +2237,7 @@ yyreduce:
|
|||||||
|
|
||||||
|
|
||||||
/* Line 1274 of yacc.c. */
|
/* Line 1274 of yacc.c. */
|
||||||
#line 2238 "parse-gram.c"
|
#line 2241 "parse-gram.c"
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
|
YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
|
||||||
@@ -2454,7 +2457,7 @@ yyreturn:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#line 540 "parse-gram.y"
|
#line 543 "parse-gram.y"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -473,8 +473,11 @@ rhs:
|
|||||||
| rhs symbol
|
| rhs symbol
|
||||||
{ grammar_current_rule_symbol_append ($2, @2); }
|
{ grammar_current_rule_symbol_append ($2, @2); }
|
||||||
| rhs "{...}"
|
| rhs "{...}"
|
||||||
{ grammar_current_rule_action_append (gram_last_string,
|
{
|
||||||
gram_last_braced_code_loc); }
|
if (current_rule && current_rule->action)
|
||||||
|
grammar_midrule_action ();
|
||||||
|
grammar_current_rule_action_append ($2, @2);
|
||||||
|
}
|
||||||
| rhs "%prec" symbol
|
| rhs "%prec" symbol
|
||||||
{ grammar_current_rule_prec_set ($3, @3); }
|
{ grammar_current_rule_prec_set ($3, @3); }
|
||||||
| rhs "%dprec" INT
|
| rhs "%dprec" INT
|
||||||
|
|||||||
@@ -45,18 +45,16 @@
|
|||||||
|
|
||||||
/* The current calling start condition: SC_RULE_ACTION or
|
/* The current calling start condition: SC_RULE_ACTION or
|
||||||
SC_SYMBOL_ACTION. */
|
SC_SYMBOL_ACTION. */
|
||||||
# define YY_DECL const char *code_lex (int sc_context)
|
# define YY_DECL const char *code_lex (int sc_context, symbol_list *rule)
|
||||||
YY_DECL;
|
YY_DECL;
|
||||||
|
|
||||||
#define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng);
|
#define YY_USER_ACTION location_compute (loc, &loc->end, yytext, yyleng);
|
||||||
|
|
||||||
static void handle_action_dollar (char *cp, location dollar_loc);
|
static void handle_action_dollar (symbol_list *rule, char *cp,
|
||||||
static void handle_action_at (char *cp, location at_loc);
|
location dollar_loc);
|
||||||
|
static void handle_action_at (symbol_list *rule, char *cp, location at_loc);
|
||||||
static location the_location;
|
static location the_location;
|
||||||
static location *loc = &the_location;
|
static location *loc = &the_location;
|
||||||
|
|
||||||
/* The rule being processed. */
|
|
||||||
symbol_list *current_rule;
|
|
||||||
%}
|
%}
|
||||||
/* C and C++ comments in code. */
|
/* C and C++ comments in code. */
|
||||||
%x SC_COMMENT SC_LINE_COMMENT
|
%x SC_COMMENT SC_LINE_COMMENT
|
||||||
@@ -153,8 +151,8 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
|
|
||||||
<SC_RULE_ACTION>
|
<SC_RULE_ACTION>
|
||||||
{
|
{
|
||||||
"$"("<"{tag}">")?(-?[0-9]+|"$") handle_action_dollar (yytext, *loc);
|
"$"("<"{tag}">")?(-?[0-9]+|"$") handle_action_dollar (rule, yytext, *loc);
|
||||||
"@"(-?[0-9]+|"$") handle_action_at (yytext, *loc);
|
"@"(-?[0-9]+|"$") handle_action_at (rule, yytext, *loc);
|
||||||
|
|
||||||
"$" {
|
"$" {
|
||||||
warn_at (*loc, _("stray `$'"));
|
warn_at (*loc, _("stray `$'"));
|
||||||
@@ -238,11 +236,11 @@ int max_left_semantic_context = 0;
|
|||||||
`------------------------------------------------------------------*/
|
`------------------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_action_dollar (char *text, location dollar_loc)
|
handle_action_dollar (symbol_list *rule, char *text, location dollar_loc)
|
||||||
{
|
{
|
||||||
const char *type_name = NULL;
|
const char *type_name = NULL;
|
||||||
char *cp = text + 1;
|
char *cp = text + 1;
|
||||||
int rule_length = symbol_list_length (current_rule->next);
|
int rule_length = symbol_list_length (rule->next);
|
||||||
|
|
||||||
/* Get the type name if explicit. */
|
/* Get the type name if explicit. */
|
||||||
if (*cp == '<')
|
if (*cp == '<')
|
||||||
@@ -257,15 +255,15 @@ handle_action_dollar (char *text, location dollar_loc)
|
|||||||
if (*cp == '$')
|
if (*cp == '$')
|
||||||
{
|
{
|
||||||
if (!type_name)
|
if (!type_name)
|
||||||
type_name = symbol_list_n_type_name_get (current_rule, dollar_loc, 0);
|
type_name = symbol_list_n_type_name_get (rule, dollar_loc, 0);
|
||||||
if (!type_name && typed)
|
if (!type_name && typed)
|
||||||
complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
|
complain_at (dollar_loc, _("$$ of `%s' has no declared type"),
|
||||||
current_rule->sym->tag);
|
rule->sym->tag);
|
||||||
if (!type_name)
|
if (!type_name)
|
||||||
type_name = "";
|
type_name = "";
|
||||||
obstack_fgrow1 (&obstack_for_string,
|
obstack_fgrow1 (&obstack_for_string,
|
||||||
"]b4_lhs_value([%s])[", type_name);
|
"]b4_lhs_value([%s])[", type_name);
|
||||||
current_rule->used = true;
|
rule->used = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -279,16 +277,16 @@ handle_action_dollar (char *text, location dollar_loc)
|
|||||||
max_left_semantic_context = 1-n;
|
max_left_semantic_context = 1-n;
|
||||||
if (!type_name && n > 0)
|
if (!type_name && n > 0)
|
||||||
type_name =
|
type_name =
|
||||||
symbol_list_n_type_name_get (current_rule, dollar_loc, n);
|
symbol_list_n_type_name_get (rule, dollar_loc, n);
|
||||||
if (!type_name && typed)
|
if (!type_name && typed)
|
||||||
complain_at (dollar_loc, _("$%d of `%s' has no declared type"),
|
complain_at (dollar_loc, _("$%d of `%s' has no declared type"),
|
||||||
n, current_rule->sym->tag);
|
n, rule->sym->tag);
|
||||||
if (!type_name)
|
if (!type_name)
|
||||||
type_name = "";
|
type_name = "";
|
||||||
obstack_fgrow3 (&obstack_for_string,
|
obstack_fgrow3 (&obstack_for_string,
|
||||||
"]b4_rhs_value(%d, %d, [%s])[",
|
"]b4_rhs_value(%d, %d, [%s])[",
|
||||||
rule_length, n, type_name);
|
rule_length, n, type_name);
|
||||||
symbol_list_n_used_set (current_rule, n, true);
|
symbol_list_n_used_set (rule, n, true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
complain_at (dollar_loc, _("integer out of range: %s"), quote (text));
|
complain_at (dollar_loc, _("integer out of range: %s"), quote (text));
|
||||||
@@ -302,10 +300,10 @@ handle_action_dollar (char *text, location dollar_loc)
|
|||||||
`------------------------------------------------------*/
|
`------------------------------------------------------*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handle_action_at (char *text, location at_loc)
|
handle_action_at (symbol_list *rule, char *text, location at_loc)
|
||||||
{
|
{
|
||||||
char *cp = text + 1;
|
char *cp = text + 1;
|
||||||
int rule_length = symbol_list_length (current_rule->next);
|
int rule_length = symbol_list_length (rule->next);
|
||||||
locations_flag = true;
|
locations_flag = true;
|
||||||
|
|
||||||
if (*cp == '$')
|
if (*cp == '$')
|
||||||
@@ -337,7 +335,7 @@ handle_action_at (char *text, location at_loc)
|
|||||||
INITIAL), the processing is different. */
|
INITIAL), the processing is different. */
|
||||||
|
|
||||||
static const char *
|
static const char *
|
||||||
translate_action (int sc_context, const char *a, location l)
|
translate_action (int sc_context, symbol_list *rule, const char *a, location l)
|
||||||
{
|
{
|
||||||
const char *res;
|
const char *res;
|
||||||
static bool initialized = false;
|
static bool initialized = false;
|
||||||
@@ -352,29 +350,28 @@ translate_action (int sc_context, const char *a, location l)
|
|||||||
|
|
||||||
loc->start = loc->end = l.start;
|
loc->start = loc->end = l.start;
|
||||||
yy_switch_to_buffer (yy_scan_string (a));
|
yy_switch_to_buffer (yy_scan_string (a));
|
||||||
res = code_lex (sc_context);
|
res = code_lex (sc_context, rule);
|
||||||
yy_delete_buffer (YY_CURRENT_BUFFER);
|
yy_delete_buffer (YY_CURRENT_BUFFER);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
translate_rule_action (symbol_list *r, const char *a, location l)
|
translate_rule_action (symbol_list *rule, const char *a, location l)
|
||||||
{
|
{
|
||||||
current_rule = r;
|
return translate_action (SC_RULE_ACTION, rule, a, l);
|
||||||
return translate_action (SC_RULE_ACTION, a, l);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
translate_symbol_action (const char *a, location l)
|
translate_symbol_action (const char *a, location l)
|
||||||
{
|
{
|
||||||
return translate_action (SC_SYMBOL_ACTION, a, l);
|
return translate_action (SC_SYMBOL_ACTION, NULL, a, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
translate_code (const char *a, location l)
|
translate_code (const char *a, location l)
|
||||||
{
|
{
|
||||||
return translate_action (INITIAL, a, l);
|
return translate_action (INITIAL, NULL, a, l);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------.
|
/*-----------------------------------------------.
|
||||||
|
|||||||
@@ -243,8 +243,6 @@ splice (\\[ \f\t\v]*\n)*
|
|||||||
|
|
||||||
/* Code in between braces. */
|
/* Code in between braces. */
|
||||||
"{" {
|
"{" {
|
||||||
if (current_rule && current_rule->action)
|
|
||||||
grammar_midrule_action ();
|
|
||||||
STRING_GROW;
|
STRING_GROW;
|
||||||
braces_level = 0;
|
braces_level = 0;
|
||||||
code_start = loc->start;
|
code_start = loc->start;
|
||||||
|
|||||||
@@ -1004,3 +1004,79 @@ AT_CLEANUP
|
|||||||
AT_CHECK_EXPECT2()
|
AT_CHECK_EXPECT2()
|
||||||
AT_CHECK_EXPECT2([%glr-parser])
|
AT_CHECK_EXPECT2([%glr-parser])
|
||||||
AT_CHECK_EXPECT2([%skeleton "lalr1.cc"])
|
AT_CHECK_EXPECT2([%skeleton "lalr1.cc"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## --------------------------------------------- ##
|
||||||
|
## Braced code in declaration in rules section. ##
|
||||||
|
## --------------------------------------------- ##
|
||||||
|
|
||||||
|
AT_SETUP([Braced code in declaration in rules section])
|
||||||
|
|
||||||
|
# Bison once mistook braced code in a declaration in the rules section to be a
|
||||||
|
# rule action.
|
||||||
|
|
||||||
|
AT_DATA_GRAMMAR([input.y],
|
||||||
|
[[%{
|
||||||
|
#include <stdio.h>
|
||||||
|
void yyerror (char const *msg);
|
||||||
|
int yylex (void);
|
||||||
|
%}
|
||||||
|
|
||||||
|
%error-verbose
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
start:
|
||||||
|
{
|
||||||
|
printf ("Bison would once convert this action to a midrule because of the"
|
||||||
|
" subsequent braced code.\n");
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
%destructor { fprintf (stderr, "DESTRUCTOR\n"); } 'a';
|
||||||
|
%printer { fprintf (yyoutput, "PRINTER"); } 'a';
|
||||||
|
|
||||||
|
%%
|
||||||
|
|
||||||
|
void
|
||||||
|
yyerror (char const *msg)
|
||||||
|
{
|
||||||
|
fprintf (stderr, "%s\n", msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
yylex (void)
|
||||||
|
{
|
||||||
|
return 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (void)
|
||||||
|
{
|
||||||
|
yydebug = 1;
|
||||||
|
return !yyparse ();
|
||||||
|
}
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_CHECK([bison -t -o input.c input.y])
|
||||||
|
AT_COMPILE([input])
|
||||||
|
AT_PARSER_CHECK([./input], 0,
|
||||||
|
[[Bison would once convert this action to a midrule because of the subsequent braced code.
|
||||||
|
]],
|
||||||
|
[[Starting parse
|
||||||
|
Entering state 0
|
||||||
|
Reducing stack by rule 1 (line 22):
|
||||||
|
-> $$ = nterm start ()
|
||||||
|
Stack now 0
|
||||||
|
Entering state 1
|
||||||
|
Reading a token: Next token is token 'a' (PRINTER)
|
||||||
|
syntax error, unexpected 'a', expecting $end
|
||||||
|
Error: popping nterm start ()
|
||||||
|
Stack now 0
|
||||||
|
Cleanup: discarding lookahead token 'a' (PRINTER)
|
||||||
|
DESTRUCTOR
|
||||||
|
Stack now 0
|
||||||
|
]])
|
||||||
|
|
||||||
|
AT_CLEANUP
|
||||||
|
|||||||
Reference in New Issue
Block a user