summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
authorDaniel Stenberg <daniel@haxx.se>2006-04-03 21:11:11 +0000
committerDaniel Stenberg <daniel@haxx.se>2006-04-03 21:11:11 +0000
commitc06e7772ff81ed4bbc78377a6e16456456f3e96c (patch)
tree0eee2026f47d5041461d2a35349f0c2175e97ab0 /tools
parenta87203651e35f368bf1d8bca5a846a0b9fb657c1 (diff)
downloadrockbox-c06e7772ff81ed4bbc78377a6e16456456f3e96c.tar.gz
rockbox-c06e7772ff81ed4bbc78377a6e16456456f3e96c.zip
langv2
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@9470 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'tools')
-rwxr-xr-xtools/binlang130
-rwxr-xr-xtools/buildzip.pl11
-rwxr-xr-xtools/configure4
-rwxr-xr-xtools/genlang611
-rwxr-xr-xtools/genlang2595
-rwxr-xr-xtools/uplang135
6 files changed, 554 insertions, 932 deletions
diff --git a/tools/binlang b/tools/binlang
index 053180317a..90681348f9 100755
--- a/tools/binlang
+++ b/tools/binlang
@@ -8,7 +8,7 @@
8# \/ \/ \/ \/ \/ 8# \/ \/ \/ \/ \/
9# $Id$ 9# $Id$
10# 10#
11# Copyright (C) 2002 by Daniel Stenberg <daniel@haxx.se> 11# Copyright (C) 2002, 2006 by Daniel Stenberg <daniel@haxx.se>
12# 12#
13# All files in this archive are subject to the GNU General Public License. 13# All files in this archive are subject to the GNU General Public License.
14# See the file COPYING in the source tree root for full license agreement. 14# See the file COPYING in the source tree root for full license agreement.
@@ -18,130 +18,8 @@
18# 18#
19############################################################################ 19############################################################################
20 20
21if(!$ARGV[0] || !$ARGV[1] || !$ARGV[2]) { 21print <<MOO
22 print <<MOO 22The tool formerly known as 'binlang' is no longer used. We now use
23Usage: binlang <english file> <language file> <output file> 23genlang2 with the -b option to generate binary language files.
24
25Generate a binary language file.
26MOO 24MOO
27; 25;
28 exit;
29}
30
31if($ARGV[0] eq "-v") {
32 shift @ARGV;
33 $debug=1;
34}
35
36my $english = $ARGV[0];
37my $input = $ARGV[1];
38my $output = $ARGV[2];
39
40my $idnum=0;
41
42open(ENG, "<$english") or die "Can't open $english";
43open(LANG, "<$input") or die "Can't open $input";
44open(OUTF, ">$output") or die "Can't open $output";
45
46my $langversion = 3;
47
48binmode OUTF;
49
50printf OUTF ("\x1a%c", $langversion); # magic lang file header
51
52#
53# We scan the english file to get the correct order of the id numbers
54#
55my $idnum=0; # start with a true number
56while(<ENG>) {
57 if($_ =~ / *\#/) {
58 # comment
59 next;
60 }
61 # get rid of DOS newlines
62 $_ =~ s/\r//g;
63 if($_ =~ /^ *([a-z]+): *(.*)/) {
64 ($var, $value) = ($1, $2);
65 $set{$var} = $value;
66
67 # "new" is always the last one, so now we have them all
68 if($var eq "new") {
69 $value = $set{'eng'};
70
71 if($value =~ s/^\"(.*)\"\s*$/$1/g) {
72 # Skip voice-only entries
73 if($set{'id'} =~ /^VOICE_/) {
74 $idnum{$set{'id'}} = '_done_';
75 next;
76 }
77
78 # Assign an ID number to this entry
79 $idnum{$set{'id'}}=$idnum;
80 $idnum++;
81 }
82 undef %set;
83 }
84 }
85}
86close(ENG);
87
88while(<LANG>) {
89 if($_ =~ /^ *\#/) {
90 # comment
91 next;
92 }
93 # get rid of DOS newlines
94 $_ =~ s/\r//g;
95 if($_ =~ /^ *([a-z]+): *(.*)/) {
96 ($var, $value) = ($1, $2);
97
98 $set{$var} = $value;
99
100 # "new" is always the last one, so now we have them all
101 if($var eq "new") {
102 $idnum = $idnum{$set{'id'}};
103
104 # Skip already processed entries (like voice-only ones)
105 next if($idnum eq '_done_');
106
107 if(!$value) {
108 # if not set, get the english version
109 $value = $set{'eng'};
110 }
111
112 if($value =~ s/^\"(.*)\"\s*$/$1/g) {
113 if($idnum eq "") {
114 warn "Found no ".$set{'id'}." in english file!\n";
115 }
116 else {
117 $idnum{$set{'id'}} = '_done_';
118
119 printf OUTF ("%c%c%s\x00",
120 ($idnum>>8), ($idnum&0xff),
121 $value);
122 if($debug) {
123 printf("%02x => %s\n", $idnum, $value);
124 }
125 }
126 }
127 else {
128 warn "String for ".$set{'id'}." misses quotes\n";
129 }
130
131 undef %set;
132 }
133
134 }
135
136}
137close(LANG);
138
139close(OUTF);
140
141foreach $k (keys(%idnum))
142{
143 if($idnum{$k} ne '_done_')
144 {
145 warn "Missing ID in $input: $k\n";
146 }
147}
diff --git a/tools/buildzip.pl b/tools/buildzip.pl
index a7c8fb64bc..81010def07 100755
--- a/tools/buildzip.pl
+++ b/tools/buildzip.pl
@@ -17,6 +17,7 @@ my $output="rockbox.zip";
17my $verbose; 17my $verbose;
18my $exe; 18my $exe;
19my $target; 19my $target;
20my $archos;
20 21
21while(1) { 22while(1) {
22 if($ARGV[0] eq "-r") { 23 if($ARGV[0] eq "-r") {
@@ -31,6 +32,12 @@ while(1) {
31 shift @ARGV; 32 shift @ARGV;
32 } 33 }
33 34
35 elsif($ARGV[0] eq "-t") {
36 # The target name as used in ARCHOS in the root makefile
37 $archos=$ARGV[1];
38 shift @ARGV;
39 shift @ARGV;
40 }
34 elsif($ARGV[0] eq "-o") { 41 elsif($ARGV[0] eq "-o") {
35 $output=$ARGV[1]; 42 $output=$ARGV[1];
36 shift @ARGV; 43 shift @ARGV;
@@ -72,8 +79,8 @@ sub buildlangs {
72 for(@files) { 79 for(@files) {
73 my $output = $_; 80 my $output = $_;
74 $output =~ s/(.*)\.lang/$1.lng/; 81 $output =~ s/(.*)\.lang/$1.lng/;
75 print "lang $_\n" if($verbose); 82 print "$ROOT/tools/genlang -e=$dir/english.lang -t=$archos -b=$outputlang/$output $dir/$_\n" if($verbose);
76 system ("$ROOT/tools/binlang $dir/english.lang $dir/$_ $outputlang/$output >/dev/null 2>&1"); 83 system ("$ROOT/tools/genlang -e=$dir/english.lang -t=$archos -b=$outputlang/$output $dir/$_ >/dev/null 2>&1");
77 } 84 }
78} 85}
79 86
diff --git a/tools/configure b/tools/configure
index c2d4d90daf..72ef48cf3b 100755
--- a/tools/configure
+++ b/tools/configure
@@ -1171,6 +1171,8 @@ sed > Makefile \
1171 1171
1172ifndef V 1172ifndef V
1173SILENT=@ 1173SILENT=@
1174else
1175VERBOSEOPT=-v
1174endif 1176endif
1175 1177
1176export ROOTDIR=@ROOTDIR@ 1178export ROOTDIR=@ROOTDIR@
@@ -1255,7 +1257,7 @@ tags:
1255 \$(SILENT)\$(MAKE) -C \$(APPSDIR)/plugins/lib tags 1257 \$(SILENT)\$(MAKE) -C \$(APPSDIR)/plugins/lib tags
1256 1258
1257zip: 1259zip:
1258 \$(SILENT)\$(TOOLSDIR)/buildzip.pl -r "\$(ROOTDIR)" \$(TARGET) \$(BINARY) 1260 \$(SILENT)\$(TOOLSDIR)/buildzip.pl \$(VERBOSEOPT) -t \"\$(ARCHOS)\" -r "\$(ROOTDIR)" \$(TARGET) \$(BINARY)
1259 1261
12607zip: 12627zip:
1261 \$(SILENT)\$(TOOLSDIR)/buildzip.pl -o "rockbox.7z" -z "7za a" -r "\$(ROOTDIR)" \$(TARGET) \$(BINARY) 1263 \$(SILENT)\$(TOOLSDIR)/buildzip.pl -o "rockbox.7z" -z "7za a" -r "\$(ROOTDIR)" \$(TARGET) \$(BINARY)
diff --git a/tools/genlang b/tools/genlang
index cde23f85fa..07c866a288 100755
--- a/tools/genlang
+++ b/tools/genlang
@@ -1,28 +1,430 @@
1#!/usr/bin/perl -s 1#!/usr/bin/perl -s
2# __________ __ ___.
3# Open \______ \ ____ ____ | | _\_ |__ _______ ___
4# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7# \/ \/ \/ \/ \/
8# $Id$
9#
10# Copyright (C) 2006 by Daniel Stenberg
11#
12
13# binary version for the binary lang file
14my $langversion = 2; # 2 is the latest one used in the v1 format
15
16# A note for future users and readers: The original v1 language system allowed
17# the build to create and use a different language than english built-in. We
18# removed that feature from our build-system, but the build scripts still had
19# the ability. But, starting now, this ability is no longer provided since I
20# figured it was boring and unnecessary to write support for now since we
21# don't use it anymore.
2 22
3if(!$ARGV[0]) { 23if(!$ARGV[0]) {
4 print <<MOO 24 print <<MOO
5Usage: genlang [-p=<prefix>] <language file> 25Usage: genlang2 [options] <langv2 file>
26
27 -p=<prefix>
28 Make the tool create a [prefix].c and [prefix].h file.
29
30 -b=<outfile>
31 Make the tool create a binary language (.lng) file namaed [outfile].
32 The use of this option requires that you also use -e.
33
34 -u
35 Update language file. Given the translated file and the most recent english
36 file, you\'ll get an updated version sent to stdout. Suitable action to do
37 when you intend to update a translation.
38
39 -e=<english lang file>
40 Point out the english (original source) file, to use that as master
41 language template. Used in combination with -b or -u.
6 42
7When running this program. <prefix>.h and <prefix>.c will be created in the 43 -t=<target>
8"current directory". <prefix> is "lang" by default. 44 Specify which target you want the translations/phrases for. Required when
45 -b or -p is used.
46
47 -o
48 Voice mode output. Outputs all id: and voice: lines for the given target!
49
50 -v
51 Enables verbose (debug) output.
9MOO 52MOO
10; 53;
11 exit; 54 exit;
12} 55}
13 56
57# How update works:
58#
59# 1) scan the english file, keep the whole <phrase> for each phrase.
60# 2) read the translated file, for each end of phrase, compare:
61# A) all source strings, if there's any change there should be a comment about
62# it output
63# B) the desc fields
64#
65# 3) output the phrase with the comments from above
66# 4) check which phrases that the translated version didn't have, and spit out
67# the english version of those
68#
69
14my $prefix = $p; 70my $prefix = $p;
15if(!$prefix) { 71my $binary = $b;
16 $prefix="lang"; 72my $update = $u;
73
74my $english = $e;
75my $voiceout = $o;
76
77my $check = ($binary?1:0) + ($prefix?1:0) + ($update?1:0) + ($voiceout?1:0);
78
79if($check > 1) {
80 print "Please use only one of -p, -u, -o and -b\n";
81 exit;
82}
83if(!$check) {
84 print "Please use at least one of -p, -u, -o and -b\n";
85 exit;
86}
87if(($binary || $update || $voiceout) && !$english) {
88 print "Please use -e too when you use -b, -o or -u\n";
89 exit;
90}
91
92my $target = $t;
93if(!$target && !$update) {
94 print "Please specify a target (with -t)!\n";
95 exit;
17} 96}
97my $verbose=$v;
98
99my %id; # string to num hash
100my @idnum; # num to string array
101
102my %source; # id string to source phrase hash
103my %dest; # id string to dest phrase hash
104my %voice; # id string to voice phrase hash
18 105
19my $input = $ARGV[0]; 106my $input = $ARGV[0];
20 107
21open(HFILE, ">$prefix.h"); 108my @m;
22open(CFILE, ">$prefix.c"); 109my $m="blank";
110
111sub match {
112 my ($string, $pattern)=@_;
113
114 $pattern =~ s/\*/.?*/g;
115 $pattern =~ s/\?/./g;
116
117 return ($string =~ $pattern);
118}
119
120sub blank {
121 # nothing to do
122}
123
124my %head;
125sub header {
126 my ($full, $n, $v)=@_;
127 $head{$n}=$v;
128}
129
130my %phrase;
131sub phrase {
132 my ($full, $n, $v)=@_;
133 $phrase{$n}=$v;
134}
135
136sub parsetarget {
137 my ($debug, $strref, $full, $n, $v)=@_;
138 my $string;
139 my @all= split(" *, *", $n);
140 my $test;
141 for $test (@all) {
142# print "TEST ($debug) $target for $test\n";
143 if(match($target, $test)) {
144 $string = $v;
145# print "MATCH: $test => $v\n";
146 }
147 }
148 if($string) {
149 $$strref = $string;
150 }
151 return $string;
152}
153
154my $src;
155sub source {
156 parsetarget("src", \$src, @_);
157}
158
159my $dest;
160sub dest {
161 parsetarget("dest", \$dest, @_);
162}
163
164my $voice;
165sub voice {
166 parsetarget("voice", \$voice, @_);
167}
168
169my %idmap;
170my %english;
171if($english) {
172 # For the cases where the english file needs to be scanned/read, we do
173 # it before we read the translated file. For -b it isn't necessary, but for
174 # -u it is convenient.
175
176 my $idnum=0; # start with a true number
177 my $vidnum=0x8000; # first voice id
178 open(ENG, "<$english") || die "can't open $english";
179 my @phrase;
180 my $id;
181 while(<ENG>) {
182
183 # get rid of DOS newlines
184 $_ =~ s/\r//g;
185
186 if($_ =~ /^ *\<phrase\>/) {
187 # this is the start of a phrase
188 }
189 elsif($_ =~ /^ *\<\/phrase\>/) {
190 # this is the end of a phrase, add it to the english hash
191 $english{$id}=join("", @phrase);
192 undef @phrase;
193 }
194 elsif($_ ne "\n") {
195 # gather everything related to this phrase
196 push @phrase, $_;
197 }
198
199 if($_ =~ /^ *id: ([^ \t\n]+)/i) {
200 $id=$1;
201 # voice-only entries get a difference range
202 if($id =~ /^VOICE_/) {
203 # Assign an ID number to this entry
204 $idmap{$id}=$vidnum;
205 $vidnum++;
206 }
207 else {
208 # Assign an ID number to this entry
209 $idmap{$id}=$idnum;
210 $idnum++;
211 }
212 }
213 }
214 close(ENG);
215}
216
217# a function that compares the english phrase with the translated one.
218# compare source strings and desc
219
220# Then output the updated version!
221sub compare {
222 my ($idstr, $engref, $locref)=@_;
223 my ($edesc, $ldesc);
224 my ($esource, $lsource);
225 my $mode=0;
226
227 for my $l (@$engref) {
228 if($l =~ /^ *desc: (.*)/) {
229 $edesc=$1;
230 }
231 elsif($l =~ / *\<source\>/i) {
232 $mode=1;
233 }
234 elsif($mode) {
235 if($l =~ / *\<\/source\>/i) {
236 last;
237 }
238 $esource .= "$l\n";
239 }
240 }
241
242 my @show;
243 my @source;
244
245 $mode = 0;
246 for my $l (@$locref) {
247 if($l =~ /^ *desc: (.*)/) {
248 $ldesc=$1;
249 if($edesc ne $ldesc) {
250 $l = "### The 'desc' field differs from the english!\n### the previously used desc is commented below:\n### desc: $ldesc\n desc: $edesc\n";
251 }
252 push @show, $l;
253 }
254 elsif($l =~ / *\<source\>/i) {
255 $mode=1;
256 push @show, $l;
257 }
258 elsif($mode) {
259 if($l =~ / *\<\/source\>/i) {
260 $mode = 0;
261 print @show;
262 if($esource ne $lsource) {
263 print "### The <source> section differs from the english!\n",
264 "### the previously used one is commented below:\n";
265 for(split("\n", $lsource)) {
266 print "### $_\n";
267 }
268 print $esource;
269 }
270 else {
271 print $lsource;
272 }
273 undef @show; # start over
274
275 push @show, $l;
276 }
277 else {
278 $lsource .= "$l";
279 }
280 }
281 else {
282 push @show, $l;
283 }
284 }
285
286
287 print @show;
288}
289
290my $idcount; # counter for lang ID numbers
291my $voiceid=0x8000; # counter for voice-only ID numbers
292
293#
294# Now start the scanning of the selected language string
295#
296
297open(LANG, "<$input");
298my @phrase;
299while(<LANG>) {
300
301 $line++;
302
303 # get rid of DOS newlines
304 $_ =~ s/\r//g;
305
306 if($_ =~ /^( *\#|[ \t\n\r]*\z)/) {
307 # comment or empty line
308 next;
309 }
310
311 my $ll = $_;
23 312
24print HFILE <<MOO 313 # print "M: $m\n";
25/* This file was automatically generated using genlang */ 314
315 push @phrase, $ll;
316
317 # this is an XML-lookalike tag
318 if(/ *<([^>]*)>/) {
319 my $part = $1;
320 #print "P: $part\n";
321
322 if($part =~ /^\//) {
323 # this was a closing tag
324
325 if($part eq "/phrase") {
326 # closing the phrase
327
328 my $idstr = $phrase{'id'};
329 my $idnum;
330
331 if($dest =~ /^none\z/i) {
332 # "none" as dest means that this entire phrase is to be
333 # ignored
334 #print "dest is NONE!\n";
335 }
336 else {
337
338 # Use the ID name to figure out which id number range we
339 # should use for this phrase. Voice-only strings are
340 # separated.
341
342 if($idstr =~ /^VOICE/) {
343 $idnum = $voiceid++;
344 }
345 else {
346 $idnum = $idcount++;
347 }
348
349 $id{$idstr} = $idnum;
350 $idnum[$idnum]=$idstr;
351
352 $source{$idstr}=$src;
353 $dest{$idstr}=$dest;
354 $voice{$idstr}=$voice;
355
356 if($verbose) {
357 print "id: $phrase{id} ($idnum)\n";
358 print "source: $src\n";
359 print "dest: $dest\n";
360 print "voice: $voice\n";
361 }
362
363 undef $src;
364 undef $dest;
365 undef $voice;
366 undef %phrase;
367 }
368
369 if($update) {
370 my $e = $english{$idstr};
371
372 if($e) {
373 # compare original english with this!
374 my @eng = split("\n", $english{$idstr});
375
376 compare($idstr, \@eng, \@phrase);
377
378 $english{$idstr}=""; # clear it
379 }
380 else {
381 print "### $idstr: The phrase is not used. Skipped\n";
382 }
383 }
384 undef @phrase;
385
386 } # end of </phrase>
387
388 # starts with a slash, this _ends_ this section
389 $m = pop @m; # get back old value, the previous level's tag
390 next;
391 } # end of tag close
392
393 # This is an opening (sub) tag
394
395 push @m, $m; # store old value
396 $m = $1;
397 next;
398 }
399
400 if(/^ *([^:]+): *(.*)/) {
401 my ($name, $val)=($1, $2);
402 &$m($_, $name, $val);
403 }
404}
405close(LANG);
406
407if($update) {
408 my $any=0;
409 for(keys %english) {
410 if($english{$_}) {
411 print "###\n",
412 "### This phrase below was not present in the translated file\n",
413 "<phrase>\n";
414 print $english{$_};
415 print "</phrase>\n";
416 }
417 }
418}
419
420if($prefix) {
421 # We create a .c and .h file
422
423 open(HFILE, ">$prefix.h");
424 open(CFILE, ">$prefix.c");
425
426 print HFILE <<MOO
427/* This file was automatically generated using genlang2 */
26/* 428/*
27 * The str() macro/functions is how to access strings that might be 429 * The str() macro/functions is how to access strings that might be
28 * translated. Use it like str(MACRO) and expect a string to be 430 * translated. Use it like str(MACRO) and expect a string to be
@@ -37,12 +439,12 @@ extern unsigned char *language_strings[];
37extern const unsigned char language_builtin[]; 439extern const unsigned char language_builtin[];
38 440
39/* The enum below contains all available strings */ 441/* The enum below contains all available strings */
40enum { 442enum \{
41MOO 443MOO
42 ; 444 ;
43 445
44print CFILE <<MOO 446 print CFILE <<MOO
45/* This file was automaticly generated using genlang, the strings come 447/* This file was automaticly generated using genlang2, the strings come
46 from "$input" */ 448 from "$input" */
47 449
48#include "$prefix.h" 450#include "$prefix.h"
@@ -50,87 +452,144 @@ print CFILE <<MOO
50unsigned char *language_strings[LANG_LAST_INDEX_IN_ARRAY]; 452unsigned char *language_strings[LANG_LAST_INDEX_IN_ARRAY];
51const unsigned char language_builtin[] = 453const unsigned char language_builtin[] =
52MOO 454MOO
53 ; 455;
54 456
55open(LANG, "<$input"); 457 # Output the ID names for the enum in the header file
56while(<LANG>) { 458 my $i;
57 $line++; 459 for $i (1 .. $idcount) {
58 if($_ =~ / *\#/) { 460 my $name=$idnum[$i - 1]; # get the ID name
59 # comment 461
60 next; 462 $name =~ s/\"//g; # cut off the quotes
463
464 printf HFILE (" %s,\n", $name);
61 } 465 }
62 # get rid of DOS newlines
63 $_ =~ s/\r//g;
64 if($_ =~ / *([a-z]+): *(.*)/) {
65 ($var, $value) = ($1, $2);
66 # print "$var => $value\n";
67 466
68 $set{$var} = $value; 467# Output separation marker for last string ID and the upcoming voice IDs
69 468
70 if( (($var eq "new") && $value && ($value !~ /^\"(.*)\"\W*$/)) || 469 print HFILE <<MOO
71 (($var eq "voice") && $value && ($value !~ /^\"(.*)\"\W*$/)) || 470 LANG_LAST_INDEX_IN_ARRAY, /* this is not a string, this is a marker */
72 (($var eq "eng") && ($value !~ /^\"(.*)\"\W*$/)) ) { 471 /* --- below this follows voice-only strings --- */
73 print "$input:$line:missing quotes for ".$set{'id'}."\n"; 472 VOICEONLY_DELIMITER = 0x8000,
74 $errors++; 473MOO
75 next; 474 ;
76 }
77 475
78 if($var eq "new") { 476# Output the ID names for the enum in the header file
79 # the last one for a single phrase 477 my $i;
478 for $i (0x8000 .. ($voiceid-1)) {
479 my $name=$idnum[$i]; # get the ID name
480
481 $name =~ s/\"//g; # cut off the quotes
482
483 printf HFILE (" %s,\n", $name);
484 }
80 485
81 if(!$value || ($value eq "\"\"") ) { 486 # Output end of enum
82 # if not set, get the english version 487 print HFILE "\n};\n/* end of generated enum list */\n";
83 $value = $set{'eng'}; 488
84 } 489 # Output the target phrases for the source file
85# print "VOICE: ".$set{'voice'}." VALUE: $value\n"; 490 for $i (1 .. $idcount) {
86 # Note: if both entries are "", the string is deprecated, 491 my $name=$idnum[$i - 1]; # get the ID
87 # but must be included to maintain compatibility 492 my $dest = $dest{$name}; # get the destination phrase
88 if($set{'id'} =~ /^VOICE_/) { 493
89 # voice-only 494 $dest =~ s:\"$:\\0\":; # insert a \0 before the second quote
90 push @vfile, $set{'id'};
91 }
92 else {
93 push @hfile, $set{'id'};
94 $value =~ s/^\"(.*)\"\W*$/\"$1\\0\"/;
95 print CFILE " $value\n";
96 }
97 495
98 undef %set; 496 if(!$dest) {
497 # this is just to be on the safe side
498 $dest = '"\0"';
99 } 499 }
100 500
501 printf CFILE (" %s\n", $dest);
101 } 502 }
102 503
103} 504# Output end of string chunk
104close(LANG); 505 print CFILE <<MOO
506;
507/* end of generated string list */
508MOO
509;
105 510
106for(@hfile) { 511 close(HFILE);
107 print HFILE " $_,\n"; 512 close(CFILE);
513} # end of the c/h file generation
514elsif($binary) {
515 # Creation of a binary lang file was requested
516
517 # We must first scan the english file to get the correct order of the id
518 # numbers used there, as that is what sets the id order for all language
519 # files. The english file is scanned before the translated file was
520 # scanned.
521
522 open(OUTF, ">$binary") or die "Can't create $binary";
523 binmode OUTF;
524 printf OUTF ("\x1a%c", $langversion); # magic lang file header
525
526 # loop over the target phrases
527 for $i (1 .. $idcount) {
528 my $name=$idnum[$i - 1]; # get the ID
529 my $dest = $dest{$name}; # get the destination phrase
530
531 if($dest) {
532 $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes
533
534 # Now, make sure we get the number from the english sort order:
535 $idnum = $idmap{$name};
536
537 printf OUTF ("%c%c%s\x00", ($idnum>>8), ($idnum&0xff), $dest);
538 if($debug) {
539 printf("%02x => %s\n", $idnum, $value);
540 }
541 }
542 }
108} 543}
544elsif($voiceout) {
545 # voice output requested, display id: and voice: strings in a v1-like
546 # fashion
109 547
110print HFILE <<MOO 548 my @engl;
111 LANG_LAST_INDEX_IN_ARRAY, /* this is not a string, this is a marker */ 549
112 /* --- below this follows voice-only strings --- */ 550 # This loops over the strings in the translated language file order
113 VOICEONLY_DELIMITER = 0x8000, 551 my @ids = ((0 .. ($idcount-1)));
114MOO 552 push @ids, (0x8000 .. ($voiceid-1));
115 ; 553
554 #for my $id (@ids) {
555 # print "$id\n";
556 #}
557
558 for $i (@ids) {
559 my $name=$idnum[$i]; # get the ID
560 my $dest = $voice{$name}; # get the destination voice string
116 561
117for(@vfile) { 562 if($dest) {
118 print HFILE " $_,\n"; 563 $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes
564
565 # Now, make sure we get the number from the english sort order:
566 $idnum = $idmap{$name};
567
568 $engl[$idnum] = $i;
569
570 # print "Input index $i output index $idnum\n";
571
572 }
573 }
574 for my $i (@ids) {
575
576 my $o = $engl[$i];
577
578 my $name=$idnum[$o]; # get the ID
579 my $dest = $voice{$name}; # get the destination voice string
580
581 print "#$i\nid: $name\nvoice: $dest\n";
582 }
583
119} 584}
120 585
121print HFILE <<MOO
122};
123/* end of generated enum list */
124MOO
125 ;
126 586
127print CFILE <<MOO 587if($verbose) {
128; 588 printf("%d ID strings scanned\n", $idcount);
129/* end of generated string list */
130MOO
131 ;
132 589
133close(CFILE); 590 print "* head *\n";
134close(HFILE); 591 for(keys %head) {
592 printf "$_: %s\n", $head{$_};
593 }
594}
135 595
136exit $errors;
diff --git a/tools/genlang2 b/tools/genlang2
deleted file mode 100755
index 07c866a288..0000000000
--- a/tools/genlang2
+++ /dev/null
@@ -1,595 +0,0 @@
1#!/usr/bin/perl -s
2# __________ __ ___.
3# Open \______ \ ____ ____ | | _\_ |__ _______ ___
4# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7# \/ \/ \/ \/ \/
8# $Id$
9#
10# Copyright (C) 2006 by Daniel Stenberg
11#
12
13# binary version for the binary lang file
14my $langversion = 2; # 2 is the latest one used in the v1 format
15
16# A note for future users and readers: The original v1 language system allowed
17# the build to create and use a different language than english built-in. We
18# removed that feature from our build-system, but the build scripts still had
19# the ability. But, starting now, this ability is no longer provided since I
20# figured it was boring and unnecessary to write support for now since we
21# don't use it anymore.
22
23if(!$ARGV[0]) {
24 print <<MOO
25Usage: genlang2 [options] <langv2 file>
26
27 -p=<prefix>
28 Make the tool create a [prefix].c and [prefix].h file.
29
30 -b=<outfile>
31 Make the tool create a binary language (.lng) file namaed [outfile].
32 The use of this option requires that you also use -e.
33
34 -u
35 Update language file. Given the translated file and the most recent english
36 file, you\'ll get an updated version sent to stdout. Suitable action to do
37 when you intend to update a translation.
38
39 -e=<english lang file>
40 Point out the english (original source) file, to use that as master
41 language template. Used in combination with -b or -u.
42
43 -t=<target>
44 Specify which target you want the translations/phrases for. Required when
45 -b or -p is used.
46
47 -o
48 Voice mode output. Outputs all id: and voice: lines for the given target!
49
50 -v
51 Enables verbose (debug) output.
52MOO
53;
54 exit;
55}
56
57# How update works:
58#
59# 1) scan the english file, keep the whole <phrase> for each phrase.
60# 2) read the translated file, for each end of phrase, compare:
61# A) all source strings, if there's any change there should be a comment about
62# it output
63# B) the desc fields
64#
65# 3) output the phrase with the comments from above
66# 4) check which phrases that the translated version didn't have, and spit out
67# the english version of those
68#
69
70my $prefix = $p;
71my $binary = $b;
72my $update = $u;
73
74my $english = $e;
75my $voiceout = $o;
76
77my $check = ($binary?1:0) + ($prefix?1:0) + ($update?1:0) + ($voiceout?1:0);
78
79if($check > 1) {
80 print "Please use only one of -p, -u, -o and -b\n";
81 exit;
82}
83if(!$check) {
84 print "Please use at least one of -p, -u, -o and -b\n";
85 exit;
86}
87if(($binary || $update || $voiceout) && !$english) {
88 print "Please use -e too when you use -b, -o or -u\n";
89 exit;
90}
91
92my $target = $t;
93if(!$target && !$update) {
94 print "Please specify a target (with -t)!\n";
95 exit;
96}
97my $verbose=$v;
98
99my %id; # string to num hash
100my @idnum; # num to string array
101
102my %source; # id string to source phrase hash
103my %dest; # id string to dest phrase hash
104my %voice; # id string to voice phrase hash
105
106my $input = $ARGV[0];
107
108my @m;
109my $m="blank";
110
111sub match {
112 my ($string, $pattern)=@_;
113
114 $pattern =~ s/\*/.?*/g;
115 $pattern =~ s/\?/./g;
116
117 return ($string =~ $pattern);
118}
119
120sub blank {
121 # nothing to do
122}
123
124my %head;
125sub header {
126 my ($full, $n, $v)=@_;
127 $head{$n}=$v;
128}
129
130my %phrase;
131sub phrase {
132 my ($full, $n, $v)=@_;
133 $phrase{$n}=$v;
134}
135
136sub parsetarget {
137 my ($debug, $strref, $full, $n, $v)=@_;
138 my $string;
139 my @all= split(" *, *", $n);
140 my $test;
141 for $test (@all) {
142# print "TEST ($debug) $target for $test\n";
143 if(match($target, $test)) {
144 $string = $v;
145# print "MATCH: $test => $v\n";
146 }
147 }
148 if($string) {
149 $$strref = $string;
150 }
151 return $string;
152}
153
154my $src;
155sub source {
156 parsetarget("src", \$src, @_);
157}
158
159my $dest;
160sub dest {
161 parsetarget("dest", \$dest, @_);
162}
163
164my $voice;
165sub voice {
166 parsetarget("voice", \$voice, @_);
167}
168
169my %idmap;
170my %english;
171if($english) {
172 # For the cases where the english file needs to be scanned/read, we do
173 # it before we read the translated file. For -b it isn't necessary, but for
174 # -u it is convenient.
175
176 my $idnum=0; # start with a true number
177 my $vidnum=0x8000; # first voice id
178 open(ENG, "<$english") || die "can't open $english";
179 my @phrase;
180 my $id;
181 while(<ENG>) {
182
183 # get rid of DOS newlines
184 $_ =~ s/\r//g;
185
186 if($_ =~ /^ *\<phrase\>/) {
187 # this is the start of a phrase
188 }
189 elsif($_ =~ /^ *\<\/phrase\>/) {
190 # this is the end of a phrase, add it to the english hash
191 $english{$id}=join("", @phrase);
192 undef @phrase;
193 }
194 elsif($_ ne "\n") {
195 # gather everything related to this phrase
196 push @phrase, $_;
197 }
198
199 if($_ =~ /^ *id: ([^ \t\n]+)/i) {
200 $id=$1;
201 # voice-only entries get a difference range
202 if($id =~ /^VOICE_/) {
203 # Assign an ID number to this entry
204 $idmap{$id}=$vidnum;
205 $vidnum++;
206 }
207 else {
208 # Assign an ID number to this entry
209 $idmap{$id}=$idnum;
210 $idnum++;
211 }
212 }
213 }
214 close(ENG);
215}
216
217# a function that compares the english phrase with the translated one.
218# compare source strings and desc
219
220# Then output the updated version!
221sub compare {
222 my ($idstr, $engref, $locref)=@_;
223 my ($edesc, $ldesc);
224 my ($esource, $lsource);
225 my $mode=0;
226
227 for my $l (@$engref) {
228 if($l =~ /^ *desc: (.*)/) {
229 $edesc=$1;
230 }
231 elsif($l =~ / *\<source\>/i) {
232 $mode=1;
233 }
234 elsif($mode) {
235 if($l =~ / *\<\/source\>/i) {
236 last;
237 }
238 $esource .= "$l\n";
239 }
240 }
241
242 my @show;
243 my @source;
244
245 $mode = 0;
246 for my $l (@$locref) {
247 if($l =~ /^ *desc: (.*)/) {
248 $ldesc=$1;
249 if($edesc ne $ldesc) {
250 $l = "### The 'desc' field differs from the english!\n### the previously used desc is commented below:\n### desc: $ldesc\n desc: $edesc\n";
251 }
252 push @show, $l;
253 }
254 elsif($l =~ / *\<source\>/i) {
255 $mode=1;
256 push @show, $l;
257 }
258 elsif($mode) {
259 if($l =~ / *\<\/source\>/i) {
260 $mode = 0;
261 print @show;
262 if($esource ne $lsource) {
263 print "### The <source> section differs from the english!\n",
264 "### the previously used one is commented below:\n";
265 for(split("\n", $lsource)) {
266 print "### $_\n";
267 }
268 print $esource;
269 }
270 else {
271 print $lsource;
272 }
273 undef @show; # start over
274
275 push @show, $l;
276 }
277 else {
278 $lsource .= "$l";
279 }
280 }
281 else {
282 push @show, $l;
283 }
284 }
285
286
287 print @show;
288}
289
290my $idcount; # counter for lang ID numbers
291my $voiceid=0x8000; # counter for voice-only ID numbers
292
293#
294# Now start the scanning of the selected language string
295#
296
297open(LANG, "<$input");
298my @phrase;
299while(<LANG>) {
300
301 $line++;
302
303 # get rid of DOS newlines
304 $_ =~ s/\r//g;
305
306 if($_ =~ /^( *\#|[ \t\n\r]*\z)/) {
307 # comment or empty line
308 next;
309 }
310
311 my $ll = $_;
312
313 # print "M: $m\n";
314
315 push @phrase, $ll;
316
317 # this is an XML-lookalike tag
318 if(/ *<([^>]*)>/) {
319 my $part = $1;
320 #print "P: $part\n";
321
322 if($part =~ /^\//) {
323 # this was a closing tag
324
325 if($part eq "/phrase") {
326 # closing the phrase
327
328 my $idstr = $phrase{'id'};
329 my $idnum;
330
331 if($dest =~ /^none\z/i) {
332 # "none" as dest means that this entire phrase is to be
333 # ignored
334 #print "dest is NONE!\n";
335 }
336 else {
337
338 # Use the ID name to figure out which id number range we
339 # should use for this phrase. Voice-only strings are
340 # separated.
341
342 if($idstr =~ /^VOICE/) {
343 $idnum = $voiceid++;
344 }
345 else {
346 $idnum = $idcount++;
347 }
348
349 $id{$idstr} = $idnum;
350 $idnum[$idnum]=$idstr;
351
352 $source{$idstr}=$src;
353 $dest{$idstr}=$dest;
354 $voice{$idstr}=$voice;
355
356 if($verbose) {
357 print "id: $phrase{id} ($idnum)\n";
358 print "source: $src\n";
359 print "dest: $dest\n";
360 print "voice: $voice\n";
361 }
362
363 undef $src;
364 undef $dest;
365 undef $voice;
366 undef %phrase;
367 }
368
369 if($update) {
370 my $e = $english{$idstr};
371
372 if($e) {
373 # compare original english with this!
374 my @eng = split("\n", $english{$idstr});
375
376 compare($idstr, \@eng, \@phrase);
377
378 $english{$idstr}=""; # clear it
379 }
380 else {
381 print "### $idstr: The phrase is not used. Skipped\n";
382 }
383 }
384 undef @phrase;
385
386 } # end of </phrase>
387
388 # starts with a slash, this _ends_ this section
389 $m = pop @m; # get back old value, the previous level's tag
390 next;
391 } # end of tag close
392
393 # This is an opening (sub) tag
394
395 push @m, $m; # store old value
396 $m = $1;
397 next;
398 }
399
400 if(/^ *([^:]+): *(.*)/) {
401 my ($name, $val)=($1, $2);
402 &$m($_, $name, $val);
403 }
404}
405close(LANG);
406
407if($update) {
408 my $any=0;
409 for(keys %english) {
410 if($english{$_}) {
411 print "###\n",
412 "### This phrase below was not present in the translated file\n",
413 "<phrase>\n";
414 print $english{$_};
415 print "</phrase>\n";
416 }
417 }
418}
419
420if($prefix) {
421 # We create a .c and .h file
422
423 open(HFILE, ">$prefix.h");
424 open(CFILE, ">$prefix.c");
425
426 print HFILE <<MOO
427/* This file was automatically generated using genlang2 */
428/*
429 * The str() macro/functions is how to access strings that might be
430 * translated. Use it like str(MACRO) and expect a string to be
431 * returned!
432 */
433#define str(x) language_strings[x]
434
435/* this is the array for holding the string pointers.
436 It will be initialized at runtime. */
437extern unsigned char *language_strings[];
438/* this contains the concatenation of all strings, separated by \\0 chars */
439extern const unsigned char language_builtin[];
440
441/* The enum below contains all available strings */
442enum \{
443MOO
444 ;
445
446 print CFILE <<MOO
447/* This file was automaticly generated using genlang2, the strings come
448 from "$input" */
449
450#include "$prefix.h"
451
452unsigned char *language_strings[LANG_LAST_INDEX_IN_ARRAY];
453const unsigned char language_builtin[] =
454MOO
455;
456
457 # Output the ID names for the enum in the header file
458 my $i;
459 for $i (1 .. $idcount) {
460 my $name=$idnum[$i - 1]; # get the ID name
461
462 $name =~ s/\"//g; # cut off the quotes
463
464 printf HFILE (" %s,\n", $name);
465 }
466
467# Output separation marker for last string ID and the upcoming voice IDs
468
469 print HFILE <<MOO
470 LANG_LAST_INDEX_IN_ARRAY, /* this is not a string, this is a marker */
471 /* --- below this follows voice-only strings --- */
472 VOICEONLY_DELIMITER = 0x8000,
473MOO
474 ;
475
476# Output the ID names for the enum in the header file
477 my $i;
478 for $i (0x8000 .. ($voiceid-1)) {
479 my $name=$idnum[$i]; # get the ID name
480
481 $name =~ s/\"//g; # cut off the quotes
482
483 printf HFILE (" %s,\n", $name);
484 }
485
486 # Output end of enum
487 print HFILE "\n};\n/* end of generated enum list */\n";
488
489 # Output the target phrases for the source file
490 for $i (1 .. $idcount) {
491 my $name=$idnum[$i - 1]; # get the ID
492 my $dest = $dest{$name}; # get the destination phrase
493
494 $dest =~ s:\"$:\\0\":; # insert a \0 before the second quote
495
496 if(!$dest) {
497 # this is just to be on the safe side
498 $dest = '"\0"';
499 }
500
501 printf CFILE (" %s\n", $dest);
502 }
503
504# Output end of string chunk
505 print CFILE <<MOO
506;
507/* end of generated string list */
508MOO
509;
510
511 close(HFILE);
512 close(CFILE);
513} # end of the c/h file generation
514elsif($binary) {
515 # Creation of a binary lang file was requested
516
517 # We must first scan the english file to get the correct order of the id
518 # numbers used there, as that is what sets the id order for all language
519 # files. The english file is scanned before the translated file was
520 # scanned.
521
522 open(OUTF, ">$binary") or die "Can't create $binary";
523 binmode OUTF;
524 printf OUTF ("\x1a%c", $langversion); # magic lang file header
525
526 # loop over the target phrases
527 for $i (1 .. $idcount) {
528 my $name=$idnum[$i - 1]; # get the ID
529 my $dest = $dest{$name}; # get the destination phrase
530
531 if($dest) {
532 $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes
533
534 # Now, make sure we get the number from the english sort order:
535 $idnum = $idmap{$name};
536
537 printf OUTF ("%c%c%s\x00", ($idnum>>8), ($idnum&0xff), $dest);
538 if($debug) {
539 printf("%02x => %s\n", $idnum, $value);
540 }
541 }
542 }
543}
544elsif($voiceout) {
545 # voice output requested, display id: and voice: strings in a v1-like
546 # fashion
547
548 my @engl;
549
550 # This loops over the strings in the translated language file order
551 my @ids = ((0 .. ($idcount-1)));
552 push @ids, (0x8000 .. ($voiceid-1));
553
554 #for my $id (@ids) {
555 # print "$id\n";
556 #}
557
558 for $i (@ids) {
559 my $name=$idnum[$i]; # get the ID
560 my $dest = $voice{$name}; # get the destination voice string
561
562 if($dest) {
563 $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes
564
565 # Now, make sure we get the number from the english sort order:
566 $idnum = $idmap{$name};
567
568 $engl[$idnum] = $i;
569
570 # print "Input index $i output index $idnum\n";
571
572 }
573 }
574 for my $i (@ids) {
575
576 my $o = $engl[$i];
577
578 my $name=$idnum[$o]; # get the ID
579 my $dest = $voice{$name}; # get the destination voice string
580
581 print "#$i\nid: $name\nvoice: $dest\n";
582 }
583
584}
585
586
587if($verbose) {
588 printf("%d ID strings scanned\n", $idcount);
589
590 print "* head *\n";
591 for(keys %head) {
592 printf "$_: %s\n", $head{$_};
593 }
594}
595
diff --git a/tools/uplang b/tools/uplang
index 81c3a3acc5..0f0106f98d 100755
--- a/tools/uplang
+++ b/tools/uplang
@@ -1,136 +1,7 @@
1#!/usr/bin/perl 1#!/usr/bin/perl
2 2
3if(!$ARGV[0]) { 3print <<MOO
4 print <<MOO 4The tool formerly known as 'uplang' is no longer used. We now use
5Usage: uplang <english file> <translated file> 5genlang2 with the -u option to get updated language files.
6MOO 6MOO
7; 7;
8 exit;
9}
10
11my %ids, @ids;
12open(ENG, "<$ARGV[0]");
13while(<ENG>) {
14 if($_ =~ /^ *\#/) {
15 # comment
16 next;
17 }
18 $_ =~ s/\r//g;
19 if($_ =~ /^ *([a-z]+): *(.*)/) {
20 ($var, $value) = ($1, $2);
21 # print "$var => $value\n";
22
23 $set{$var} = $value;
24
25 if($var eq "new") {
26 # the last one for a single phrase
27 $all{$set{'id'}, 'desc'}=$set{'desc'};
28 $all{$set{'id'}, 'eng'}=$set{'eng'};
29 $all{$set{'id'}, 'voice'}=$set{'voice'};
30
31 $ids{$set{'id'}}=1;
32 push @ids, $set{'id'};
33 undef %set;
34 }
35 }
36}
37close(ENG);
38
39undef %set;
40my $cblock = 1;
41open(NEW, "<$ARGV[1]");
42while(<NEW>) {
43 $_ =~ s/\r//g;
44
45 if($_ =~ /^ *\#/) {
46 # comment
47 if($_ !~ /^ *\#\#\#/) {
48 # no special ### comment -> keep it
49 if(!$cblock) {
50 print "\n";
51 $cblock = 1;
52 }
53 print $_;
54 }
55 next;
56 }
57 $cblock = 0;
58
59 if($_ =~ /^ *([a-z]+): *(.*)/) {
60 ($var, $value) = ($1, $2);
61
62 $set{$var} = $value;
63
64 if($var eq "new") {
65 # the last one for a single phrase
66
67 if(!$ids{$set{'id'}}) {
68 print "\n### ".$set{'id'}." was not found in the english file!\n";
69 next;
70 }
71
72 print "\nid: ".$set{'id'}."\n";
73
74 if($set{'desc'} ne $all{$set{'id'}, 'desc'}) {
75 print "### Description changed! Previous description was:\n",
76 "### \"".$set{'desc'}."\"\n";
77 print "desc: ".$all{$set{'id'}, 'desc'}."\n";
78 }
79 else {
80 print "desc: ".$set{'desc'}."\n";
81 }
82
83 if($set{'eng'} ne $all{$set{'id'}, 'eng'}) {
84 print "### English phrase was changed! Previous translation was made on:\n",
85 "### ".$set{'eng'}."\n";
86 print "eng: ".$all{$set{'id'}, 'eng'}."\n";
87 }
88 else {
89 print "eng: ".$set{'eng'}."\n";
90 }
91
92 if($set{'id'} =~ /^VOICE_/) { # voice only, compare desc:
93 if($set{'desc'} ne $all{$set{'id'}, 'desc'}) {
94 print "### Voice only: description changed! Voice set to english. Previous voice was:\n",
95 "### ".$set{'voice'}."\n";
96 $set{'voice'} = $all{$set{'id'}, 'voice'};
97 }
98 }
99 else { # standard entry, compare eng:
100 if($set{'eng'} ne $all{$set{'id'}, 'eng'}
101 #only if either original or translated voice: is non-empty
102 and ($set{'voice'} !~ /^(\"\")? *$/
103 or $all{$set{'id'}, 'voice'} !~ /^(\"\")? *$/)) {
104 print "### English phrase was changed! Voice set to english. Previous voice was:\n",
105 "### ".$set{'voice'}."\n";
106 $set{'voice'} = $all{$set{'id'}, 'voice'};
107 }
108 }
109 if($set{'voice'} =~ /^(\"\")? *$/
110 and $all{$set{'id'}, 'voice'} !~ /^(\"\")? *$/) {
111 print "### Voice not found in previous translation. Set to english.\n";
112 $set{'voice'} = $all{$set{'id'}, 'voice'};
113 }
114 print "voice: ".$set{'voice'}."\n";
115
116 print "new: ".$set{'new'}."\n";
117
118 $ids{$set{'id'}}=0;
119 undef %set;
120 }
121 }
122}
123close(NEW);
124
125# output new phrases not already translated , in english.lang order
126for(@ids) {
127 if($ids{$_}) {
128 my $id=$_;
129 print "\nid: $_\n";
130 print "desc: ".$all{$id, 'desc'}."\n";
131 print "eng: ".$all{$id, 'eng'}."\n";
132 print "### Not previously translated\n";
133 print "voice: ".$all{$id, 'voice'}."\n";
134 print "new: \n";
135 }
136}