bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fix %error-verbose for conflicts resolved by %nonassoc.


From: Joel E. Denny
Subject: Re: Fix %error-verbose for conflicts resolved by %nonassoc.
Date: Tue, 25 Aug 2009 20:41:04 -0400 (EDT)
User-agent: Alpine 1.00 (DEB 882 2007-12-20)

On Tue, 25 Aug 2009, Joel E. Denny wrote:

> I feel this area is a bit too subtle to include this change 
> in branch-2.4.2.

At least I got that right.

As for the rest, the following patch hopefully fixes it.  I pushed it to 
master and a similar patch to branch-2.5.

> I'm not proud of propagating more preprocessor macros to yacc.c.  Maybe 
> this is a good place for some more functions like the ones Akim has 
> discussed recently.  Also, we could probably find better names than NINF.  
> For example, error_action or default_action.

They're still macros in yacc.c, but I've chosen better names, and I've 
added corresponding functions in lalr1.cc and lalr1.java.

>From f2b30bdf3713e6fa9fafd0fc6caed68e38248ebc Mon Sep 17 00:00:00 2001
From: Joel E. Denny <address@hidden>
Date: Tue, 25 Aug 2009 19:41:49 -0400
Subject: [PATCH] More fixes related to last two patches.

* data/bison.m4 (b4_integral_parser_tables_map): Fix YYTABLE
comments: zero indicates syntax error not default action.
* data/c.m4 (b4_table_value_equals): Comment that YYID must be
defined.
* data/glr.c (yyis_pact_ninf): Rename to...
(yypact_value_is_default): ... this.
(yyisDefaultedState): Update for rename.
(yyis_table_ninf): Rename to...
(yytable_value_is_error): ... this, and check for value zero
besides just YYTABLE_NINF.
(yygetLRActions): Check for default value from yypact.  It
appears that this check is always performed before this function
is invoked, and so adding the check here is probably redundant.
However, the code may evolve after this subtlety is forgotten.
Also, update for rename to yytable_value_is_error.  Because that
macro now checks for zero, a different but equivalent branch of
the if-then-else here is evaluated.
(yyreportSyntaxError): Update for rename to
yytable_value_is_error.  The zero condition was mishandled
before.
(yyrecoverSyntaxError): Update for renames.  No behavioral
changes.
* data/lalr1.cc, data/lalr1.java (yy_pact_value_is_default_):
New function.
(yy_table_value_is_error_): New function.
(parse): Use new functions where possible.  No behavioral
changes.
(yysyntax_error_, yysyntax_error): Use yy_table_value_is_error_.
The zero condition was mishandled before.
* data/yacc.c (yyis_pact_ninf): Rename to...
(yypact_value_is_default): ... this.
(yyis_table_ninf): Rename to...
(yytable_value_is_error): ... this, and check for value zero
besides just YYTABLE_NINF.
(yysyntax_error): Update for rename to yytable_value_is_error.
The zero condition was mishandled before.
(yyparse): Update for renames.  No behavioral changes.
* src/tables.h: Improve comments about yypact, yytable, etc.
more.  Most importantly, say yytable value of zero means syntax
error not default action.
---
 ChangeLog        |   44 ++++++
 data/bison.m4    |    3 +-
 data/c.m4        |    3 +-
 data/glr.c       |   22 ++--
 data/lalr1.cc    |   28 +++-
 data/lalr1.java  |   28 +++-
 data/yacc.c      |   15 +-
 src/parse-gram.c |  438 +++++++++++++++++++++++++++---------------------------
 src/parse-gram.h |    6 +-
 src/tables.h     |   58 ++++----
 10 files changed, 367 insertions(+), 278 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 6624a0c..93a7499 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,49 @@
 2009-08-25  Joel E. Denny  <address@hidden>
 
