FAQ
# New Ticket Created by Gerard Goossen
# Please include the string: [perl #98372]
# in the subject line of all future correspondence about this issue.
# <URL: https://rt.perl.org:443/rt3/Ticket/Display.html?id=98372 >



This is a bug report for perl from gerard@ggoossen.net,
generated with the help of perlbug 1.39 running under perl 5.15.2.
From 763753c0fca75fd509e7c93b8bf8b8911fc93ff4 Mon Sep 17 00:00:00 2001
From: Gerard Goossen <gerard@ggoossen.net>
Date: Sat, 20 Aug 2011 21:18:44 +0200
Subject: [PATCH] Move non-constant folding parts of fold_constants into a
separate functions.

The non-constant folding parts of fold_constants are moved into
separate functions. op_integerize handles converting ops to integer
(and special case of OP_NEGATE), op_std_init handling some standard
functionality (forced scalar context and allocating the TARGET).
Both functions are called where fold_constants is called (but we might
want to make that a bit some selective and use op_std_init in other
places).
---
embed.fnc | 2 +
embed.h | 2 +
op.c | 64 ++++++++++++++++++++++++++++++++++++++++---------------------
proto.h | 10 +++++++++
4 files changed, 56 insertions(+), 22 deletions(-)

diff --git a/embed.fnc b/embed.fnc
index 106c6c7..b7988df 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -406,6 +406,8 @@ p |char* |find_script |NN const char *scriptname|bool dosearch \
NULLOK const char *const *const search_ext|I32 flags
#if defined(PERL_IN_OP_C)
s |OP* |force_list |NULLOK OP* arg
+i |OP* |op_integerize |NN OP *o
+i |OP* |op_std_init |NN OP *o
: FIXME
s |OP* |fold_constants |NN OP *o
#endif
diff --git a/embed.h b/embed.h
index 4ac70e7..120567f 100644
--- a/embed.h
+++ b/embed.h
@@ -1355,6 +1355,8 @@
#define new_logop(a,b,c,d) S_new_logop(aTHX_ a,b,c,d)
#define no_bareword_allowed(a) S_no_bareword_allowed(aTHX_ a)
#define no_fh_allowed(a) S_no_fh_allowed(aTHX_ a)
+#define op_integerize(a) S_op_integerize(aTHX_ a)
+#define op_std_init(a) S_op_std_init(aTHX_ a)
#define opt_scalarhv(a) S_opt_scalarhv(aTHX_ a)
#define pmtrans(a,b,c) S_pmtrans(aTHX_ a,b,c)
#define process_special_blocks(a,b,c) S_process_special_blocks(aTHX_ a,b,c)
diff --git a/op.c b/op.c
index 1d2b437..c36c325 100644
--- a/op.c
+++ b/op.c
@@ -2894,6 +2894,44 @@ Perl_jmaybe(pTHX_ OP *o)
return o;
}

+PERL_STATIC_INLINE OP *
+S_op_std_init(pTHX_ OP *o)
+{
+ I32 type = o->op_type;
+
+ PERL_ARGS_ASSERT_OP_STD_INIT;
+
+ if (PL_opargs[type] & OA_RETSCALAR)
+ scalar(o);
+ if (PL_opargs[type] & OA_TARGET && !o->op_targ)
+ o->op_targ = pad_alloc(type, SVs_PADTMP);
+
+ return o;
+}
+
+PERL_STATIC_INLINE OP *
+S_op_integerize(pTHX_ OP *o)
+{
+ I32 type = o->op_type;
+
+ PERL_ARGS_ASSERT_OP_INTEGERIZE;
+
+ /* integerize op, unless it happens to be C<-foo>.
+ * XXX should pp_i_negate() do magic string negation instead? */
+ if ((PL_opargs[type] & OA_OTHERINT) && (PL_hints & HINT_INTEGER)
+ && !(type == OP_NEGATE && cUNOPo->op_first->op_type == OP_CONST
+ && (cUNOPo->op_first->op_private & OPpCONST_BARE)))
+ {
+ o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)];
+ }
+
+ if (type == OP_NEGATE)
+ /* XXX might want a ck_negate() for this */
+ cUNOPo->op_first->op_private &= ~OPpCONST_STRICT;
+
+ return o;
+}
+
static OP *
S_fold_constants(pTHX_ register OP *o)
{
@@ -2912,28 +2950,10 @@ S_fold_constants(pTHX_ register OP *o)

PERL_ARGS_ASSERT_FOLD_CONSTANTS;

- if (PL_opargs[type] & OA_RETSCALAR)
- scalar(o);
- if (PL_opargs[type] & OA_TARGET && !o->op_targ)
- o->op_targ = pad_alloc(type, SVs_PADTMP);
-
- /* integerize op, unless it happens to be C<-foo>.
- * XXX should pp_i_negate() do magic string negation instead? */
- if ((PL_opargs[type] & OA_OTHERINT) && (PL_hints & HINT_INTEGER)
- && !(type == OP_NEGATE && cUNOPo->op_first->op_type == OP_CONST
- && (cUNOPo->op_first->op_private & OPpCONST_BARE)))
- {
- o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)];
- }
-
if (!(PL_opargs[type] & OA_FOLDCONST))
goto nope;

