зеркало из https://github.com/mozilla/gecko-dev.git
Bug 175668: merged the fix for the pointer aliasing bug from the 2001
version of dtoa.c. Removed the workaround of disabling compiler optimizations on AIX. Modified Files: Makefile.in prdtoa.c
This commit is contained in:
Родитель
7fe4fdbc33
Коммит
72e5b42617
|
@ -82,14 +82,6 @@ RELEASE_BINS = $(srcdir)/compile-et.pl $(srcdir)/prerr.properties
|
|||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
# An AIX Optimization bug causes PR_dtoa() to produce wrong result.
|
||||
# This suppresses optimization for this single compilation unit.
|
||||
ifeq ($(OS_ARCH), AIX)
|
||||
$(OBJDIR)/prdtoa.o: prdtoa.c
|
||||
@$(MAKE_OBJDIR)
|
||||
$(CC) -o $@ -c $(filter-out -O, $(CFLAGS)) $<
|
||||
endif
|
||||
|
||||
#
|
||||
# Generate prerr.h, prerr.c, and prerr.properties from prerr.et.
|
||||
#
|
||||
|
|
|
@ -123,6 +123,11 @@
|
|||
* if memory is available and otherwise does something you deem
|
||||
* appropriate. If MALLOC is undefined, malloc will be invoked
|
||||
* directly -- and assumed always to succeed.
|
||||
* #define YES_ALIAS to permit aliasing certain double values with
|
||||
* arrays of unsigned Longs. This leads to slightly better code with
|
||||
* some compilers and was always used prior to 19990916, but it
|
||||
* is not strictly legal and can cause trouble with aggressively
|
||||
* optimizing compilers (e.g., gcc 2.95.1 under -O2).
|
||||
*/
|
||||
#if defined(IS_LITTLE_ENDIAN)
|
||||
#define IEEE_8087
|
||||
|
@ -226,6 +231,10 @@ extern void *MALLOC(size_t);
|
|||
Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
|
||||
#endif
|
||||
|
||||
typedef union { double d; unsigned Long L[2]; } U;
|
||||
|
||||
#ifdef YES_ALIAS
|
||||
#define dval(x) x
|
||||
#ifdef IEEE_8087
|
||||
#define word0(x) ((unsigned Long *)&x)[1]
|
||||
#define word1(x) ((unsigned Long *)&x)[0]
|
||||
|
@ -233,6 +242,16 @@ Exactly one of IEEE_8087, IEEE_MC68k, VAX, or IBM should be defined.
|
|||
#define word0(x) ((unsigned Long *)&x)[0]
|
||||
#define word1(x) ((unsigned Long *)&x)[1]
|
||||
#endif
|
||||
#else
|
||||
#ifdef IEEE_8087
|
||||
#define word0(x) ((U*)&x)->L[1]
|
||||
#define word1(x) ((U*)&x)->L[0]
|
||||
#else
|
||||
#define word0(x) ((U*)&x)->L[0]
|
||||
#define word1(x) ((U*)&x)->L[1]
|
||||
#endif
|
||||
#define dval(x) ((U*)&x)->d
|
||||
#endif
|
||||
|
||||
/* The following definition of Storeinc is appropriate for MIPS processors.
|
||||
* An alternative that might be better on some machines is
|
||||
|
@ -914,7 +933,7 @@ static double ulp(double x)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
return a;
|
||||
return dval(a);
|
||||
}
|
||||
|
||||
static double
|
||||
|
@ -984,7 +1003,7 @@ ret_d:
|
|||
#undef d0
|
||||
#undef d1
|
||||
#endif
|
||||
return d;
|
||||
return dval(d);
|
||||
}
|
||||
|
||||
static Bigint *
|
||||
|
@ -1127,8 +1146,8 @@ ratio
|
|||
double da, db;
|
||||
PRInt32 k, ka, kb;
|
||||
|
||||
da = b2d(a, &ka);
|
||||
db = b2d(b, &kb);
|
||||
dval(da) = b2d(a, &ka);
|
||||
dval(db) = b2d(b, &kb);
|
||||
#ifdef Pack_32
|
||||
k = ka - kb + 32*(a->wds - b->wds);
|
||||
#else
|
||||
|
@ -1138,13 +1157,13 @@ ratio
|
|||
if (k > 0) {
|
||||
word0(da) += (k >> 2)*Exp_msk1;
|
||||
if (k &= 3)
|
||||
da *= 1 << k;
|
||||
dval(da) *= 1 << k;
|
||||
}
|
||||
else {
|
||||
k = -k;
|
||||
word0(db) += (k >> 2)*Exp_msk1;
|
||||
if (k &= 3)
|
||||
db *= 1 << k;
|
||||
dval(db) *= 1 << k;
|
||||
}
|
||||
#else
|
||||
if (k > 0)
|
||||
|
@ -1154,7 +1173,7 @@ ratio
|
|||
word0(db) += k*Exp_msk1;
|
||||
}
|
||||
#endif
|
||||
return da / db;
|
||||
return dval(da) / dval(db);
|
||||
}
|
||||
|
||||
static CONST double
|
||||
|
@ -1219,7 +1238,7 @@ PR_strtod(CONST char *s00, char **se)
|
|||
if (!_pr_initialized) _PR_ImplicitInitialization();
|
||||
|
||||
sign = nz0 = nz = 0;
|
||||
rv = 0.;
|
||||
dval(rv) = 0.;
|
||||
for(s = s00;;s++) switch(*s) {
|
||||
case '-':
|
||||
sign = 1;
|
||||
|
@ -1341,9 +1360,9 @@ dig_done:
|
|||
if (!nd0)
|
||||
nd0 = nd;
|
||||
k = nd < DBL_DIG + 1 ? nd : DBL_DIG + 1;
|
||||
rv = y;
|
||||
dval(rv) = y;
|
||||
if (k > 9)
|
||||
rv = tens[k - 9] * rv + z;
|
||||
dval(rv) = tens[k - 9] * dval(rv) + z;
|
||||
bd0 = 0;
|
||||
if (nd <= DBL_DIG
|
||||
#ifndef RND_PRODQUOT
|
||||
|
@ -1357,7 +1376,7 @@ dig_done:
|
|||
#ifdef VAX
|
||||
goto vax_ovfl_check;
|
||||
#else
|
||||
/* rv = */ rounded_product(rv, tens[e]);
|
||||
/* rv = */ rounded_product(dval(rv), tens[e]);
|
||||
goto ret;
|
||||
#endif
|
||||
}
|
||||
|
@ -1367,27 +1386,27 @@ dig_done:
|
|||
* this for larger i values.
|
||||
*/
|
||||
e -= i;
|
||||
rv *= tens[i];
|
||||
dval(rv) *= tens[i];
|
||||
#ifdef VAX
|
||||
/* VAX exponent range is so narrow we must
|
||||
* worry about overflow here...
|
||||
*/
|
||||
vax_ovfl_check:
|
||||
word0(rv) -= P*Exp_msk1;
|
||||
/* rv = */ rounded_product(rv, tens[e]);
|
||||
/* rv = */ rounded_product(dval(rv), tens[e]);
|
||||
if ((word0(rv) & Exp_mask)
|
||||
> Exp_msk1*(DBL_MAX_EXP+Bias-1-P))
|
||||
goto ovfl;
|
||||
word0(rv) += P*Exp_msk1;
|
||||
#else
|
||||
/* rv = */ rounded_product(rv, tens[e]);
|
||||
/* rv = */ rounded_product(dval(rv), tens[e]);
|
||||
#endif
|
||||
goto ret;
|
||||
}
|
||||
}
|
||||
#ifndef Inaccurate_Divide
|
||||
else if (e >= -Ten_pmax) {
|
||||
/* rv = */ rounded_quotient(rv, tens[-e]);
|
||||
/* rv = */ rounded_quotient(dval(rv), tens[-e]);
|
||||
goto ret;
|
||||
}
|
||||
#endif
|
||||
|
@ -1398,13 +1417,13 @@ dig_done:
|
|||
|
||||
if (e1 > 0) {
|
||||
if ((i = e1 & 15) != 0)
|
||||
rv *= tens[i];
|
||||
dval(rv) *= tens[i];
|
||||
if (e1 &= ~15) {
|
||||
if (e1 > DBL_MAX_10_EXP) {
|
||||
ovfl:
|
||||
PR_SetError(PR_RANGE_ERROR, 0);
|
||||
#ifdef __STDC__
|
||||
rv = HUGE_VAL;
|
||||
dval(rv) = HUGE_VAL;
|
||||
#else
|
||||
/* Can't trust HUGE_VAL */
|
||||
#ifdef IEEE_Arith
|
||||
|
@ -1422,10 +1441,10 @@ dig_done:
|
|||
if (e1 >>= 4) {
|
||||
for(j = 0; e1 > 1; j++, e1 >>= 1)
|
||||
if (e1 & 1)
|
||||
rv *= bigtens[j];
|
||||
dval(rv) *= bigtens[j];
|
||||
/* The last multiplication could overflow. */
|
||||
word0(rv) -= P*Exp_msk1;
|
||||
rv *= bigtens[j];
|
||||
dval(rv) *= bigtens[j];
|
||||
if ((z = word0(rv) & Exp_mask)
|
||||
> Exp_msk1*(DBL_MAX_EXP+Bias-P))
|
||||
goto ovfl;
|
||||
|
@ -1444,23 +1463,23 @@ dig_done:
|
|||
else if (e1 < 0) {
|
||||
e1 = -e1;
|
||||
if ((i = e1 & 15) != 0)
|
||||
rv /= tens[i];
|
||||
dval(rv) /= tens[i];
|
||||
if (e1 &= ~15) {
|
||||
e1 >>= 4;
|
||||
if (e1 >= 1 << n_bigtens)
|
||||
goto undfl;
|
||||
for(j = 0; e1 > 1; j++, e1 >>= 1)
|
||||
if (e1 & 1)
|
||||
rv *= tinytens[j];
|
||||
dval(rv) *= tinytens[j];
|
||||
/* The last multiplication could underflow. */
|
||||
rv0 = rv;
|
||||
rv *= tinytens[j];
|
||||
if (!rv) {
|
||||
rv = 2.*rv0;
|
||||
rv *= tinytens[j];
|
||||
if (!rv) {
|
||||
dval(rv0) = dval(rv);
|
||||
dval(rv) *= tinytens[j];
|
||||
if (!dval(rv)) {
|
||||
dval(rv) = 2.*dval(rv0);
|
||||
dval(rv) *= tinytens[j];
|
||||
if (!dval(rv)) {
|
||||
undfl:
|
||||
rv = 0.;
|
||||
dval(rv) = 0.;
|
||||
PR_SetError(PR_RANGE_ERROR, 0);
|
||||
if (bd0)
|
||||
goto retfree;
|
||||
|
@ -1484,7 +1503,7 @@ dig_done:
|
|||
for(;;) {
|
||||
bd = Balloc(bd0->k);
|
||||
Bcopy(bd, bd0);
|
||||
bb = d2b(rv, &bbe, &bbbits); /* rv = bb * 2^bbe */
|
||||
bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */
|
||||
bs = i2b(1);
|
||||
|
||||
if (e >= 0) {
|
||||
|
@ -1596,12 +1615,12 @@ dig_done:
|
|||
break;
|
||||
#endif
|
||||
if (dsign)
|
||||
rv += ulp(rv);
|
||||
dval(rv) += ulp(dval(rv));
|
||||
#ifndef ROUND_BIASED
|
||||
else {
|
||||
rv -= ulp(rv);
|
||||
dval(rv) -= ulp(dval(rv));
|
||||
#ifndef Sudden_Underflow
|
||||
if (!rv)
|
||||
if (!dval(rv))
|
||||
goto undfl;
|
||||
#endif
|
||||
}
|
||||
|
@ -1652,10 +1671,10 @@ dig_done:
|
|||
/* Check for overflow */
|
||||
|
||||
if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) {
|
||||
rv0 = rv;
|
||||
dval(rv0) = dval(rv);
|
||||
word0(rv) -= P*Exp_msk1;
|
||||
adj = aadj1 * ulp(rv);
|
||||
rv += adj;
|
||||
adj = aadj1 * ulp(dval(rv));
|
||||
dval(rv) += adj;
|
||||
if ((word0(rv) & Exp_mask) >=
|
||||
Exp_msk1*(DBL_MAX_EXP+Bias-P)) {
|
||||
if (word0(rv0) == Big0 && word1(rv0) == Big1)
|
||||
|
@ -1670,10 +1689,10 @@ dig_done:
|
|||
else {
|
||||
#ifdef Sudden_Underflow
|
||||
if ((word0(rv) & Exp_mask) <= P*Exp_msk1) {
|
||||
rv0 = rv;
|
||||
dval(rv0) = dval(rv);
|
||||
word0(rv) += P*Exp_msk1;
|
||||
adj = aadj1 * ulp(rv);
|
||||
rv += adj;
|
||||
adj = aadj1 * ulp(dval(rv));
|
||||
dval(rv) += adj;
|
||||
#ifdef IBM
|
||||
if ((word0(rv) & Exp_mask) < P*Exp_msk1)
|
||||
#else
|
||||
|
@ -1691,8 +1710,8 @@ dig_done:
|
|||
word0(rv) -= P*Exp_msk1;
|
||||
}
|
||||
else {
|
||||
adj = aadj1 * ulp(rv);
|
||||
rv += adj;
|
||||
adj = aadj1 * ulp(dval(rv));
|
||||
dval(rv) += adj;
|
||||
}
|
||||
#else
|
||||
/* Compute adj so that the IEEE rounding rules will
|
||||
|
@ -1707,8 +1726,8 @@ dig_done:
|
|||
if (!dsign)
|
||||
aadj1 = -aadj1;
|
||||
}
|
||||
adj = aadj1 * ulp(rv);
|
||||
rv += adj;
|
||||
adj = aadj1 * ulp(dval(rv));
|
||||
dval(rv) += adj;
|
||||
#endif
|
||||
}
|
||||
z = word0(rv) & Exp_mask;
|
||||
|
@ -1739,7 +1758,7 @@ retfree:
|
|||
ret:
|
||||
if (se)
|
||||
*se = (char *)s;
|
||||
return sign ? -rv : rv;
|
||||
return sign ? -dval(rv) : dval(rv);
|
||||
}
|
||||
|
||||
static PRInt32
|
||||
|
@ -1972,9 +1991,9 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
}
|
||||
#endif
|
||||
#ifdef IBM
|
||||
d += 0; /* normalize */
|
||||
dval(d) += 0; /* normalize */
|
||||
#endif
|
||||
if (!d) {
|
||||
if (!dval(d)) {
|
||||
*decpt = 1;
|
||||
if (bufsize < 2) {
|
||||
PR_SetError(PR_BUFFER_OVERFLOW_ERROR, 0);
|
||||
|
@ -1988,18 +2007,18 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
return PR_SUCCESS;
|
||||
}
|
||||
|
||||
b = d2b(d, &be, &bbits);
|
||||
b = d2b(dval(d), &be, &bbits);
|
||||
#ifdef Sudden_Underflow
|
||||
i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1));
|
||||
#else
|
||||
if ((i = (PRInt32)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) {
|
||||
#endif
|
||||
d2 = d;
|
||||
dval(d2) = dval(d);
|
||||
word0(d2) &= Frac_mask1;
|
||||
word0(d2) |= Exp_11;
|
||||
#ifdef IBM
|
||||
if (j = 11 - hi0bits(word0(d2) & Frac_mask))
|
||||
d2 /= 1 << j;
|
||||
dval(d2) /= 1 << j;
|
||||
#endif
|
||||
|
||||
/* log(x) ~=~ log(1.5) + (x-1.5)/1.5
|
||||
|
@ -2038,19 +2057,19 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
i = bbits + be + (Bias + (P-1) - 1);
|
||||
x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32)
|
||||
: word1(d) << (32 - i);
|
||||
d2 = x;
|
||||
dval(d2) = x;
|
||||
word0(d2) -= 31*Exp_msk1; /* adjust exponent */
|
||||
i -= (Bias + (P-1) - 1) + 1;
|
||||
denorm = 1;
|
||||
}
|
||||
#endif
|
||||
ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
|
||||
ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
|
||||
k = (PRInt32)ds;
|
||||
if (ds < 0. && ds != k)
|
||||
k--; /* want k = floor(ds) */
|
||||
k_check = 1;
|
||||
if (k >= 0 && k <= Ten_pmax) {
|
||||
if (d < tens[k])
|
||||
if (dval(d) < tens[k])
|
||||
k--;
|
||||
k_check = 0;
|
||||
}
|
||||
|
@ -2117,7 +2136,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
/* Try to get by with floating-point arithmetic. */
|
||||
|
||||
i = 0;
|
||||
d2 = d;
|
||||
dval(d2) = dval(d);
|
||||
k0 = k;
|
||||
ilim0 = ilim;
|
||||
ieps = 2; /* conservative */
|
||||
|
@ -2127,7 +2146,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
if (j & Bletch) {
|
||||
/* prevent overflows */
|
||||
j &= Bletch - 1;
|
||||
d /= bigtens[n_bigtens-1];
|
||||
dval(d) /= bigtens[n_bigtens-1];
|
||||
ieps++;
|
||||
}
|
||||
for(; j; j >>= 1, i++)
|
||||
|
@ -2135,32 +2154,32 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
ieps++;
|
||||
ds *= bigtens[i];
|
||||
}
|
||||
d /= ds;
|
||||
dval(d) /= ds;
|
||||
}
|
||||
else if ((j1 = -k) != 0) {
|
||||
d *= tens[j1 & 0xf];
|
||||
dval(d) *= tens[j1 & 0xf];
|
||||
for(j = j1 >> 4; j; j >>= 1, i++)
|
||||
if (j & 1) {
|
||||
ieps++;
|
||||
d *= bigtens[i];
|
||||
dval(d) *= bigtens[i];
|
||||
}
|
||||
}
|
||||
if (k_check && d < 1. && ilim > 0) {
|
||||
if (k_check && dval(d) < 1. && ilim > 0) {
|
||||
if (ilim1 <= 0)
|
||||
goto fast_failed;
|
||||
ilim = ilim1;
|
||||
k--;
|
||||
d *= 10.;
|
||||
dval(d) *= 10.;
|
||||
ieps++;
|
||||
}
|
||||
eps = ieps*d + 7.;
|
||||
dval(eps) = ieps*dval(d) + 7.;
|
||||
word0(eps) -= (P-1)*Exp_msk1;
|
||||
if (ilim == 0) {
|
||||
S = mhi = 0;
|
||||
d -= 5.;
|
||||
if (d > eps)
|
||||
dval(d) -= 5.;
|
||||
if (dval(d) > dval(eps))
|
||||
goto one_digit;
|
||||
if (d < -eps)
|
||||
if (dval(d) < -dval(eps))
|
||||
goto no_digits;
|
||||
goto fast_failed;
|
||||
}
|
||||
|
@ -2169,33 +2188,33 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
/* Use Steele & White method of only
|
||||
* generating digits needed.
|
||||
*/
|
||||
eps = 0.5/tens[ilim-1] - eps;
|
||||
dval(eps) = 0.5/tens[ilim-1] - dval(eps);
|
||||
for(i = 0;;) {
|
||||
L = (Long) d;
|
||||
d -= L;
|
||||
L = (Long) (dval(d));
|
||||
dval(d) -= L;
|
||||
*s++ = '0' + (PRInt32)L;
|
||||
if (d < eps)
|
||||
if (dval(d) < dval(eps))
|
||||
goto ret1;
|
||||
if (1. - d < eps)
|
||||
if (1. - dval(d) < dval(eps))
|
||||
goto bump_up;
|
||||
if (++i >= ilim)
|
||||
break;
|
||||
eps *= 10.;
|
||||
d *= 10.;
|
||||
dval(eps) *= 10.;
|
||||
dval(d) *= 10.;
|
||||
}
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
/* Generate ilim digits, then fix them up. */
|
||||
eps *= tens[ilim-1];
|
||||
for(i = 1;; i++, d *= 10.) {
|
||||
L = (Long) d;
|
||||
d -= L;
|
||||
dval(eps) *= tens[ilim-1];
|
||||
for(i = 1;; i++, dval(d) *= 10.) {
|
||||
L = (Long) (dval(d));
|
||||
dval(d) -= L;
|
||||
*s++ = '0' + (PRInt32)L;
|
||||
if (i == ilim) {
|
||||
if (d > 0.5 + eps)
|
||||
if (dval(d) > 0.5 + dval(eps))
|
||||
goto bump_up;
|
||||
else if (d < 0.5 - eps) {
|
||||
else if (dval(d) < 0.5 - dval(eps)) {
|
||||
while(*--s == '0'){} /* just count -- nothing to execute */
|
||||
s++;
|
||||
goto ret1;
|
||||
|
@ -2208,7 +2227,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
#endif
|
||||
fast_failed:
|
||||
s = s0;
|
||||
d = d2;
|
||||
dval(d) = dval(d2);
|
||||
k = k0;
|
||||
ilim = ilim0;
|
||||
}
|
||||
|
@ -2220,24 +2239,24 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
ds = tens[k];
|
||||
if (ndigits < 0 && ilim <= 0) {
|
||||
S = mhi = 0;
|
||||
if (ilim < 0 || d <= 5*ds)
|
||||
if (ilim < 0 || dval(d) <= 5*ds)
|
||||
goto no_digits;
|
||||
goto one_digit;
|
||||
}
|
||||
for(i = 1;; i++) {
|
||||
L = (Long) (d / ds);
|
||||
d -= L*ds;
|
||||
L = (Long) (dval(d) / ds);
|
||||
dval(d) -= L*ds;
|
||||
#ifdef Check_FLT_ROUNDS
|
||||
/* If FLT_ROUNDS == 2, L will usually be high by 1 */
|
||||
if (d < 0) {
|
||||
if (dval(d) < 0) {
|
||||
L--;
|
||||
d += ds;
|
||||
dval(d) += ds;
|
||||
}
|
||||
#endif
|
||||
*s++ = '0' + (PRInt32)L;
|
||||
if (i == ilim) {
|
||||
d += d;
|
||||
if ((d > ds) || (d == ds && L & 1)) {
|
||||
dval(d) += dval(d);
|
||||
if ((dval(d) > ds) || (dval(d) == ds && L & 1)) {
|
||||
bump_up:
|
||||
while(*--s == '9')
|
||||
if (s == s0) {
|
||||
|
@ -2249,7 +2268,7 @@ PR_dtoa(PRFloat64 d, int mode, int ndigits,
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (!(d *= 10.))
|
||||
if (!(dval(d) *= 10.))
|
||||
break;
|
||||
}
|
||||
goto ret1;
|
||||
|
@ -2534,7 +2553,7 @@ PR_cnvtf(char *buf,int bufsz, int prcsn,double fval)
|
|||
return;
|
||||
}
|
||||
/* XXX Why use mode 1? */
|
||||
if (PR_dtoa(fval,1,prcsn,&decpt,&sign,&endnum,num,bufsz)
|
||||
if (PR_dtoa(dval(fval),1,prcsn,&decpt,&sign,&endnum,num,bufsz)
|
||||
== PR_FAILURE) {
|
||||
buf[0] = '\0';
|
||||
goto done;
|
||||
|
|
Загрузка…
Ссылка в новой задаче