+       More fixes related to last two patches.
+       * data/bison.m4 (b4_integral_parser_tables_map): Fix YYTABLE
+       comments: zero indicates syntax error not default action.
+       * data/c.m4 (b4_table_value_equals): Comment that YYID must be
+       defined.
+       * data/glr.c (yyis_pact_ninf): Rename to...
+       (yypact_value_is_default): ... this.
+       (yyisDefaultedState): Update for rename.
+       (yyis_table_ninf): Rename to...
+       (yytable_value_is_error): ... this, and check for value zero
+       besides just YYTABLE_NINF.
+       (yygetLRActions): Check for default value from yypact.  It
+       appears that this check is always performed before this function
+       is invoked, and so adding the check here is probably redundant.
+       However, the code may evolve after this subtlety is forgotten.
+       Also, update for rename to yytable_value_is_error.  Because that
+       macro now checks for zero, a different but equivalent branch of
+       the if-then-else here is evaluated.
+       (yyreportSyntaxError): Update for rename to
+       yytable_value_is_error.  The zero condition was mishandled
+       before.
+       (yyrecoverSyntaxError): Update for renames.  No behavioral
+       changes.
+       * data/lalr1.cc, data/lalr1.java (yy_pact_value_is_default_):
+       New function.
+       (yy_table_value_is_error_): New function.
+       (parse): Use new functions where possible.  No behavioral
+       changes.
+       (yysyntax_error_, yysyntax_error): Use yy_table_value_is_error_.
+       The zero condition was mishandled before.
+       * data/yacc.c (yyis_pact_ninf): Rename to...
+       (yypact_value_is_default): ... this.
+       (yyis_table_ninf): Rename to...
+       (yytable_value_is_error): ... this, and check for value zero
+       besides just YYTABLE_NINF.
+       (yysyntax_error): Update for rename to yytable_value_is_error.
+       The zero condition was mishandled before.
+       (yyparse): Update for renames.  No behavioral changes.
+       * src/tables.h: Improve comments about yypact, yytable, etc.
+       more.  Most importantly, say yytable value of zero means syntax
+       error not default action.
+
+2009-08-25  Joel E. Denny  <address@hidden>
+
        Fix %error-verbose for conflicts resolved by %nonassoc.
        * NEWS (2.5): Document.
        * data/glr.c (yyreportSyntaxError): Fix this by checking
diff --git a/data/bison.m4 b/data/bison.m4
index 4ca6cee..ef8f778 100644
--- a/data/bison.m4
+++ b/data/bison.m4
@@ -266,8 +266,7 @@ $1([defgoto], [b4_defgoto], [[YYDEFGOTO[NTERM-NUM].]])
 $1([table], [b4_table],
    [[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, syntax error.]])
+number is the opposite.  If zero or YYTABLE_NINF, syntax error.]])
 
 $1([check], [b4_check])
 
