Move printing into it's own library
[profile/ivi/qtbase.git] / bin / findtr
1 #!/usr/bin/perl -w
2 # vi:wrap:
3
4 # See Qt I18N documentation for usage information.
5
6 use POSIX qw(strftime);
7
8 $projectid='PROJECT VERSION';
9 $datetime = strftime "%Y-%m-%d %X %Z", localtime;
10 $charset='iso-8859-1';
11 $translator='FULLNAME <EMAIL@ADDRESS>';
12 $revision_date='YYYY-MM-DD';
13
14 $real_mark = "tr";
15 $noop_mark = "QT_TR_NOOP";
16 $scoped_mark = "qApp->translate";
17 $noop_scoped_mark = "QT_TRANSLATE_NOOP";
18
19 $header=
20 '# This is a Qt message file in .po format.  Each msgid starts with
21 # a scope.  This scope should *NOT* be translated - eg. translating
22 # from French to English, "Foo::Bar" would be translated to "Pub",
23 # not "Foo::Pub".
24 msgid ""
25 msgstr ""
26 "Project-Id-Version: '.$projectid.'\n"
27 "POT-Creation-Date: '.$datetime.'\n"
28 "PO-Revision-Date: '.$revision_date.'\n"
29 "Last-Translator: '.$translator.'\n"
30 "Content-Type: text/plain; charset='.$charset.'\n"
31
32 ';
33
34
35
36
37 $scope = "";
38
39 if ( $#ARGV < 0 ) {
40     print STDERR "Usage:  findtr sourcefile ...  >project.po\n";
41     exit 1;
42 }
43
44
45 sub outmsg {
46     my ($file, $line, $scope, $msgid) = @_;
47     # unesc
48     $msgid =~ s/$esc:$esc:$esc/::/gs;
49     $msgid =~ s|$esc/$esc/$esc|//|gs;
50
51     # Remove blank lines
52     $msgid =~ s/\n\n+/\n/gs;
53     $msgid = "\"\"\n$msgid" if $msgid =~ /\n/s;
54     print "#: $file:$line\n";
55     $msgid =~ s/^"//; #"emacs bug
56     print "msgid \"${scope}::$msgid\n";
57     #print "msgstr \"$msgid\n";
58     print "msgstr \"\"\n";
59     print "\n";
60 }
61
62 sub justlines {
63     my $l = @_;
64     $l =~ tr|\n||dc;
65     return $l;
66 }
67
68 print $header;
69
70
71 foreach $file ( @ARGV ) {
72     next unless open( I, "< $file" );
73
74     $source = join( "", <I> );
75
76     # Find esc. Avoid bad case 1/// -> 1/1/1/1 -> ///1
77     $esc = 1;
78     while ( $source =~ m!(?:$esc/$esc/$esc)|(?:$esc///)
79             |(?:$esc:$esc:$esc)|(?:$esc:\:\:)! ) {
80         $esc++;
81     }
82
83     # Hide quoted :: in practically all strings
84     $source =~ s/\"([^"\n]*)::([^"\n]*)\"/\"$1$esc:$esc:$esc$2\"/g;
85
86     # Hide quoted // in practically all strings
87     $source =~ s|\"([^"\n]*)//([^"\n]*)\"|\"$1$esc/$esc/$esc$2\"|g;
88
89
90     # strip comments -- does not handle "/*" in strings
91     while( $source =~ s|/\*(.*?)\*/|justlines($1)|ges ) { }
92     while( $source =~ s|//(.*?)\n|\n|g ) { }
93
94     while( $source =~ /
95             (?:
96                 # Some doublequotes are "escaped" to help vim syntax highlight
97
98                 # $1 = scope; $2 = parameters etc.
99                 (?:
100                     # Scoped function name ($1 is scope).
101                     (\w+)::(?:\w+)
102                     \s*
103                     # Parameters etc up to open-curly - no semicolons
104                     \(([^();]*)\)
105                     \s*
106                     (?:\{|:)
107                 )
108               |
109                 # $3 - one-argument msgid
110                 (?:\b
111                     # One of the marks
112                     (?:$real_mark|$noop_mark)
113                     \s*
114                     # The parameter
115                     \(\s*((?:"(?:[^"]|[^\\]\\")*"\s*)+)\)
116                 )
117               |
118                 # $4,$5 - two-argument msgid
119                 (?:\b
120                     # One of the scoped marks
121                     (?:$scoped_mark|$noop_scoped_mark)
122                     \s*
123                     # The parameters
124                     \(
125                         # The scope parameter
126                         \s*"([^\"]*)"
127                         \s*,\s*
128                         # The msgid parameter
129                         \s*((?:\"(?:[^"]|[^\\]\\")*"\s*)+) #"emacs
130                     \)
131                 )
132               |
133                 # $6,$7 - scoped one-argument msgid
134                 (?:\b
135                     # The scope
136                     (\w+)::
137                     # One of the marks
138                     (?:$real_mark)
139                     \s*
140                     # The parameter
141                     \(\s*((?:"(?:[^"]|[^\\]\\")*"\s*)+)\)
142                 )
143             )/gsx )
144     {
145         @lines = split /^/m, "$`";
146         $line = @lines;
147         if ( defined( $1 ) ) {
148             if ( $scope ne $1 ) {
149                 $sc=$1;
150                 $etc=$2;
151                 # remove strings
152                 $etc =~ s/"(?:[^"]|[^\\]\\")"//g;
153                 # count ( and )
154                 @open = split /\(/m, $etc;
155                 @close = split /\)/m, $etc;
156                 if ( $#open == $#close ) {
157                     $scope = $sc;
158                 }
159             }
160             next;
161         }
162
163         if ( defined( $3 ) ) {
164             $this_scope = $scope;
165             $msgid = $3;
166         } elsif ( defined( $4 ) ) {
167             $this_scope = $4;
168             $msgid = $5;
169         } elsif ( defined( $6 ) ) {
170             $this_scope = $6;
171             $msgid = $7;
172         } else {
173             next;
174         }
175
176         $msgid =~ s/^\s*//;
177         $msgid =~ s/\s*$//;
178
179         # Might still be non-unique eg. tr("A" "B")  vs.  tr("A"  "B").
180
181         $location{"${this_scope}::${msgid}"} = "$file:$line";
182     }
183 }
184
185 for $scoped_msgid ( sort keys %location ) {
186     ($scope,$msgid) = $scoped_msgid =~ m/([^:]*)::(.*)/s;
187     ($file,$line) = $location{$scoped_msgid} =~ m/([^:]*):(.*)/s;
188     outmsg($file,$line,$scope,$msgid);
189 }