[Po4a-devel][CVS] po4a/lib/Locale/Po4a Sgml.pm,1.28,1.29
by Martin Quinson
Update of /cvsroot/po4a/po4a/lib/Locale/Po4a
In directory haydn:/tmp/cvs-serv23701/lib/Locale/Po4a
Modified Files:
Sgml.pm
Log Message:
Turn of debugging
Index: Sgml.pm
===================================================================
RCS file: /cvsroot/po4a/po4a/lib/Locale/Po4a/Sgml.pm,v
retrieving revision 1.28
retrieving revision 1.29
diff -u -d -r1.28 -r1.29
--- Sgml.pm 1 Aug 2004 20:56:16 -0000 1.28
+++ Sgml.pm 2 Aug 2004 09:45:48 -0000 1.29
@@ -178,7 +178,7 @@
my %debug=('tag' => 0,
'generic' => 0,
- 'entities' => 1,
+ 'entities' => 0,
'refs' => 0);
my $xmlprolog = undef; # the '<?xml ... ?>' line if existing
20 years, 3 months
[Po4a-devel][CVS] po4a/lib/Locale/Po4a Po.pm,1.15,1.16
by Martin Quinson
Update of /cvsroot/po4a/po4a/lib/Locale/Po4a
In directory haydn:/tmp/cvs-serv23510/lib/Locale/Po4a
Modified Files:
Po.pm
Log Message:
Implement a tool I dream of since a long time: msgsearch, which allows you to filter out some messages of the po file and put them in another
Index: Po.pm
===================================================================
RCS file: /cvsroot/po4a/po4a/lib/Locale/Po4a/Po.pm,v
retrieving revision 1.15
retrieving revision 1.16
diff -u -d -r1.15 -r1.16
--- Po.pm 1 Aug 2004 09:44:50 -0000 1.15
+++ Po.pm 2 Aug 2004 09:35:39 -0000 1.16
@@ -77,7 +77,8 @@
my %debug=('canonize' => 0,
'quote' => 0,
- 'escape' => 0);
+ 'escape' => 0,
+ 'filter' => 1);
=head1 Functions about whole message catalogs
@@ -142,16 +143,21 @@
my $filename=shift
|| croak (dgettext("po4a","po4a::po: Please provide a non-nul filename")."\n");
- open INPUT,"<$filename"
- || croak (sprintf(dgettext("po4a","Can't read from %s: %s"),$filename,$!)."\n");
+ my $fh;
+ if ($filename eq '-') {
+ $fh=*STDIN;
+ } else {
+ open $fh,"<$filename"
+ || croak (sprintf(dgettext("po4a","Can't read from %s: %s"),$filename,$!)."\n");
+ }
## Read paragraphs line-by-line
my $pofile="";
my $textline;
- while (defined ($textline = <INPUT>)) {
+ while (defined ($textline = <$fh>)) {
$pofile .= $textline;
}
- close INPUT || croak (sprintf(dgettext("po4a","Can't close %s after reading: %s"),$filename,$!)."\n");
+# close INPUT || croak (sprintf(dgettext("po4a","Can't close %s after reading: %s"),$filename,$!)."\n");
my $linenum=0;
@@ -334,29 +340,192 @@
return $pores;
}
-=item select_file()
+=item filter()
This function extract a catalog from an existing one. Only the entries having a
reference in the given file will be placed in the resulting catalog.
+This function parses its argument, convert it to a perl function definition,
+eval this definition and filter the fields for which this function returns true.
+I love perl sometimes ;)
+
=cut
-sub select_file {
+sub filter {
my $self=shift;
- my $file=shift;
+ our $filter=shift;
my $res;
$res = Locale::Po4a::Po->new();
+ # Parse the filter
+ our $code="sub apply { return ";
+ our $pos=0;
+ our $length = length $filter;
+ our @filter = split(//,$filter); # explode chars to parts. How to subscript a string in Perl?
+
+ sub gloups {
+ my $fmt=shift;
+ my $space;
+ for (1..$pos){
+ $space .= ' ';
+ }
+ die (sprintf(dgettext("po4a",$fmt)."\n",@_)."$filter\n$space^ HERE\n");;
+ }
+ sub showmethecode {
+ return unless $debug{'filter'};
+ my $fmt=shift;
+ my $space="";
+ for (1..$pos){
+ $space .= ' ';
+ }
+ print STDERR "$filter\n$space^ $fmt\n";#"$code\n";
+ }
+
+ # I dream of a lex in perl :-/
+ sub parse_expression {
+ showmethecode("Begin expression");
+
+ gloups("Begin of expression expected, got '%s'",$filter[$pos])
+ unless ($filter[$pos] eq '(');
+ $pos ++; # pass the '('
+ if ($filter[$pos] eq '&') {
+ # AND
+ $pos++;
+ showmethecode("Begin of AND");
+ $code .= "(";
+ while (1) {
+ gloups ("Unfinished AND statement.")
+ if ($pos == $length);
+ parse_expression();
+ if ($filter[$pos] eq '(') {
+ $code .= " && ";
+ } elsif ($filter[$pos] eq ')') {
+ last; # do not eat that char
+ } else {
+ gloups("End of AND or begin of sub-expression expected, got '%s'", $filter[$pos]);
+ }
+ }
+ $code .= ")";
+ } elsif ($filter[$pos] eq '|') {
+ # OR
+ $pos++;
+ $code .= "(";
+ while (1) {
+ gloups("Unfinished OR statement.")
+ if ($pos == $length);
+ parse_expression();
+ if ($filter[$pos] eq '(') {
+ $code .= " || ";
+ } elsif ($filter[$pos] eq ')') {
+ last; # do not eat that char
+ } else {
+ gloups("End of OR or begin of sub-expression expected, got '%s'",$filter[$pos]);
+ }
+ }
+ $code .= ")";
+ } elsif ($filter[$pos] eq '!') {
+ # NOT
+ $pos++;
+ $code .= "(!";
+ gloups("Missing sub-expression in NOT statement.")
+ if ($pos == $length);
+ parse_expression();
+ $code .= ")";
+ } else {
+ # must be an equal. Let's get field and argument
+ my ($field,$arg,$done);
+ $field = substr($filter,$pos);
+ gloups("EQ statement contains no '=' or invalid field name")
+ unless ($field =~ /([a-z]*)=/i);
+ $field = lc($1);
+ $pos += (length $field) + 1;
+
+ # check that we've got a valid field name, and the number it referes to
+ my @names=qw(msgid msgstr reference flags comment automatic); # DO NOT CHANGE THE ORDER
+ my $fieldpos;
+ for ($fieldpos = 0;
+ $fieldpos < scalar @names && $field ne $names[$fieldpos];
+ $fieldpos++) {}
+ gloups("Invalid field name: %s",$field)
+ if $fieldpos == scalar @names; # not found
+
+ # Now, get the argument value. It has to be between quotes, which can be escaped
+ # We point right on the first char of the argument (first quote already ate)
+ my $escaped = 0;
+ my $quoted = 0;
+ if ($filter[$pos] eq '"') {
+ $pos++;
+ $quoted = 1;
+ }
+ showmethecode(($quoted?"Quoted":"Unquoted")." argument of field '$field'");
+
+ while (!$done) {
+ gloups("Unfinished EQ argument.")
+ if ($pos == $length);
+
+ if ($quoted) {
+ if ($filter[$pos] eq '\\') {
+ if ($escaped) {
+ $arg .= '\\';
+ $escaped = 0;
+ } else {
+ $escaped = 1;
+ }
+ } elsif ($escaped) {
+ if ($filter[$pos] eq '"') {
+ $arg .= '"';
+ $escaped = 0;
+ } else {
+ gloups("Invalid escape sequence in argument: '\\%s'",$filter[$pos]);
+ }
+ } else {
+ if ($filter[$pos] eq '"') {
+ $done = 1;
+ } else {
+ $arg .= $filter[$pos];
+ }
+ }
+ } else {
+ if ($filter[$pos] eq ')') {
+ $pos--; # counter the next ++ since we don't want to eat this char
+ $done = 1;
+ } else {
+ $arg .= $filter[$pos];
+ }
+ }
+ $pos++;
+ }
+ # and now, add the code to check this equality
+ $code .= "(\$_[$fieldpos] =~ m/$arg/)";
+
+ }
+ showmethecode("End of expression");
+ gloups("Unfinished statement.")
+ if ($pos == $length);
+ gloups("End of expression expected, got '%s'",$filter[$pos])
+ unless ($filter[$pos] eq ')');
+ $pos++;
+ }
+ # And now, launch the beast, finish the function and use eval to construct this function.
+ # Ok, the lack of lexer is a fair price for the eval ;)
+ parse_expression();
+ gloups("Garbage at the end of the expression")
+ if ($pos != $length);
+ $code .= "; }";
+ print STDERR "CODE = $code\n";
+ eval $code;
+ die (sprintf(dgettext("po4a","Eval failure: %s")."\n",$@))
+ if $@;
+
for (my $cpt=(0) ;
$cpt<$self->count_entries();
- $cpt) {
+ $cpt++) {
my ($msgid,$ref,$msgstr,$flags,$type,$comment,$automatic);
$msgid = $self->msgid($cpt);
$ref=$self->{po}{$msgid}{'reference'};
- next unless ($ref =~ / $file:/);
$msgstr= $self->{po}{$msgid}{'msgstr'};
$flags = $self->{po}{$msgid}{'flags'};
@@ -364,14 +533,14 @@
$comment = $self->{po}{$msgid}{'comment'};
$automatic = $self->{po}{$msgid}{'automatic'};
-# $res->push_raw('msgid' => $msgid,
-# 'msgstr' => $msgstr,
-# 'flags' => $flags,
-# 'type' => $type,
-# 'reference' => $ref,
-# 'comment' => $comment,
-# 'automatic' => $automatic);
-
+ $res->push_raw('msgid' => $msgid,
+ 'msgstr' => $msgstr,
+ 'flags' => $flags,
+ 'type' => $type,
+ 'reference' => $ref,
+ 'comment' => $comment,
+ 'automatic' => $automatic)
+ if (apply($msgid,$msgstr,$ref,$flags,$comment,$automatic)); # DO NOT CHANGE THE ORDER
}
return $res;
}
20 years, 3 months
[Po4a-devel][CVS] po4a msgsearch,NONE,1.1
by Martin Quinson
Update of /cvsroot/po4a/po4a
In directory haydn:/tmp/cvs-serv23510
Added Files:
msgsearch
Log Message:
Implement a tool I dream of since a long time: msgsearch, which allows you to filter out some messages of the po file and put them in another
--- NEW FILE: msgsearch ---
#! /usr/bin/perl
eval 'exec /usr/bin/perl -S $0 ${1+"$@"}'
if $running_under_some_shell;
# $Id: msgsearch,v 1.1 2004/08/02 09:35:39 mquinson-guest Exp $
#
# Copyright 2002, 2003, 2004 by Martin Quinson <Martin.Quinson(a)ens-lyon.fr>
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of GPL (see COPYING).
my $VERSION=$Locale::Po4a::TransTractor::VERSION;
=head1 NAME
msgsearch - Extract some messages of a po file based on several criteron
=head1 SYNOPSIS
msgsearch [-dhvV] -i E<lt>inputE<gt> -o E<lt>outputE<gt> E<lt>filterE<gt>
=head1 DESCRIPTION
msgsearch is an handy tool to extract some messages of a po file. Selection
depend on the file the message where extracted from, on the flags attached
to the message or even on their actual content.
The used filters are very similar to the LDAP ones:
=over
=item * (E<lt>fieldE<gt>=argument)
The EQ operator returns true (and thus select the message for
extraction) if and only if the value of the E<lt>fieldE<gt> is equal to the
string used as argument. The argument are Perl regular expression, so if
you want to get an equality (and not a substring search), you have to use ^value$.
Existing fields are:
=over
=item - msgid
The actual content of the message.
=item - msgstr
The actual content of the translation.
=item - reference
The location of the message in the file where it was extracted from. It is a
space separated list of positions, each ones being of the syntax
E<gt>fileE<lt>:E<gt>line numberE<lt>.
=item - comment
Comment added manually (by the translators).
=item - automatic
Comment automatically added by the string extraction program. See the
I<--add-comments> option of the B<xgettext> program for more information.
=item - flags
space-separated list of all defined flags for this entry.
Valid flags are: c-text, python-text, lisp-text, elisp-text, librep-text,
smalltalk-text, java-text, awk-text, object-pascal-text, ycp-text,
tcl-text, wrap, no-wrap and fuzzy.
See the gettext documentation for their meaning.
=back
=item * (!E<lt>expressionE<gt>)
The NOT operator returns true if the sub-E<lt>expressionE<gt> return false.
=item * (&E<lt>expression1E<gt>E<lt>expression2E<gt>...E<lt>expressionNE<gt>)
The AND operator returns true when all the sub-expression return true. It
return false if at least one of them return false.
=item * (|E<lt>expression1E<gt>E<lt>expression2E<gt>...E<lt>expressionNE<gt>)
The OR operator returns true when at least one of the sub-expression return
true. It return false if all of them return false.
=head1 OPTIONS
=over 4
=item -h, --help
Show a short help message.
=item -V, --version
Displays the version of the script and exits.
=item -i, --input
Input file. By default, files are taken from the standard input.
=item -o, --output
Output file. By default, files are sent on the standard output.
=item -v, --verbose
Increase the verbosity of the program.
=back
=head1 SEE ALSO
This tool is part of the po4a project, even if it can well prove useful in
other contexts. See L<po4a(7)> for more information about the motivations of
the po4a project, and the other tools developed in that framework.
=head1 AUTHORS
Martin Quinson <martin.quinson,tuxfamily.org>
=head1 COPYRIGHT AND LICENSE
Copyright 2004 by SPI, inc.
This program is free software; you may redistribute it and/or modify it
under the terms of GPL (see COPYING file).
=cut
use 5.006;
use strict;
use warnings;
use Getopt::Long qw(GetOptions);
use Locale::Po4a::Po;
use Pod::Usage qw(pod2usage);
use Locale::gettext;
use POSIX; # Needed for setlocale()
setlocale(LC_MESSAGES, "");
textdomain('po4a');
sub show_version {
print sprintf(gettext(
"%s version %s.\n".
"written by Martin Quinson and Denis Barbier.\n\n".
"Copyright (C) 2002, 2003, 2004 Software of Public Interest, Inc.\n".
"This is free software; see source code for copying\n".
"conditions. There is NO warranty; not even for\n".
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
), "msgsearch", $VERSION)."\n";
exit 0;
}
my ($help,@verbose,$input,$output);
$help = 0;
@verbose = ();
$input = '-';
$output = '-';
Getopt::Long::config('bundling', 'no_getopt_compat', 'no_auto_abbrev');
GetOptions(
'input|i=s' => \$input,
'output|o=s' => \$output,
'help|h' => \$help,
'verbose|v' => \@verbose,
'version|V' => \&show_version
) || pod2usage(1);
$input eq '-' || -e $input || die sprintf(gettext("msgsearch: File '%s' does not exist")."\n",$input);
my $verbose = scalar @verbose;
# Argument check
$help && pod2usage (0);
my $filter = shift(@ARGV) || pod2usage(1);
my $poin = Locale::Po4a::Po->new();
# All following function croak on problem
print STDERR gettext("Read $input")."\n" if $verbose;
$poin->read($input);
print STDERR gettext("Filter")."\n" if $verbose;
my $poout = $poin->filter($filter);
print STDERR gettext("Write result to $output")."\n" if $verbose;
$poout->write($output);
0;
20 years, 3 months
[Po4a-devel][CVS] po4a/po/bin fr.po,1.26,1.27
by Martin Quinson
Update of /cvsroot/po4a/po4a/po/bin
In directory haydn:/tmp/cvs-serv5217/po/bin
Modified Files:
fr.po
Log Message:
typo
Index: fr.po
===================================================================
RCS file: /cvsroot/po4a/po4a/po/bin/fr.po,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- fr.po 21 Jul 2004 00:11:16 -0000 1.26
+++ fr.po 2 Aug 2004 08:29:37 -0000 1.27
@@ -591,7 +591,7 @@
#: ../../po4a:280
#, perl-format
msgid "Translation of %s in %s redefined"
-msgstr "La tranduction de %s en %s redéfinie."
+msgstr "La traduction de %s en %s redéfinie."
#: ../../po4a:289
#, perl-format
20 years, 3 months
[Po4a-devel][CVS] po4a/debian changelog,1.63,1.64
by Martin Quinson
Update of /cvsroot/po4a/po4a/debian
In directory haydn:/tmp/cvs-serv28498/debian
Modified Files:
changelog
Log Message:
explain my mother what I did last night
Index: changelog
===================================================================
RCS file: /cvsroot/po4a/po4a/debian/changelog,v
retrieving revision 1.63
retrieving revision 1.64
diff -u -d -r1.63 -r1.64
--- changelog 1 Aug 2004 20:36:51 -0000 1.63
+++ changelog 1 Aug 2004 20:57:50 -0000 1.64
@@ -5,6 +5,7 @@
[Martin Quinson]
- add refentry to verbatim so that no spaces are added.
Closes #262739 (in Debian).
+ - Allow entities definition to contain '>'. Closes #262735 (in Debian)
- Overhaul of po4a(7)
- Various pod fixup
20 years, 3 months
[Po4a-devel][CVS] po4a/lib/Locale/Po4a Sgml.pm,1.27,1.28
by Martin Quinson
Update of /cvsroot/po4a/po4a/lib/Locale/Po4a
In directory haydn:/tmp/cvs-serv28390
Modified Files:
Sgml.pm
Log Message:
allow entities definition to contain '>'. Fixes Debian's #262735
Index: Sgml.pm
===================================================================
RCS file: /cvsroot/po4a/po4a/lib/Locale/Po4a/Sgml.pm,v
retrieving revision 1.27
retrieving revision 1.28
diff -u -d -r1.27 -r1.28
--- Sgml.pm 1 Aug 2004 20:33:13 -0000 1.27
+++ Sgml.pm 1 Aug 2004 20:56:16 -0000 1.28
@@ -178,7 +178,7 @@
my %debug=('tag' => 0,
'generic' => 0,
- 'entities' => 0,
+ 'entities' => 1,
'refs' => 0);
my $xmlprolog = undef; # the '<?xml ... ?>' line if existing
@@ -536,10 +536,11 @@
# <!ENTITY myentity "definition_of_my_entity">
# and push("<!ENTITY myentity \"".$self->translate("definition_of_my_entity")
if ($prolog =~ m/(.*?\[)(.*)(\]>)/s) {
+ warn "Pre=~~$1~~;Post=~~$3~~\n" if ($debug{'entities'});
$self->pushline($1);
$prolog=$2;
my ($post) = $3;
- while ($prolog =~ m/^(.*?)<!ENTITY\s(\S*)\s*"([^>"]*)">(.*)$/is) { #" ){
+ while ($prolog =~ m/^(.*?)<!ENTITY\s+(\S*)\s+"([^"]*)">(.*)$/is) { #" ){
$self->pushline($1);
$self->pushline("<!ENTITY $2 \"".$self->translate($3,"","definition of entity \&$2;")."\">");
warn "Seen text entity $2" if ($debug{'entities'});
@@ -548,8 +549,8 @@
$self->pushline($post);
} else {
warn "No entity declaration detected in ~~$prolog~~...\n" if ($debug{'entities'});
+ $self->pushline($prolog);
}
- $self->pushline($prolog);
# The parse object.
# Damn SGMLS. It makes me crude things.
20 years, 3 months
[Po4a-devel][CVS] po4a/debian changelog,1.62,1.63
by Martin Quinson
Update of /cvsroot/po4a/po4a/debian
In directory haydn:/tmp/cvs-serv9416/debian
Modified Files:
changelog
Log Message:
Document last changes, and put 0.17.2 on the track
Index: changelog
===================================================================
RCS file: /cvsroot/po4a/po4a/debian/changelog,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -d -r1.62 -r1.63
--- changelog 21 Jul 2004 02:10:06 -0000 1.62
+++ changelog 1 Aug 2004 20:36:51 -0000 1.63
@@ -1,3 +1,19 @@
+po4a (0.17.2-1) experimental; urgency=low
+
+ NOT YET RELEASED
+
+ [Martin Quinson]
+ - add refentry to verbatim so that no spaces are added.
+ Closes #262739 (in Debian).
+ - Overhaul of po4a(7)
+ - Various pod fixup
+
+ [Jordi Vilalta]
+ - Further pod and english fixup
+ - Greatly improve the spanish documentation translation
+
+ -- Martin Quinson <martin.quinson(a)tuxfamily.org> Sun, 1 Aug 2004 13:36:08 -0700
+
po4a (0.17.1-1) unstable; urgency=low
[Jordi Vilalta]
20 years, 3 months
[Po4a-devel][CVS] po4a/lib/Locale/Po4a Sgml.pm,1.26,1.27
by Martin Quinson
Update of /cvsroot/po4a/po4a/lib/Locale/Po4a
In directory haydn:/tmp/cvs-serv25428/lib/Locale/Po4a
Modified Files:
Sgml.pm
Log Message:
add refentry to verbatim so that no spaces are added. Closes Debian's #262739
Index: Sgml.pm
===================================================================
RCS file: /cvsroot/po4a/po4a/lib/Locale/Po4a/Sgml.pm,v
retrieving revision 1.26
retrieving revision 1.27
diff -u -d -r1.26 -r1.27
--- Sgml.pm 29 Jul 2004 01:27:51 -0000 1.26
+++ Sgml.pm 1 Aug 2004 20:33:13 -0000 1.27
@@ -383,7 +383,7 @@
"table tbody textobject tgroup thead tip toc ".
"variablelist varlistentry videoobject ".
"warning",
- "verbatim" => "address programlisting literallayout screen",
+ "verbatim" => "address programlisting literallayout refentry screen",
"ignore" => "action affiliation anchor application author authorinitials ".
"command citation citerefentry citetitle classname co computeroutput constant corpauthor ".
"database ".
20 years, 3 months
[Po4a-devel][CVS] po4a/po/pod fr.po,1.29,1.30
by Pierre Machard
Update of /cvsroot/po4a/po4a/po/pod
In directory haydn:/tmp/cvs-serv24433
Modified Files:
fr.po
Log Message:
Untypoed
Index: fr.po
===================================================================
RCS file: /cvsroot/po4a/po4a/po/pod/fr.po,v
retrieving revision 1.29
retrieving revision 1.30
diff -u -d -r1.29 -r1.30
--- fr.po 21 Jul 2004 00:16:51 -0000 1.29
+++ fr.po 1 Aug 2004 18:11:29 -0000 1.30
@@ -4785,7 +4785,7 @@
msgstr ""
"Ajoute le contenu d'un fichier dans le résultat (pour ajouter le nom du "
"traducteur, ou une section nommée \"À propos de cette traduction\", par "
-"exemple). La première lign du fichier à ajouter (de \"l'addendum\") doit "
+"exemple). La première ligne du fichier à ajouter (de \"l'addendum\") doit "
"être un entête valide indiquant où l'ajout doit avoir lieu (voir la section "
"I<Comment ajouter des choses n'étant pas des traduction> dans po4a(7))."
20 years, 3 months
[Po4a-devel][CVS] po4a/lib/Locale/Po4a Po.pm,1.14,1.15
by Martin Quinson
Update of /cvsroot/po4a/po4a/lib/Locale/Po4a
In directory haydn:/tmp/cvs-serv23112
Modified Files:
Po.pm
Log Message:
Ok, select does not work, and I shouldn't have commited an half broken function in the first place. But now that it's done (I though it was pod cleanups), comment the part generating such an awfull warning
Index: Po.pm
===================================================================
RCS file: /cvsroot/po4a/po4a/lib/Locale/Po4a/Po.pm,v
retrieving revision 1.14
retrieving revision 1.15
diff -u -d -r1.14 -r1.15
--- Po.pm 29 Jul 2004 01:27:51 -0000 1.14
+++ Po.pm 1 Aug 2004 09:44:50 -0000 1.15
@@ -364,13 +364,13 @@
$comment = $self->{po}{$msgid}{'comment'};
$automatic = $self->{po}{$msgid}{'automatic'};
- $res->push_raw('msgid' => $msgid,
- 'msgstr' => $msgstr,
- 'flags' => $flags,
- 'type' => $type,
- 'reference' => $ref,
- 'comment' => $comment,
- 'automatic' => $automatic);
+# $res->push_raw('msgid' => $msgid,
+# 'msgstr' => $msgstr,
+# 'flags' => $flags,
+# 'type' => $type,
+# 'reference' => $ref,
+# 'comment' => $comment,
+# 'automatic' => $automatic);
}
return $res;
20 years, 3 months