diff --git a/data/c.m4 b/data/c.m4
index 3ba48db..5cd404d 100644
--- a/data/c.m4
+++ b/data/c.m4
@@ -161,7 +161,8 @@ m4_define([b4_int_type_for],
 # --------------------------------------------
 # Without inducing a comparison warning from the compiler, check if the
 # literal value LITERAL equals VALUE from table TABLE, which must have
-# TABLE_min and TABLE_max defined.
+# TABLE_min and TABLE_max defined.  YYID must be defined as an identity
+# function that suppresses warnings about constant conditions.
 m4_define([b4_table_value_equals],
 [m4_if(m4_eval($3 < m4_indir([b4_]$1[_min])
                || m4_indir([b4_]$1[_max]) < $3), [1],
diff --git a/data/glr.c b/data/glr.c
index 85a5aff..8d37070 100644
--- a/data/glr.c
+++ b/data/glr.c
@@ -953,7 +953,7 @@ yylhsNonterm (yyRuleNum yyrule)
   return yyr1[yyrule];
 }
 
-#define yyis_pact_ninf(yystate) \
+#define yypact_value_is_default(yystate) \
   ]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
 
 /** True iff LR state STATE has only a default reduction (regardless
@@ -961,7 +961,7 @@ yylhsNonterm (yyRuleNum yyrule)
 static inline yybool
 yyisDefaultedState (yyStateNum yystate)
 {
-  return yyis_pact_ninf (yypact[yystate]);
+  return yypact_value_is_default (yypact[yystate]);
 }
 
 /** The default reduction for STATE, assuming it has one.  */
@@ -971,8 +971,9 @@ yydefaultAction (yyStateNum yystate)
   return yydefact[yystate];
 }
 
-#define yyis_table_ninf(yytable_value) \
-  ]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf])[
+#define yytable_value_is_error(yytable_value) \
+  (]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf])[ \
+   || ]b4_table_value_equals([[table]], [[yytable_value]], [[0]])[)
 
 /** Set *YYACTION to the action to take in YYSTATE on seeing YYTOKEN.
  *  Result R means
@@ -987,12 +988,13 @@ yygetLRActions (yyStateNum yystate, int yytoken,
                int* yyaction, const short int** yyconflicts)
 {
   int yyindex = yypact[yystate] + yytoken;
-  if (yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken)
+  if (yypact_value_is_default (yypact[yystate])
+      || yyindex < 0 || YYLAST < yyindex || yycheck[yyindex] != yytoken)
     {
       *yyaction = -yydefact[yystate];
       *yyconflicts = yyconfl;
     }
-  else if (! yyis_table_ninf (yytable[yyindex]))
+  else if (! yytable_value_is_error (yytable[yyindex]))
     {
       *yyaction = yytable[yyindex];
       *yyconflicts = yyconfl + yyconflp[yyindex];
@@ -2061,7 +2063,7 @@ yyreportSyntaxError (yyGLRStack* 
yystackp]b4_user_formals[)
 
          for (yyx = yyxbegin; yyx < yyxend; ++yyx)
            if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-               && !yyis_table_ninf (yytable[yyx + yyn]))
+               && !yytable_value_is_error (yytable[yyx + yyn]))
              {
                if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
                  {
@@ -2172,7 +2174,7 @@ yyrecoverSyntaxError (yyGLRStack* 
yystackp]b4_user_formals[)
            YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
          }
        yyj = yypact[yystackp->yytops.yystates[0]->yylrState];
-       if (yyis_pact_ninf (yyj))
+       if (yypact_value_is_default (yyj))
          return;
        yyj += yytoken;
        if (yyj < 0 || YYLAST < yyj || yycheck[yyj] != yytoken)
@@ -2180,7 +2182,7 @@ yyrecoverSyntaxError (yyGLRStack* 
yystackp]b4_user_formals[)
            if (yydefact[yystackp->yytops.yystates[0]->yylrState] != 0)
              return;
          }
-       else if (yytable[yyj] != 0 && ! yyis_table_ninf (yytable[yyj]))
+       else if (! yytable_value_is_error (yytable[yyj]))
          return;
       }
 
@@ -2201,7 +2203,7 @@ yyrecoverSyntaxError (yyGLRStack* 
yystackp]b4_user_formals[)
     {
       yyGLRState *yys = yystackp->yytops.yystates[0];
       yyj = yypact[yys->yylrState];
-      if (! yyis_pact_ninf (yyj))
+      if (! yypact_value_is_default (yyj))
        {
          yyj += YYTERROR;
          if (0 <= yyj && yyj <= YYLAST && yycheck[yyj] == YYTERROR
diff --git a/data/lalr1.cc b/data/lalr1.cc
index 1e4c856..36c8d58 100644
--- a/data/lalr1.cc
+++ b/data/lalr1.cc
@@ -245,6 +245,14 @@ do {                                                       
     \
     /// \param yylhs     the nonterminal to push on the stack
     state_type yy_lr_goto_state_ (state_type yystate, int yylhs);
 
+    /// Whether the given \c yypact_ value indicates a defaulted state.
+    /// \param yyvalue   the value to check
+    static bool yy_pact_value_is_default_ (int yyvalue);
+
+    /// Whether the given \c yytable_ value indicates a syntax error.
+    /// \param yyvalue   the value to check
+    static bool yy_table_value_is_error_ (int yyvalue);
+
     /// Internal symbol numbers.
     typedef ]b4_int_type_for([b4_translate])[ token_number_type;
     static const ]b4_int_type(b4_pact_ninf, b4_pact_ninf)[ yypact_ninf_;
@@ -651,6 +659,18 @@ b4_percent_code_get[]dnl
       return yydefgoto_[yylhs - yyntokens_];
   }
 
+  inline bool
+  ]b4_parser_class_name[::yy_pact_value_is_default_ (int yyvalue)
+  {
+    return yyvalue == yypact_ninf_;
+  }
+
+  inline bool
+  ]b4_parser_class_name[::yy_table_value_is_error_ (int yyvalue)
+  {
+    return yyvalue == 0 || yyvalue == yytable_ninf_;
+  }
+
   int
   ]b4_parser_class_name[::parse ()
   {
@@ -709,7 +729,7 @@ m4_popdef([b4_at_dollar])])dnl
 
     /* Try to take a decision without lookahead.  */
     yyn = yypact_[yystack_[0].state];