switch (type) {
- case OP_NEGATE:
- /* XXX might want a ck_negate() for this */
- cUNOPo->op_first->op_private &= ~OPpCONST_STRICT;
- break;
case OP_UCFIRST:
case OP_LCFIRST:
case OP_UC:
@@ -3111,7 +3131,7 @@ Perl_convert(pTHX_ I32 type, I32 flags, OP *o)
if (o->op_type != (unsigned)type)
return o;

- return fold_constants(o);
+ return fold_constants(op_integerize(op_std_init(o)));
}

/*
@@ -3659,7 +3679,7 @@ Perl_newUNOP(pTHX_ I32 type, I32 flags, OP *first)
if (unop->op_next)
return (OP*)unop;

- return fold_constants((OP *) unop);
+ return fold_constants(op_integerize(op_std_init((OP *) unop)));
}

/*
@@ -3709,7 +3729,7 @@ Perl_newBINOP(pTHX_ I32 type, I32 flags, OP *first, OP *last)

binop->op_last = binop->op_first->op_sibling;

- return fold_constants((OP *)binop);
+ return fold_constants(op_integerize(op_std_init((OP *)binop)));
}

static int uvcompare(const void *a, const void *b)
@@ -8564,7 +8584,7 @@ Perl_ck_select(pTHX_ OP *o)
o->op_type = OP_SSELECT;
o->op_ppaddr = PL_ppaddr[OP_SSELECT];
o = ck_fun(o);
- return fold_constants(o);
+ return fold_constants(op_integerize(op_std_init(o)));
}
}
o = ck_fun(o);
diff --git a/proto.h b/proto.h
index 4c79414..58fc77e 100644
--- a/proto.h
+++ b/proto.h
@@ -5569,6 +5569,16 @@ STATIC OP* S_no_fh_allowed(pTHX_ OP *o)
#define PERL_ARGS_ASSERT_NO_FH_ALLOWED \
assert(o)

+PERL_STATIC_INLINE OP* S_op_integerize(pTHX_ OP *o)
+ __attribute__nonnull__(pTHX_1);
+#define PERL_ARGS_ASSERT_OP_INTEGERIZE \
+ assert(o)
+
+PERL_STATIC_INLINE OP* S_op_std_init(pTHX_ OP *o)
+ __attribute__nonnull__(pTHX_1);
+#define PERL_ARGS_ASSERT_OP_STD_INIT \
+ assert(o)
+
STATIC OP* S_opt_scalarhv(pTHX_ OP* rep_op)
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_OPT_SCALARHV \
--
1.7.5.4

---
Flags:
category=core
severity=low
---
Site configuration information for perl 5.15.2:

Configured by gerard at Sun Sep 4 14:41:00 CEST 2011.

Summary of my perl5 (revision 5 version 15 subversion 2) configuration:
Derived from: 6ba99909fd9845960e57958af5e05881b9dc09e3
Platform:
osname=linux, osvers=3.0.0-1-686-pae, archname=i686-linux-thread-multi
uname='linux zeus 3.0.0-1-686-pae #1 smp sun jul 24 14:27:32 utc 2011 i686 gnulinux '
config_args='-des -Dusethreads -Dnoextensions= -Doptimize=-O3 -g3 -DDEBUGGING -Dusedevel -Dprefix=/home/gerard/perl/inst/blead-codegen'
hint=recommended, useposix=true, d_sigaction=define
useithreads=define, usemultiplicity=define
useperlio=define, d_sfio=undef, uselargefiles=define, usesocks=undef
use64bitint=undef, use64bitall=undef, uselongdouble=undef
usemymalloc=n, bincompat5005=undef
Compiler:
cc='cc', ccflags ='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64',
optimize='-O3 -g3',
cppflags='-D_REENTRANT -D_GNU_SOURCE -DDEBUGGING -fno-strict-aliasing -pipe -fstack-protector -I/usr/local/include'
ccversion='', gccversion='4.6.1', gccosandvers=''
intsize=4, longsize=4, ptrsize=4, doublesize=8, byteorder=1234
d_longlong=define, longlongsize=8, d_longdbl=define, longdblsize=12
ivtype='long', ivsize=4, nvtype='double', nvsize=8, Off_t='off_t', lseeksize=8
alignbytes=4, prototype=define
Linker and Libraries:
ld='cc', ldflags =' -fstack-protector -L/usr/local/lib'
libpth=/usr/local/lib /lib /usr/lib /usr/lib/i386-linux-gnu /usr/lib64
libs=-lnsl -ldb -ldl -lm -lcrypt -lutil -lpthread -lc
perllibs=-lnsl -ldl -lm -lcrypt -lutil -lpthread -lc
libc=, so=so, useshrplib=false, libperl=libperl.a
gnulibc_version='2.13'
Dynamic Linking:
dlsrc=dl_dlopen.xs, dlext=so, d_dlsymun=undef, ccdlflags='-Wl,-E'
cccdlflags='-fPIC', lddlflags='-shared -O3 -g3 -L/usr/local/lib -fstack-protector'

Locally applied patches:


---
@INC for perl 5.15.2:
lib
/home/gerard/perl/inst/blead-codegen/lib/site_perl/5.15.2/i686-linux-thread-multi
/home/gerard/perl/inst/blead-codegen/lib/site_perl/5.15.2
/home/gerard/perl/inst/blead-codegen/lib/5.15.2/i686-linux-thread-multi
/home/gerard/perl/inst/blead-codegen/lib/5.15.2
/home/gerard/perl/inst/blead-codegen/lib/site_perl
.

---
Environment for perl 5.15.2:
HOME=/home/gerard
LANG=en_US.UTF-8
LANGUAGE (unset)
LD_LIBRARY_PATH (unset)
LOGDIR (unset)
PATH=/usr/lib/ccache:/home/gerard/bin:/usr/local/bin:/usr/bin:/bin:/usr/games
PERL_BADLANG (unset)
SHELL=/bin/bash

Search Discussions

  • Father Chrysostomos via RT at Sep 4, 2011 at 5:45 pm

    On Sun Sep 04 06:44:43 2011, ggoossen wrote:

    This is a bug report for perl from gerard@ggoossen.net,
    generated with the help of perlbug 1.39 running under perl 5.15.2.

    From 763753c0fca75fd509e7c93b8bf8b8911fc93ff4 Mon Sep 17 00:00:00 2001
    From: Gerard Goossen <gerard@ggoossen.net>
    Date: Sat, 20 Aug 2011 21:18:44 +0200
    Subject: [PATCH] Move non-constant folding parts of fold_constants
    into a
    separate functions.

    The non-constant folding parts of fold_constants are moved into
    separate functions. op_integerize handles converting ops to integer
    (and special case of OP_NEGATE)
    Don’t integerization and OP_NEGATE folding both fall under constant
    folding? I would expect at least the latter to, and the former is very
    similar.
  • Hv at Sep 4, 2011 at 9:36 pm
    "Father Chrysostomos via RT" wrote:
    :On Sun Sep 04 06:44:43 2011, ggoossen wrote:
    :>
    :> This is a bug report for perl from gerard@ggoossen.net,
    :> generated with the help of perlbug 1.39 running under perl 5.15.2.
    :>
    :> From 763753c0fca75fd509e7c93b8bf8b8911fc93ff4 Mon Sep 17 00:00:00 2001
    :> From: Gerard Goossen <gerard@ggoossen.net>
    :> Date: Sat, 20 Aug 2011 21:18:44 +0200
    :> Subject: [PATCH] Move non-constant folding parts of fold_constants
    :> into a
    :> separate functions.
    :>
    :> The non-constant folding parts of fold_constants are moved into
    :> separate functions. op_integerize handles converting ops to integer
    :> (and special case of OP_NEGATE)
    :
    :Don't integerization and OP_NEGATE folding both fall under constant
    :folding? I would expect at least the latter to, and the former is very
    :similar.

    Isn't (this) integerization to switch op types to integer variants
    in the context of 'use integer'? That's what I would guess from this:
    o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)];

    In that case, this seems a perfectly fair example of the ongoing
    separation of optimizations from mandatory fixups.

    Hugo
  • Father Chrysostomos via RT at Sep 5, 2011 at 2:23 am

    On Sun Sep 04 14:36:46 2011, hv wrote:
    "Father Chrysostomos via RT" wrote:
    :On Sun Sep 04 06:44:43 2011, ggoossen wrote:
    :>
    :> This is a bug report for perl from gerard@ggoossen.net,
    :> generated with the help of perlbug 1.39 running under perl 5.15.2.
    :>
    :> From 763753c0fca75fd509e7c93b8bf8b8911fc93ff4 Mon Sep 17 00:00:00 2001
    :> From: Gerard Goossen <gerard@ggoossen.net>
    :> Date: Sat, 20 Aug 2011 21:18:44 +0200
    :> Subject: [PATCH] Move non-constant folding parts of fold_constants
    :> into a
    :> separate functions.
    :>
    :> The non-constant folding parts of fold_constants are moved into
    :> separate functions. op_integerize handles converting ops to integer
    :> (and special case of OP_NEGATE)
    :
    :Don't integerization and OP_NEGATE folding both fall under constant
    :folding? I would expect at least the latter to, and the former is very
    :similar.

    Isn't (this) integerization to switch op types to integer variants
    in the context of 'use integer'? That's what I would guess from this:
    o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)];

    In that case, this seems a perfectly fair example of the ongoing
    separation of optimizations from mandatory fixups.
    Is it possible nonetheless to keep OP_NEGATE folding in fold_constants,
    or is that out of the question?
  • Hv at Sep 5, 2011 at 5:50 am
    "Father Chrysostomos via RT" wrote:
    :On Sun Sep 04 14:36:46 2011, hv wrote:
    :> "Father Chrysostomos via RT" wrote:
    :> :On Sun Sep 04 06:44:43 2011, ggoossen wrote:
    :> :>
    :> :> This is a bug report for perl from gerard@ggoossen.net,
    :> :> generated with the help of perlbug 1.39 running under perl 5.15.2.
    :> :>
    :> :> From 763753c0fca75fd509e7c93b8bf8b8911fc93ff4 Mon Sep 17 00:00:00 2001
    :> :> From: Gerard Goossen <gerard@ggoossen.net>
    :> :> Date: Sat, 20 Aug 2011 21:18:44 +0200
    :> :> Subject: [PATCH] Move non-constant folding parts of fold_constants
    :> :> into a
    :> :> separate functions.
    :> :>
    :> :> The non-constant folding parts of fold_constants are moved into
    :> :> separate functions. op_integerize handles converting ops to integer
    :> :> (and special case of OP_NEGATE)
    :> :
    :> :Don't integerization and OP_NEGATE folding both fall under constant
    :> :folding? I would expect at least the latter to, and the former is very
    :> :similar.
    :>
    :> Isn't (this) integerization to switch op types to integer variants
    :> in the context of 'use integer'? That's what I would guess from this:
    :> o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)];
    :>
    :> In that case, this seems a perfectly fair example of the ongoing
    :> separation of optimizations from mandatory fixups.
    :
    :Is it possible nonetheless to keep OP_NEGATE folding in fold_constants,
    :or is that out of the question?

    There are two references to OP_NEGATE in S_op_integerize. The first
    is to avoid the op switching above for the C<-foo> case. The second
    is there, I think, to stop C<strict 'subs'> complaining about C<-foo>,
    but I'm not totally sure that's what it is doing.

    I don't see anything there that's folding constants. Though if I'm
    right about what the second part is doing, it doesn't sound like it
    belongs in S_op_integerize either - the XXX comment offers what could
    be the better solution, "might want a ck_negate() for this".

    Hugo
  • Gerard Goossen at Sep 5, 2011 at 7:30 am

    On Sun, Sep 04, 2011 at 10:50:40PM -0700, Hugo van der Sanden via RT wrote:
    "Father Chrysostomos via RT" wrote:
    :On Sun Sep 04 14:36:46 2011, hv wrote:
    :> "Father Chrysostomos via RT" wrote:
    :> :On Sun Sep 04 06:44:43 2011, ggoossen wrote:
    :> :>
    :> :> This is a bug report for perl from gerard@ggoossen.net,
    :> :> generated with the help of perlbug 1.39 running under perl 5.15.2.
    :> :>
    :> :> From 763753c0fca75fd509e7c93b8bf8b8911fc93ff4 Mon Sep 17 00:00:00 2001
    :> :> From: Gerard Goossen <gerard@ggoossen.net>
    :> :> Date: Sat, 20 Aug 2011 21:18:44 +0200
    :> :> Subject: [PATCH] Move non-constant folding parts of fold_constants
    :> :> into a
    :> :> separate functions.
    :> :>
    :> :> The non-constant folding parts of fold_constants are moved into
    :> :> separate functions. op_integerize handles converting ops to integer
    :> :> (and special case of OP_NEGATE)
    :> :
    :> :Don't integerization and OP_NEGATE folding both fall under constant
    :> :folding? I would expect at least the latter to, and the former is very
    :> :similar.
    :>
    :> Isn't (this) integerization to switch op types to integer variants
    :> in the context of 'use integer'? That's what I would guess from this:
    :> o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)];
    :>
    :> In that case, this seems a perfectly fair example of the ongoing
    :> separation of optimizations from mandatory fixups.
    :
    :Is it possible nonetheless to keep OP_NEGATE folding in fold_constants,
    :or is that out of the question?

    There are two references to OP_NEGATE in S_op_integerize. The first
    is to avoid the op switching above for the C<-foo> case. The second
    is there, I think, to stop C<strict 'subs'> complaining about C<-foo>,
    but I'm not totally sure that's what it is doing.

    I don't see anything there that's folding constants. Though if I'm
    right about what the second part is doing, it doesn't sound like it
    belongs in S_op_integerize either - the XXX comment offers what could
    be the better solution, "might want a ck_negate() for this".
    You're right about what it is doing, and indeed creating a ck_negate
    for it might be a good idea.

    Gerard
  • Father Chrysostomos via RT at Sep 5, 2011 at 3:21 pm

    On Sun Sep 04 22:50:40 2011, hv wrote:
    "Father Chrysostomos via RT" wrote:
    :On Sun Sep 04 14:36:46 2011, hv wrote:
    :> "Father Chrysostomos via RT" wrote:
    :> :On Sun Sep 04 06:44:43 2011, ggoossen wrote:
    :> :>
    :> :> This is a bug report for perl from gerard@ggoossen.net,
    :> :> generated with the help of perlbug 1.39 running under perl 5.15.2.
    :> :>
    :> :> From 763753c0fca75fd509e7c93b8bf8b8911fc93ff4 Mon Sep 17
    00:00:00 2001
    :> :> From: Gerard Goossen <gerard@ggoossen.net>
    :> :> Date: Sat, 20 Aug 2011 21:18:44 +0200
    :> :> Subject: [PATCH] Move non-constant folding parts of fold_constants
    :> :> into a
    :> :> separate functions.
    :> :>
    :> :> The non-constant folding parts of fold_constants are moved into
    :> :> separate functions. op_integerize handles converting ops to integer
    :> :> (and special case of OP_NEGATE)
    :> :
    :> :Don't integerization and OP_NEGATE folding both fall under constant
    :> :folding? I would expect at least the latter to, and the former is very
    :> :similar.
    :>
    :> Isn't (this) integerization to switch op types to integer variants
    :> in the context of 'use integer'? That's what I would guess from this:
    :> o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)];
    :>
    :> In that case, this seems a perfectly fair example of the ongoing
    :> separation of optimizations from mandatory fixups.
    :
    :Is it possible nonetheless to keep OP_NEGATE folding in fold_constants,
    :or is that out of the question?

    There are two references to OP_NEGATE in S_op_integerize. The first
    is to avoid the op switching above for the C<-foo> case. The second
    is there, I think, to stop C<strict 'subs'> complaining about C<-foo>,
    but I'm not totally sure that's what it is doing.

    I don't see anything there that's folding constants. Though if I'm
    right about what the second part is doing, it doesn't sound like it
    belongs in S_op_integerize either - the XXX comment offers what could
    be the better solution, "might want a ck_negate() for this".
    If S_op_integerize is a static function, it probably doesn’t matter what
    goes in it, as we can always rearrange things. So I’m beginning to
    think this patch is fine as it is, since it accomplishes its goal of
    separating optimisition from necessary fix-ups.
  • Father Chrysostomos via RT at Sep 5, 2011 at 4:13 pm

    On Mon Sep 05 08:21:11 2011, sprout wrote:
    On Sun Sep 04 22:50:40 2011, hv wrote:
    "Father Chrysostomos via RT" wrote:
    :On Sun Sep 04 14:36:46 2011, hv wrote:
    :> "Father Chrysostomos via RT" wrote:
    :> :On Sun Sep 04 06:44:43 2011, ggoossen wrote:
    :> :>
    :> :> This is a bug report for perl from gerard@ggoossen.net,
    :> :> generated with the help of perlbug 1.39 running under perl 5.15.2.
    :> :>
    :> :> From 763753c0fca75fd509e7c93b8bf8b8911fc93ff4 Mon Sep 17
    00:00:00 2001
    :> :> From: Gerard Goossen <gerard@ggoossen.net>
    :> :> Date: Sat, 20 Aug 2011 21:18:44 +0200
    :> :> Subject: [PATCH] Move non-constant folding parts of fold_constants
    :> :> into a
    :> :> separate functions.
    :> :>
    :> :> The non-constant folding parts of fold_constants are moved into
    :> :> separate functions. op_integerize handles converting ops to
    integer
    :> :> (and special case of OP_NEGATE)
    :> :
    :> :Don't integerization and OP_NEGATE folding both fall under constant
    :> :folding? I would expect at least the latter to, and the former
    is very
    :> :similar.
    :>
    :> Isn't (this) integerization to switch op types to integer variants
    :> in the context of 'use integer'? That's what I would guess from this:
    :> o->op_ppaddr = PL_ppaddr[type = ++(o->op_type)];
    :>
    :> In that case, this seems a perfectly fair example of the ongoing
    :> separation of optimizations from mandatory fixups.
    :
    :Is it possible nonetheless to keep OP_NEGATE folding in fold_constants,
    :or is that out of the question?

    There are two references to OP_NEGATE in S_op_integerize. The first
    is to avoid the op switching above for the C<-foo> case. The second
    is there, I think, to stop C<strict 'subs'> complaining about C<-foo>,
    but I'm not totally sure that's what it is doing.

    I don't see anything there that's folding constants. Though if I'm
    right about what the second part is doing, it doesn't sound like it
    belongs in S_op_integerize either - the XXX comment offers what could
    be the better solution, "might want a ck_negate() for this".
    If S_op_integerize is a static function, it probably doesn’t matter what
    goes in it, as we can always rearrange things. So I’m beginning to
    think this patch is fine as it is, since it accomplishes its goal of
    separating optimisition from necessary fix-ups.
    And I’ve just applied your patch as 985b9e5. Thank you.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupperl5-porters @
categoriesperl
postedSep 4, '11 at 1:44p
activeSep 5, '11 at 4:13p
posts8
users3
websiteperl.org

People

Translate

site design / logo © 2022 Grokbase