summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rwxr-xr-xtools/genlang2365
1 files changed, 296 insertions, 69 deletions
diff --git a/tools/genlang2 b/tools/genlang2
index 400b915482..7d363d4cf7 100755
--- a/tools/genlang2
+++ b/tools/genlang2
@@ -10,27 +10,84 @@
# Copyright (C) 2006 by Daniel Stenberg
#
+# binary version for the binary lang file
+my $langversion = 2; # 2 is the latest one used in the v1 format
+
+# A note for future users and readers: The original v1 language system allowed
+# the build to create and use a different language than english built-in. We
+# removed that feature from our build-system, but the build scripts still had
+# the ability. But, starting now, this ability is no longer provided since I
+# figured it was boring and unnecessary to write support for now since we
+# don't use it anymore.
+
if(!$ARGV[0]) {
print <<MOO
-Usage: genlang2 [-p=<prefix>][-t=<target>][-v] <language file>
+Usage: genlang2 [options] <langv2 file>
+
+ -p=<prefix>
+ Make the tool create a [prefix].c and [prefix].h file.
-<prefix>.h and <prefix>.c will be created in the current directory. <prefix>
-is "lang" by default.
+ -b=<outfile>
+ Make the tool create a binary language (.lng) file namaed [outfile].
+ The use of this option requires that you also use -e.
-Use -v for verbose (debug) output.
+ -u
+ Update language file. Given the translated file and the most recent english
+ file, you\'ll get an updated version sent to stdout. Suitable action to do
+ when you intend to update a translation.
+ -e=<english lang file>
+ Point out the english (original source) file, to use that as master
+ language template. Used in combination with -b or -u.
+
+ -t=<target>
+ Specify which target you want the translations/phrases for. Required when
+ -b or -p is used.
+
+ -v
+ Enables verbose (debug) output.
MOO
;
exit;
}
+# How update works:
+#
+# 1) scan the english file, keep the whole <phrase> for each phrase.
+# 2) read the translated file, for each end of phrase, compare:
+# A) all source strings, if there's any change there should be a comment about
+# it output
+# B) the desc fields
+#
+# 3) output the phrase with the comments from above
+# 4) check which phrases that the translated version didn't have, and spit out
+# the english version of those
+#
+
my $prefix = $p;
-if(!$prefix) {
- $prefix="lang";
+my $binary = $b;
+my $update = $u;
+
+my $english = $e;
+
+my $check = $binary?1:0 + $prefix?1:0 + $update?1:0;
+
+if($check > 1) {
+ print "Please use only one of -p, -u and -b\n";
+ exit;
+}
+if(!$check) {
+ print "Please use at least one of -p, -u and -b\n";
+ exit;
+}
+if(($binary || $update) && !$english) {
+ print "Please use -e too when you use -b or -u\n";
+ exit;
}
+
my $target = $t;
-if(!$target) {
- print "Please specify a target!\n";
+if(!$target && !$update) {
+ print "Please specify a target (with -t)!\n";
exit;
}
my $verbose=$v;
@@ -45,40 +102,6 @@ my %voice; # id string to voice phrase hash
my $input = $ARGV[0];
-open(HFILE, ">$prefix.h");
-open(CFILE, ">$prefix.c");
-
-print HFILE <<MOO
-/* This file was automatically generated using genlang2 */
-/*
- * The str() macro/functions is how to access strings that might be
- * translated. Use it like str(MACRO) and expect a string to be
- * returned!
- */
-#define str(x) language_strings[x]
-
-/* this is the array for holding the string pointers.
- It will be initialized at runtime. */
-extern unsigned char *language_strings[];
-/* this contains the concatenation of all strings, separated by \\0 chars */
-extern const unsigned char language_builtin[];
-
-/* The enum below contains all available strings */
-enum {
-MOO
- ;
-
-print CFILE <<MOO
-/* This file was automaticly generated using genlang2, the strings come
- from "$input" */
-
-#include "$prefix.h"
-
-unsigned char *language_strings[LANG_LAST_INDEX_IN_ARRAY];
-const unsigned char language_builtin[] =
-MOO
- ;
-
my @m;
my $m="blank";
@@ -140,29 +163,140 @@ sub voice {
parsetarget("voice", \$voice, @_);
}
-my $idcount; # counter for lang ID numbers
+my %english;
+if($english) {
+ # For the cases where the english file needs to be scanned/read, we do
+ # it before we read the translated file. For -b it isn't necessary, but for
+ # -u it is convenient.
+
+ my $idnum=0; # start with a true number
+ my %idmap;
+ open(ENG, "<$english") || die "can't open $english";
+ my @phrase;
+ my $id;
+ while(<ENG>) {
+
+ # get rid of DOS newlines
+ $_ =~ s/\r//g;
+
+ if($_ =~ /^ *\<phrase\>/) {
+ # this is the start of a phrase
+ }
+ elsif($_ =~ /^ *\<\/phrase\>/) {
+ # this is the end of a phrase, add it to the english hash
+ $english{$id}=join("", @phrase);
+ undef @phrase;
+ }
+ elsif($_ ne "\n") {
+ # gather everything related to this phrase
+ push @phrase, $_;
+ }
+
+ if($_ =~ /^ *id: ([^ \t\n]+)/i) {
+ $id=$1;
+ # Skip voice-only entries
+ if($id =~ /^VOICE_/) {
+ next;
+ }
+
+ # Assign an ID number to this entry
+ $idmap{$id}=$idnum;
+ $idnum++;
+ }
+ }
+ close(ENG);
+}
+
+# a function that compares the english phrase with the translated one.
+# compare source strings and desc
+sub compare {
+ my ($engref, $locref)=@_;
+ my ($edesc, $ldesc);
+ my ($esource, $lsource);
+ my $mode=0;
+
+ for my $l (@$engref) {
+ if($l =~ /^ *desc: (.*)/) {
+ $edesc=$1;
+ }
+ elsif($l =~ / *\<source\>/i) {
+ $mode=1;
+ }
+ elsif($mode) {
+ if($l =~ / *\<\/source\>/i) {
+ last;
+ }
+ $esource .= "$l\n";
+ }
+ }
+
+ $mode = 0;
+ for my $l (@$locref) {
+ if($l =~ /^ *desc: (.*)/) {
+ $ldesc=$1;
+ }
+ elsif($l =~ / *\<source\>/i) {
+ $mode=1;
+ }
+ elsif($mode) {
+ if($l =~ / *\<\/source\>/i) {
+ last;
+ }
+ $lsource .= "$l";
+ }
+ }
+
+ if($edesc ne $ldesc) {
+ print "### The 'desc' field differs from the english!\n";
+ }
+ if($esource ne $lsource) {
+ print "### The <source> section differs from the english!\n";
+ }
+}
+
+my $idcount; # counter for lang ID numbers
my $voiceid=0x8000; # counter for voice-only ID numbers
+#
+# Now start the scanning of the selected language string
+#
+
open(LANG, "<$input");
+my @phrase;
while(<LANG>) {
+
$line++;
- if($_ =~ / *\#/) {
- # comment
- next;
- }
+
# get rid of DOS newlines
$_ =~ s/\r//g;
+ if($_ =~ /^( *\#|[ \t\n\r]*\z)/) {
+ # comment or empty line
+ next;
+ }
+
+ my $ll = $_;
+
# print "M: $m\n";
+ push @phrase, $ll;
+
+ # this is an XML-lookalike tag
if(/ *<([^>]*)>/) {
my $part = $1;
#print "P: $part\n";
+
if($part =~ /^\//) {
+ # this was a closing tag
+
if($part eq "/phrase") {
+ # closing the phrase
+
my $idstr = $phrase{'id'};
my $idnum;
-
+
+ # Use the ID name to figure out which id number range we should
+ # use for this phrase. Voice-only strings are separated.
if($idstr =~ /^VOICE/) {
$idnum = $voiceid++;
}
@@ -188,13 +322,39 @@ while(<LANG>) {
undef $dest;
undef $voice;
undef %phrase;
- }
+
+ if($update) {
+ my $e = $english{$idstr};
+
+ if($e) {
+ # compare original english with this!
+ my @eng = split("\n", $english{$idstr});
+
+ compare(\@eng, \@phrase);
+ }
+ else {
+ print "### This phrase is not used, remove it!\n";
+ }
+ }
+ undef @phrase;
+
+ } # end of </phrase>
+
# starts with a slash, this _ends_ this section
- $m = pop @m; # get back old value
+ $m = pop @m; # get back old value, the previous level's tag
+ if($update) {
+ print "$ll";
+ }
next;
- }
+ } # end of tag close
+
+ # This is an opening (sub) tag
+
push @m, $m; # store old value
$m = $1;
+ if($update) {
+ print "$ll";
+ }
next;
}
@@ -202,11 +362,51 @@ while(<LANG>) {
my ($name, $val)=($1, $2);
&$m($_, $name, $val);
}
-
+ if($update) {
+ print "$ll";
+ }
+
}
close(LANG);
-# Output the ID names for the enum in the header file
+if($prefix) {
+ # We create a .c and .h file
+
+ open(HFILE, ">$prefix.h");
+ open(CFILE, ">$prefix.c");
+
+ print HFILE <<MOO
+/* This file was automatically generated using genlang2 */
+/*
+ * The str() macro/functions is how to access strings that might be
+ * translated. Use it like str(MACRO) and expect a string to be
+ * returned!
+ */
+#define str(x) language_strings[x]
+
+/* this is the array for holding the string pointers.
+ It will be initialized at runtime. */
+extern unsigned char *language_strings[];
+/* this contains the concatenation of all strings, separated by \\0 chars */
+extern const unsigned char language_builtin[];
+
+/* The enum below contains all available strings */
+enum {
+MOO
+ ;
+
+print CFILE <<MOO
+/* This file was automaticly generated using genlang2, the strings come
+ from "$input" */
+
+#include "$prefix.h"
+
+unsigned char *language_strings[LANG_LAST_INDEX_IN_ARRAY];
+const unsigned char language_builtin[] =
+MOO
+ ;
+
+ # Output the ID names for the enum in the header file
my $i;
for $i (1 .. $idcount) {
my $name=$idnum[$i - 1]; # get the ID name
@@ -235,23 +435,18 @@ for $i (0x8000 .. ($voiceid-1)) {
printf HFILE (" %s,\n", $name);
}
-
# Output end of enum
-print HFILE <<MOO
-};
-/* end of generated enum list */
-MOO
- ;
+ print HFILE "\n};\n/* end of generated enum list */\n";
-# Output the target phrases for the source file
-for $i (1 .. $idcount) {
- my $name=$idnum[$i - 1]; # get the ID
- my $dest = $dest{$name}; # get the destination phrase
-
- $dest =~ s:\"$:\\0\":; # insert a \0 before the second quote
+ # Output the target phrases for the source file
+ for $i (1 .. $idcount) {
+ my $name=$idnum[$i - 1]; # get the ID
+ my $dest = $dest{$name}; # get the destination phrase
+
+ $dest =~ s:\"$:\\0\":; # insert a \0 before the second quote
- printf CFILE (" %s\n", $dest);
-}
+ printf CFILE (" %s\n", $dest);
+ }
# Output end of string chunk
print CFILE <<MOO
@@ -260,8 +455,40 @@ print CFILE <<MOO
MOO
;
-close(HFILE);
-close(CFILE);
+ close(HFILE);
+ close(CFILE);
+} # end of the c/h file generation
+elsif($binary) {
+ # Creation of a binary lang file was requested
+
+ # We must first scan the english file to get the correct order of the id
+ # numbers used there, as that is what sets the id order for all language
+ # files. The english file is scanned before the translated file was
+ # scanned.
+
+ open(OUTF, ">$binary") or die "Can't create $binary";
+ binmode OUTF;
+ printf OUTF ("\x1a%c", $langversion); # magic lang file header
+
+ # loop over the target phrases
+ for $i (1 .. $idcount) {
+ my $name=$idnum[$i - 1]; # get the ID
+ my $dest = $dest{$name}; # get the destination phrase
+
+ if($dest) {
+ $dest =~ s/^\"(.*)\"\s*$/$1/g; # cut off quotes
+
+ # Now, make sure we get the number from the english sort order:
+ $idnum = $idmap{$name};
+
+ printf OUTF ("%c%c%s\x00", ($idnum>>8), ($idnum&0xff), $dest);
+ if($debug) {
+ printf("%02x => %s\n", $idnum, $value);
+ }
+ }
+ }
+}
+
if($verbose) {
printf("%d ID strings scanned\n", $idcount);