-    if (yyn == yypact_ninf_)
+    if (yy_pact_value_is_default_ (yyn))
       goto yydefault;
 
     /* Read a lookahead token.  */
@@ -737,7 +757,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
     yyn = yytable_[yyn];
     if (yyn <= 0)
       {
-       if (yyn == 0 || yyn == yytable_ninf_)
+       if (yy_table_value_is_error_ (yyn))
          goto yyerrlab;
        yyn = -yyn;
        goto yyreduce;
@@ -887,7 +907,7 @@ m4_ifdef([b4_lex_param], [, ]b4_lex_param)));])[
       for (;;)
         {
           yyn = yypact_[yystack_[0].state];
-          if (yyn != yypact_ninf_)
+          if (!yy_pact_value_is_default_ (yyn))
             {
               yyn += yyterror_;
               if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
@@ -972,7 +992,7 @@ b4_error_verbose_if([state_type yystate, int yytoken],
         yyarg[yycount++] = yytname_[yytoken];
        for (int yyx = yyxbegin; yyx < yyxend; ++yyx)
          if (yycheck_[yyx + yyn] == yyx && yyx != yyterror_
-             && yytable_[yyx + yyn] != yytable_ninf_)
+             && !yy_table_value_is_error_ (yytable_[yyx + yyn]))
           {
             if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
             {
diff --git a/data/lalr1.java b/data/lalr1.java
index 646b777..5f0cfd7 100644
--- a/data/lalr1.java
+++ b/data/lalr1.java
@@ -533,7 +533,7 @@ m4_popdef([b4_at_dollar])])dnl
 
         /* Take a decision.  First try without lookahead.  */
         yyn = yypact_[yystate];
-        if (yyn == yypact_ninf_)
+        if (yy_pact_value_is_default_ (yyn))
           {
             label = YYDEFAULT;
             break;
@@ -572,7 +572,7 @@ m4_popdef([b4_at_dollar])])dnl
         /* <= 0 means reduce or error.  */
         else if ((yyn = yytable_[yyn]) <= 0)
           {
-            if (yyn == 0 || yyn == yytable_ninf_)
+            if (yy_table_value_is_error_ (yyn))
               label = YYFAIL;
             else
               {
@@ -676,7 +676,7 @@ m4_popdef([b4_at_dollar])])dnl
         for (;;)
           {
             yyn = yypact_[yystate];
-            if (yyn != yypact_ninf_)
+            if (!yy_pact_value_is_default_ (yyn))
               {
                 yyn += yyterror_;
                 if (0 <= yyn && yyn <= yylast_ && yycheck_[yyn] == yyterror_)
@@ -745,7 +745,7 @@ m4_popdef([b4_at_dollar])])dnl
             int count = 0;
             for (int x = yyxbegin; x < yyxend; ++x)
               if (yycheck_[x + yyn] == x && x != yyterror_
-                  && yycheck_[x + yyn] != yytable_ninf_)
+                  && !yy_table_value_is_error_ (yycheck_[x + yyn]))
                 ++count;
 
             // FIXME: This method of building the message is not compatible
@@ -757,7 +757,7 @@ m4_popdef([b4_at_dollar])])dnl
                 count = 0;
                 for (int x = yyxbegin; x < yyxend; ++x)
                   if (yycheck_[x + yyn] == x && x != yyterror_
-                      && yycheck_[x + yyn] != yytable_ninf_)
+                      && !yy_table_value_is_error_ (yycheck_[x + yyn]))
                     {
                       res.append (count++ == 0 ? ", expecting " : " or ");
                       res.append (yytnamerr_ (yytname_[x]));
@@ -770,6 +770,24 @@ m4_popdef([b4_at_dollar])])dnl
     return "syntax error";
   }
 
