From 6e649e659ebc2d8b54fa4636986370b76c2ff988 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Fri, 15 Nov 2002 20:32:21 +0000 Subject: [PATCH] * data/glr.c, data/lalr1.cc, data/yacc.cc, doc/bison.texinfo, src/conflicts.c, src/parse-gram.y, src/tables.c, src/tables.h, tests/action.at, tests/calc.at, tests/conflicts.at, tests/cxx-type.at, tests/regression.at: "parse error" -> "syntax error" for POSIX compatibility. "parsing stack overflow..." -> "parser stack overflow" so that code matches Bison documentation. --- ChangeLog | 10 ++++++++++ NEWS | 9 +++++++++ data/glr.c | 17 ++++++++--------- data/lalr1.cc | 4 ++-- data/yacc.c | 12 ++++++------ doc/bison.texinfo | 36 ++++++++++++++++++------------------ src/conflicts.c | 4 ++-- src/parse-gram.y | 4 ++-- src/tables.c | 4 ++-- src/tables.h | 2 +- tests/actions.at | 4 ++-- tests/calc.at | 24 ++++++++++++------------ tests/conflicts.at | 6 +++--- tests/cxx-type.at | 4 ++-- tests/regression.at | 2 +- 15 files changed, 80 insertions(+), 62 deletions(-) diff --git a/ChangeLog b/ChangeLog index d504ad41..3eca897f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2002-11-15 Paul Eggert + + * data/glr.c, data/lalr1.cc, data/yacc.cc, doc/bison.texinfo, + src/conflicts.c, src/parse-gram.y, src/tables.c, src/tables.h, + tests/action.at, tests/calc.at, tests/conflicts.at, + tests/cxx-type.at, tests/regression.at: + "parse error" -> "syntax error" for POSIX compatibility. + "parsing stack overflow..." -> "parser stack overflow" so + that code matches Bison documentation. + 2002-11-15 Akim Demaille * src/parse-gram.y (declaration): Have %parse-param and %lex-param diff --git a/NEWS b/NEWS index 727101b1..554f32ca 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,15 @@ Bison News ---------- Changes in version 1.75c: +* "parse error" -> "syntax error" + Bison now uniformly uses the term "syntax error"; formerly, the code + and manual sometimes used the term "parse error" instead. POSIX + requires "syntax error" in diagnostics, and it was thought better to + be consistent. + +* "parsing stack overflow..." -> "parser stack overflow" + GLR parsers now report "parser stack overflow" as per the Bison manual. + * GLR and inline Users of Bison have to decide how they handle the portability of the C keyword `inline'. diff --git a/data/glr.c b/data/glr.c index acc30aaf..461a6313 100644 --- a/data/glr.c +++ b/data/glr.c @@ -360,7 +360,7 @@ static const ]b4_int_type_for([b4_pgoto])[ yypgoto[] = /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, parse error. */ + If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF ]b4_table_ninf[ static const ]b4_int_type_for([b4_table])[ yytable[] = { @@ -866,8 +866,7 @@ yyexpandGLRStack (yyGLRStack* yystack]b4_pure_formals[) size_t yyn; yysize = yystack->yynextFree - yystack->yyitems; if (YYMAXDEPTH <= yysize) - yyFail (yystack][]b4_pure_args[, - "parsing stack overflow (%d items)", yysize); + yyFail (yystack][]b4_pure_args[, "parser stack overflow"); yynewSize = 2*yysize; if (YYMAXDEPTH < yynewSize) yynewSize = YYMAXDEPTH; @@ -914,8 +913,7 @@ yyexpandGLRStack (yyGLRStack* yystack]b4_pure_formals[) #else - yyFail (yystack][]b4_lpure_args[, - "parsing stack overflow (%d items)", yysize); + yyFail (yystack][]b4_lpure_args[, "parser stack overflow"); #endif } @@ -1596,7 +1594,7 @@ yyreportParseError (yyGLRStack* yystack, yycount = 0; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ - yysize = sizeof ("parse error, unexpected ") + yysize = sizeof ("syntax error, unexpected ") + strlen (yytokenName (*yytokenp)); yyprefix = ", expecting "; for (yyx = yyn < 0 ? -yyn : 0; yyx < yytname_size && yycount <= 5; @@ -1605,7 +1603,8 @@ yyreportParseError (yyGLRStack* yystack, yysize += strlen (yytokenName (yyx)) + strlen (yyprefix), yycount += 1, yyprefix = " or "; yymsg = yyp = (char*) malloc (yysize); - sprintf (yyp, "parse error, unexpected %s", yytokenName (*yytokenp)); + sprintf (yyp, "syntax error, unexpected %s", + yytokenName (*yytokenp)); yyp += strlen (yyp); if (yycount < 5) { @@ -1623,7 +1622,7 @@ yyreportParseError (yyGLRStack* yystack, } else #endif - yyerror (]b4_lyyerror_args["parse error"); + yyerror (]b4_lyyerror_args["syntax error"); yynerrs += 1; } } @@ -1855,7 +1854,7 @@ yyrecoverParseError (yyGLRStack* yystack, { yyundeleteLastStack (&yystack); if (yystack.yytops.yysize == 0) - yyFail (&yystack][]b4_lpure_args[, "parse error"); + yyFail (&yystack][]b4_lpure_args[, "syntax error"); YYCHK1 (yyresolveStack (&yystack]b4_user_args[)); YYDPRINTF ((stderr, "Returning to deterministic operation.\n")); yyreportParseError (&yystack, yylvalp, yyllocp]b4_user_args[); diff --git a/data/lalr1.cc b/data/lalr1.cc index ba8ebcaa..0dd1eb06 100644 --- a/data/lalr1.cc +++ b/data/lalr1.cc @@ -484,7 +484,7 @@ b4_syncline([@oline@], [@ofile@]) n_ = pact_[[state_]]; if (pact_ninf_ < n_ && n_ < last_) { - message = "parse error, unexpected "; + message = "syntax error, unexpected "; message += name_[[ilooka_]]; { int count = 0; @@ -505,7 +505,7 @@ b4_syncline([@oline@], [@ofile@]) } else #endif - message = "parse error"; + message = "syntax error"; error_ (); } goto yyerrlab1; diff --git a/data/yacc.c b/data/yacc.c index b0517a05..78ad3379 100644 --- a/data/yacc.c +++ b/data/yacc.c @@ -425,7 +425,7 @@ static const b4_int_type_for([b4_pgoto]) yypgoto[[]] = /* YYTABLE[[YYPACT[STATE-NUM]]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. - If YYTABLE_NINF, parse error. */ + If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF b4_table_ninf static const b4_int_type_for([b4_table]) yytable[[]] = { @@ -662,7 +662,7 @@ int yychar; /* The semantic value of the lookahead symbol. */ YYSTYPE yylval; -/* Number of parse errors so far. */ +/* Number of syntax errors so far. */ int yynerrs;b4_location_if([ /* Location data for the lookahead symbol. */ YYLTYPE yylloc;]) @@ -1017,12 +1017,12 @@ yyerrlab: yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) yysize += yystrlen (yytname[yyx]) + 15, yycount++; - yysize += yystrlen ("parse error, unexpected ") + 1; + yysize += yystrlen ("syntax error, unexpected ") + 1; yysize += yystrlen (yytname[yytype]); yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg != 0) { - char *yyp = yystpcpy (yymsg, "parse error, unexpected "); + char *yyp = yystpcpy (yymsg, "syntax error, unexpected "); yyp = yystpcpy (yyp, yytname[yytype]); if (yycount < 5) @@ -1043,11 +1043,11 @@ yyerrlab: YYSTACK_FREE (yymsg); } else - yyerror (]b4_yyerror_args["parse error; also virtual memory exhausted"); + yyerror (]b4_yyerror_args["syntax error; also virtual memory exhausted"); } else #endif /* YYERROR_VERBOSE */ - yyerror (]b4_yyerror_args["parse error"); + yyerror (]b4_yyerror_args["syntax error"); } goto yyerrlab1; diff --git a/doc/bison.texinfo b/doc/bison.texinfo index 6cef9b5e..affc3b62 100644 --- a/doc/bison.texinfo +++ b/doc/bison.texinfo @@ -1373,7 +1373,7 @@ main (void) When @code{yyparse} detects a syntax error, it calls the error reporting function @code{yyerror} to print an error message (usually but not -always @code{"parse error"}). It is up to the programmer to supply +always @code{"syntax error"}). It is up to the programmer to supply @code{yyerror} (@pxref{Interface, ,Parser C-Language Interface}), so here is the definition we will use: @@ -1583,7 +1583,7 @@ line: '\n' @end example This addition to the grammar allows for simple error recovery in the -event of a parse error. If an expression that cannot be evaluated is +event of a syntax error. If an expression that cannot be evaluated is read, the error will be recognized by the third rule for @code{line}, and parsing will continue. (The @code{yyerror} function is still called upon to print its message as well.) The action executes the statement @@ -3671,7 +3671,7 @@ Generate the code processing the locations (@pxref{Action Features, ,Special Features for Use in Actions}). This mode is enabled as soon as the grammar uses the special @samp{@@@var{n}} tokens, but if your grammar does not use it, using @samp{%locations} allows for more -accurate parse error messages. +accurate syntax error messages. @end deffn @deffn {Directive} %name-prefix="@var{prefix}" @@ -4134,7 +4134,7 @@ int yyparse (int *nastiness, int *randomness); @cindex parse error @cindex syntax error -The Bison parser detects a @dfn{parse error} or @dfn{syntax error} +The Bison parser detects a @dfn{syntax error} or @dfn{parse error} whenever it reads a token which cannot satisfy any syntax rule. An action in the grammar can also explicitly proclaim an error, using the macro @code{YYERROR} (@pxref{Action Features, ,Special Features for Use @@ -4143,14 +4143,14 @@ in Actions}). The Bison parser expects to report the error by calling an error reporting function named @code{yyerror}, which you must supply. It is called by @code{yyparse} whenever a syntax error is found, and it -receives one argument. For a parse error, the string is normally -@w{@code{"parse error"}}. +receives one argument. For a syntax error, the string is normally +@w{@code{"syntax error"}}. @findex %error-verbose If you invoke the directive @code{%error-verbose} in the Bison declarations section (@pxref{Bison Declarations, ,The Bison Declarations Section}), then Bison provides a more verbose and specific error message -string instead of just plain @w{@code{"parse error"}}. +string instead of just plain @w{@code{"syntax error"}}. The parser can detect one other kind of error: stack overflow. This happens when the input contains constructions that are very deeply @@ -5156,7 +5156,7 @@ provided which addresses this issue. @cindex error recovery @cindex recovery from errors -It is not usually acceptable to have a program terminate on a parse +It is not usually acceptable to have a program terminate on a syntax error. For example, a compiler should recover sufficiently to parse the rest of the input file and check it for errors; a calculator should accept another expression. @@ -5259,7 +5259,7 @@ this is unacceptable, then the macro @code{yyclearin} may be used to clear this token. Write the statement @samp{yyclearin;} in the error rule's action. -For example, suppose that on a parse error, an error handling routine is +For example, suppose that on a syntax error, an error handling routine is called that advances the input stream to some point where parsing should once again commence. The next symbol returned by the lexical scanner is probably correct. The previous look-ahead token ought to be discarded @@ -5646,7 +5646,7 @@ after having reduced a rule that produced an @code{exp}, the control flow jumps to state 2. If there is no such transition on a nonterminal symbol, and the lookahead is a @code{NUM}, then this token is shifted on the parse stack, and the control flow jumps to state 1. Any other -lookahead triggers a parse error.'' +lookahead triggers a syntax error.'' @cindex core, item set @cindex item set core @@ -5714,7 +5714,7 @@ because of the item @samp{exp -> exp . '+' exp}, if the lookahead if @samp{+}, it will be shifted on the parse stack, and the automaton control will jump to state 4, corresponding to the item @samp{exp -> exp '+' . exp}. Since there is no default action, any other token than -those listed above will trigger a parse error. +those listed above will trigger a syntax error. The state 3 is named the @dfn{final state}, or the @dfn{accepting state}: @@ -6300,7 +6300,7 @@ The predefined token onto which all undefined values returned by A token name reserved for error recovery. This token may be used in grammar rules so as to allow the Bison parser to recognize an error in the grammar without halting the process. In effect, a sentence -containing an error may be recognized as valid. On a parse error, the +containing an error may be recognized as valid. On a syntax error, the token @code{error} becomes the current look-ahead token. Actions corresponding to @code{error} are then executed, and the look-ahead token is reset to the token that originally caused the violation. @@ -6415,7 +6415,7 @@ symbols and parser action. @xref{Tracing, ,Tracing Your Parser}. @deffn {Macro} yyerrok Macro to cause parser to recover immediately to its normal mode -after a parse error. @xref{Error Recovery}. +after a syntax error. @xref{Error Recovery}. @end deffn @deffn {Function} yyerror @@ -6448,7 +6448,7 @@ variable within @code{yyparse}, and its address is passed to @end deffn @deffn {Variable} yynerrs -Global variable which Bison increments each time there is a parse error. +Global variable which Bison increments each time there is a syntax error. (In a pure parser, it is a local variable within @code{yyparse}.) @xref{Error Reporting, ,The Error Reporting Function @code{yyerror}}. @end deffn @@ -6715,10 +6715,6 @@ A grammar symbol standing for a grammatical construct that can be expressed through rules in terms of smaller constructs; in other words, a construct that is not a token. @xref{Symbols}. -@item Parse error -An error encountered during parsing of an input stream due to invalid -syntax. @xref{Error Recovery}. - @item Parser A function that recognizes valid sentences of a language by analyzing the syntax structure of a set of tokens passed to it from a lexical @@ -6771,6 +6767,10 @@ A data structure where symbol names and associated data are stored during parsing to allow for recognition and use of existing information in repeated uses of a symbol. @xref{Multi-function Calc}. +@item Syntax error +An error encountered during parsing of an input stream due to invalid +syntax. @xref{Error Recovery}. + @item Token A basic, grammatically indivisible unit of a language. The symbol that describes a token in the grammar is a terminal symbol. diff --git a/src/conflicts.c b/src/conflicts.c index 3b4ab7d6..201c9c97 100644 --- a/src/conflicts.c +++ b/src/conflicts.c @@ -252,7 +252,7 @@ resolve_sr_conflict (state_t *state, int ruleno, | Solve the S/R conflicts of STATE using the | | precedence/associativity, and flag it inconsistent if it still has | | conflicts. ERRS can be used as storage to compute the list of | -| lookaheads on which this STATE raises a parse error (%nonassoc). | +| lookaheads on which this STATE raises a syntax error (%nonassoc). | `-------------------------------------------------------------------*/ static void @@ -302,7 +302,7 @@ void conflicts_solve (void) { state_number_t i; - /* List of lookaheads on which we explicitly raise a parse error. */ + /* List of lookaheads on which we explicitly raise a syntax error. */ symbol_t **errs = XMALLOC (symbol_t *, ntokens + 1); conflicts = XCALLOC (char, nstates); diff --git a/src/parse-gram.y b/src/parse-gram.y index e881e3f0..8af3e885 100644 --- a/src/parse-gram.y +++ b/src/parse-gram.y @@ -40,7 +40,7 @@ #include "reader.h" #include "conflicts.h" -/* Produce verbose parse errors. */ +/* Produce verbose syntax errors. */ #define YYERROR_VERBOSE 1 #define YYLLOC_DEFAULT(Current, Rhs, N) \ do { \ @@ -64,7 +64,7 @@ do { \ correctly typed access to it. */ #define yycontrol ((gram_control_t *) gram_control) -/* Request detailed parse error messages, and pass them to GRAM_ERROR. +/* Request detailed syntax error messages, and pass them to GRAM_ERROR. FIXME: depends on the undocumented availability of YYLLOC.t */ #undef yyerror #define yyerror(Msg) \ diff --git a/src/tables.c b/src/tables.c index 17883e1f..e1f0c61e 100644 --- a/src/tables.c +++ b/src/tables.c @@ -82,7 +82,7 @@ static base_t *width = NULL; /* For a given state, N = ACTROW[SYMBOL]: If N = 0, stands for `run the default action'. - If N = MIN, stands for `raise a parse error'. + If N = MIN, stands for `raise a syntax error'. If N > 0, stands for `shift SYMBOL and go to n'. If N < 0, stands for `reduce -N'. */ typedef short action_t; @@ -116,7 +116,7 @@ static int conflict_list_free; static size_t table_size = 32768; base_t *table = NULL; base_t *check = NULL; -/* The value used in TABLE to denote explicit parse errors +/* The value used in TABLE to denote explicit syntax errors (%nonassoc), a negative infinite. First defaults to ACTION_MIN, but in order to keep small tables, renumbered as TABLE_ERROR, which is the smallest (non error) value minus 1. */ diff --git a/src/tables.h b/src/tables.h index 6d56889d..0b729849 100644 --- a/src/tables.h +++ b/src/tables.h @@ -105,7 +105,7 @@ extern int conflict_list_cnt; extern base_t *table; extern base_t *check; -/* The value used in TABLE to denote explicit parse errors +/* The value used in TABLE to denote explicit syntax errors (%nonassoc), a negative infinite. */ extern base_t table_ninf; diff --git a/tests/actions.at b/tests/actions.at index 20030692..366c3d33 100644 --- a/tests/actions.at +++ b/tests/actions.at @@ -322,7 +322,7 @@ thing(1@10): 'x'(1@10) sending: 'x' (value = 2, line 20) thing(2@20): 'x'(2@20) sending: 'x' (value = 3, line 30) -30: parse error, unexpected 'x', expecting ';' +30: syntax error, unexpected 'x', expecting ';' Freeing nterm thing (2@20) Freeing nterm thing (1@10) Freeing nterm thing (0@0) @@ -344,7 +344,7 @@ thing(10@100): 'x'(10@100) sending: ';' (value = 11, line 110) line(10@100): thing(10@100) ';' sending: 'y' (value = 12, line 120) -120: parse error, unexpected $undefined, expecting $end or 'x' +120: syntax error, unexpected $undefined, expecting $end or 'x' sending: EOF Freeing nterm line (10@100) Freeing nterm line (7@70) diff --git a/tests/calc.at b/tests/calc.at index c3873e57..e79cdb2e 100644 --- a/tests/calc.at +++ b/tests/calc.at @@ -353,7 +353,7 @@ m4_bmatch([$1], # [NUM-DEBUG-LINES], # [VERBOSE-AND-LOCATED-ERROR-MESSAGE]) # --------------------------------------------------------- -# Run `calc' on INPUT, and expect a `parse error' message. +# Run `calc' on INPUT, and expect a `syntax error' message. # # If INPUT starts with a slash, it is used as absolute input file name, # otherwise as contents. @@ -362,7 +362,7 @@ m4_bmatch([$1], # is correctly output on stderr. # # If BISON-OPTIONS contains `%error-verbose', then make sure the -# IF-YYERROR-VERBOSE message is properly output after `parse error, ' +# IF-YYERROR-VERBOSE message is properly output after `syntax error, ' # on STDERR. # # If BISON-OPTIONS contains `%debug' but not `%glr', then NUM-STDERR-LINES @@ -406,7 +406,7 @@ AT_YYERROR_SEES_LOC_IF([], mv at-expout expout]]) # 4. If error-verbose is not used, strip the`, unexpected....' part. m4_bmatch([$1], [%error-verbose], [], -[[sed 's/parse error, .*$/parse error/' expout >at-expout +[[sed 's/syntax error, .*$/syntax error/' expout >at-expout mv at-expout expout]]) # 5. Check AT_CHECK([cat stderr], 0, [expout]) @@ -497,30 +497,30 @@ _AT_CHECK_CALC([$1], (2^2)^3 = 64], [486]) -# Some parse errors. +# Some syntax errors. _AT_CHECK_CALC_ERROR([$1], [1], [0 0], [11], - [1.3-1.4: parse error, unexpected "number"]) + [1.3-1.4: syntax error, unexpected "number"]) _AT_CHECK_CALC_ERROR([$1], [1], [1//2], [15], - [1.3-1.4: parse error, unexpected '/', expecting "number" or '-' or '(']) + [1.3-1.4: syntax error, unexpected '/', expecting "number" or '-' or '(']) _AT_CHECK_CALC_ERROR([$1], [1], [error], [4], - [1.1-1.2: parse error, unexpected $undefined, expecting "number" or '-' or '\n' or '(']) + [1.1-1.2: syntax error, unexpected $undefined, expecting "number" or '-' or '\n' or '(']) _AT_CHECK_CALC_ERROR([$1], [1], [1 = 2 = 3], [22], - [1.7-1.8: parse error, unexpected '=']) + [1.7-1.8: syntax error, unexpected '=']) _AT_CHECK_CALC_ERROR([$1], [1], [ +1], [14], - [2.1-2.2: parse error, unexpected '+']) + [2.1-2.2: syntax error, unexpected '+']) # Exercise error messages with EOF: work on an empty file. _AT_CHECK_CALC_ERROR([$1], [1], [/dev/null], [4], - [1.1-1.2: parse error, unexpected "end of input", expecting "number" or '-' or '\n' or '(']) + [1.1-1.2: syntax error, unexpected "end of input", expecting "number" or '-' or '\n' or '(']) # Exercise the error token: without it, we die at the first error, # hence be sure i. to have several errors, ii. to test the action # associated to `error'. _AT_CHECK_CALC_ERROR([$1], [0], [(1 ++ 2) + (0 0) = 1], [82], -[1.5-1.6: parse error, unexpected '+', expecting "number" or '-' or '(' -1.15-1.16: parse error, unexpected "number" +[1.5-1.6: syntax error, unexpected '+', expecting "number" or '-' or '(' +1.15-1.16: syntax error, unexpected "number" calc: error: 0 != 1]) AT_CHECK_POPDEFS diff --git a/tests/conflicts.at b/tests/conflicts.at index dbc9be58..f3fe7821 100644 --- a/tests/conflicts.at +++ b/tests/conflicts.at @@ -108,16 +108,16 @@ AT_PARSER_CHECK([./input '0<0']) # no one has ever spotted it! The messages are *wrong*: there should # be nothing there, it should be expected eof. AT_PARSER_CHECK([./input '0<0<0'], [1], [], - [parse error, unexpected '<', expecting '<' or '>' + [syntax error, unexpected '<', expecting '<' or '>' ]) AT_PARSER_CHECK([./input '0>0']) AT_PARSER_CHECK([./input '0>0>0'], [1], [], - [parse error, unexpected '>', expecting '<' or '>' + [syntax error, unexpected '>', expecting '<' or '>' ]) AT_PARSER_CHECK([./input '0<0>0'], [1], [], - [parse error, unexpected '>', expecting '<' or '>' + [syntax error, unexpected '>', expecting '<' or '>' ]) AT_CLEANUP diff --git a/tests/cxx-type.at b/tests/cxx-type.at index 7e58fa4a..5ad9cf49 100644 --- a/tests/cxx-type.at +++ b/tests/cxx-type.at @@ -241,11 +241,11 @@ z q + ]]) m4_define([_AT_GLR_STDERR], -[[parse error +[[syntax error ]]) m4_define([_AT_VERBOSE_GLR_STDERR], -[[parse error, unexpected ID, expecting '=' or '+' or ')' +[[syntax error, unexpected ID, expecting '=' or '+' or ')' ]]) ## ---------------------------------------------------- ## diff --git a/tests/regression.at b/tests/regression.at index db49790d..f3b98cad 100644 --- a/tests/regression.at +++ b/tests/regression.at @@ -298,7 +298,7 @@ input.y:5.1-17: invalid directive: `%a-does-not-exist' input.y:6.1: invalid character: `%' input.y:6.2: invalid character: `-' input.y:7.1-8.0: missing `%}' at end of file -input.y:7.1-8.0: parse error, unexpected "%{...%}", expecting ";" or "|" +input.y:7.1-8.0: syntax error, unexpected "%{...%}", expecting ";" or "|" ]]) AT_CLEANUP -- 2.47.2