+  /**
+   * Whether the given <code>yypact_</code> value indicates a defaulted state.
+   * @@param yyvalue   the value to check
+   */
+  private static boolean yy_pact_value_is_default_ (int yyvalue)
+  {
+    return yyvalue == yypact_ninf_;
+  }
+
+  /**
+   * Whether the given <code>yytable_</code> value indicates a syntax error.
+   * @@param yyvalue   the value to check
+   */
+  private static boolean yy_table_value_is_error_ (int yyvalue)
+  {
+    return yyvalue == 0 || yyvalue == yytable_ninf_;
+  }
+
   private static final ]b4_int_type_for([b4_pact])[ yypact_ninf_ = 
]b4_pact_ninf[;
   private static final ]b4_int_type_for([b4_table])[ yytable_ninf_ = 
]b4_table_ninf[;
 
diff --git a/data/yacc.c b/data/yacc.c
index acc1118..505b09e 100644
--- a/data/yacc.c
+++ b/data/yacc.c
@@ -525,13 +525,14 @@ static const ]b4_int_type_for([b4_toknum])[ yytoknum[] =
 
 #define YYPACT_NINF ]b4_pact_ninf[
 
-#define yyis_pact_ninf(yystate) \
+#define yypact_value_is_default(yystate) \
   ]b4_table_value_equals([[pact]], [[yystate]], [b4_pact_ninf])[
 
 #define YYTABLE_NINF ]b4_table_ninf[
 
-#define yyis_table_ninf(yytable_value) \
-  ]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf])[
+#define yytable_value_is_error(yytable_value) \
+  (]b4_table_value_equals([[table]], [[yytable_value]], [b4_table_ninf])[ \
+  || ]b4_table_value_equals([[table]], [[yytable_value]], [[0]])[)
 
 ]b4_parser_tables_define[
 
@@ -870,7 +871,7 @@ yysyntax_error (char *yyresult, int yystate, int yytoken)
 
       for (yyx = yyxbegin; yyx < yyxend; ++yyx)
        if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR
-           && !yyis_table_ninf (yytable[yyx + yyn]))
+           && !yytable_value_is_error (yytable[yyx + yyn]))
          {
            if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
              {
@@ -1279,7 +1280,7 @@ yybackup:
 
   /* First try to decide what to do without reference to lookahead token.  */
   yyn = yypact[yystate];
-  if (yyis_pact_ninf (yyn))
+  if (yypact_value_is_default (yyn))
     goto yydefault;
 
   /* Not known => get a lookahead token if don't already have one.  */
@@ -1329,7 +1330,7 @@ yyread_pushed_token:]])[
   yyn = yytable[yyn];
   if (yyn <= 0)
     {
-      if (yyn == 0 || yyis_table_ninf (yyn))
+      if (yytable_value_is_error (yyn))
        goto yyerrlab;
       yyn = -yyn;
       goto yyreduce;
@@ -1513,7 +1514,7 @@ yyerrlab1:
   for (;;)
     {
       yyn = yypact[yystate];
-      if (!yyis_pact_ninf (yyn))
+      if (!yypact_value_is_default (yyn))
        {
          yyn += YYTERROR;
          if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
diff --git a/src/tables.h b/src/tables.h
index b21fa7b..9b52f09 100644
--- a/src/tables.h
+++ b/src/tables.h
@@ -45,6 +45,24 @@
 
    YYSTOS[S] = the symbol number of the symbol that leads to state S.
 
+   YYFINAL = the state number of the termination state.
+
+   YYTABLE = a vector filled with portions for different uses, found
+   via YYPACT and YYPGOTO.
+
+   YYLAST ( = high) the number of the last element of YYTABLE, i.e.,
+   sizeof (YYTABLE) - 1.
+
+   YYCHECK = a vector indexed in parallel with YYTABLE.  It indicates,
+   in a roundabout way, the bounds of the portion you are trying to
+   examine.
+
+   Suppose that the portion of YYTABLE starts at index P and the index
+   to be examined within the portion is I.  Then if YYCHECK[P+I] != I,
+   I is outside the bounds of what is actually allocated, and the
+   default (from YYDEFACT or YYDEFGOTO) should be used.  Otherwise,
+   YYTABLE[P+I] should be used.
+
    YYDEFACT[S] = default reduction number in state s.  Performed when
    YYTABLE doesn't specify something else to do.  Zero means the default
    is an error.
@@ -58,10 +76,10 @@
    YYTABLE to find out what action to perform.
 
    If YYPACT[S] == YYPACT_NINF, if YYPACT[S] + I is outside the bounds
-   of YYTABLE (from 0 to YYLAST), or if YYCHECK indicates that I is
-   outside the bounds of the portion for S, then the default action
-   (from YYDEFACT and YYDEFGOTO) should be used instead of YYTABLE.
-   Otherwise, the value YYTABLE[YYPACT[S] + I] should be used even if
+   of YYTABLE (from 0 to YYLAST), or I is outside the bounds for portion
+   S (that is, YYCHECK[YYPACT[S] + I] != I), then the default action
+   (that is, YYDEFACT[S]) should be used instead of YYTABLE.  Otherwise,
+   the value YYTABLE[YYPACT[S] + I] should be used even if
    YYPACT[S] < 0.
 
    If the value in YYTABLE is positive, we shift the token and go to
@@ -69,33 +87,19 @@
 
    If the value is negative, it is minus a rule number to reduce by.
 
-   If the value is zero, the default action from YYDEFACT[S] is used.
-
-   If the value is YYTABLE_NINF, it's a syntax error.
+   If the value is zero or YYTABLE_NINF, it's a syntax error.
 
    YYPGOTO[I] = the index in YYTABLE of the portion describing what to
    do after reducing a rule that derives variable I + NTOKENS.  This
    portion is indexed by the parser state number, S, as of before the
-   text for this nonterminal was read.  The value from YYTABLE is the
-   state to go to if the corresponding value in YYCHECK is S.
-
-   YYTABLE = a vector filled with portions for different uses, found
-   via YYPACT and YYPGOTO.
-
-   YYCHECK = a vector indexed in parallel with YYTABLE.  It indicates,
-   in a roundabout way, the bounds of the portion you are trying to
-   examine.
-
-   Suppose that the portion of YYTABLE starts at index P and the index
-   to be examined within the portion is I.  Then if YYCHECK[P+I] != I,
-   I is outside the bounds of what is actually allocated, and the
-   default (from YYDEFACT or YYDEFGOTO) should be used.  Otherwise,
-   YYTABLE[P+I] should be used.
-
-   YYFINAL = the state number of the termination state.
-
-   YYLAST ( = high) the number of the last element of YYTABLE, i.e.,
-   sizeof (YYTABLE) - 1.  */
+   text for this nonterminal was read.
+
+   If YYPGOTO[I] + S is outside the bounds of YYTABLE (from 0 to YYLAST)
+   or if S is outside the bounds of the portion for I (that is,
+   YYCHECK[YYPGOTO[I] + S] != S), then the default state (that is,
+   YYDEFGOTO[I]) should be used instead of YYTABLE.  Otherwise,
+   YYTABLE[YYPGOTO[I] + S] is the state to go to even if YYPGOTO[I] < 0.
+*/
 
 extern int nvectors;
 
-- 
1.5.4.3





reply via email to

[Prev in Thread] Current Thread [Next in Thread]