aboutsummaryrefslogtreecommitdiff
path: root/tools/po2c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/po2c')
-rwxr-xr-xtools/po2c277
1 files changed, 277 insertions, 0 deletions
diff --git a/tools/po2c b/tools/po2c
new file mode 100755
index 0000000000..10e15338c7
--- /dev/null
+++ b/tools/po2c
@@ -0,0 +1,277 @@
+#!/usr/bin/perl
+
+#
+# po2c - Converts .po files to C code
+#
+# Copyright (C) 2004 Angel Ortega <angel@triptico.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# http://www.triptico.com
+#
+
+$VERSION = "1.0.2-scummvm";
+
+if(scalar(@ARGV) == 0)
+{
+ print "Usage: po2c {po file[s]}\n";
+ exit 1;
+}
+
+%msgs = ();
+%msgids = ();
+
+# stage 1: loading
+
+# arguments are .po files
+foreach my $f (@ARGV)
+{
+ my ($lang);
+ my ($langDesc);
+
+ next unless(($lang) = ($f =~ /([^\/]+)\.po$/));
+
+ if(open F, $f)
+ {
+ my ($msgid, $val, %a);
+
+ while(<F>)
+ {
+ chomp;
+
+ # ignore blank lines or comments
+ next if /^$/ or /^#/;
+
+ if(/^msgid\s+\"(.*)\"\s*$/)
+ {
+ # store previous msgid
+ if(defined($msgid))
+ {
+ $a{$msgid} = $val;
+ $msgids{$msgid} ++;
+ }
+
+ # start of msgid
+ $val = $1;
+ }
+ elsif(/^msgstr\s+\"(.*)\"\s*$/)
+ {
+ # store previous msgid
+ $msgid = $val;
+
+ # start of msgstr
+ $val = $1;
+ }
+ elsif(/^\"(.*)\"\s*$/)
+ {
+ # add to current value
+ $val .= $1;
+ }
+ }
+
+ # store previous msgid
+ if(defined($msgid))
+ {
+ $a{$msgid} = $val;
+ $msgids{$msgid} ++;
+ }
+
+ close F;
+
+ # add to the global message pool
+ $msgs{$lang} = \%a;
+ }
+}
+
+# stage 2: convert the data
+
+# stores all sorted msgids into @msgids
+@msgids = sort(keys(%msgids));
+
+# travels again, storing indexes into %msgids
+for(my $n = 0;$n < scalar(@msgids);$n++)
+{
+ $msgids{$msgids[$n]} = $n;
+}
+
+# stage 3: dump as C++ code
+
+print "// generated by po2c $VERSION - Do not modify\n\n";
+
+# dump first the msgid array
+print "static const char * const _messageIds[] = {\n";
+
+for(my $n = 0;$n < scalar(@msgids);$n++)
+{
+ print "\t/* $n */ \"" . $msgids[$n] . "\",\n";
+}
+
+print "\tNULL\n};\n\n";
+
+# dump the lang structure
+print "struct PoMessageEntry {\n";
+print "\tint msgid;\n";
+print "\tconst char *msgstr;\n";
+print "};\n\n";
+
+# dump now each language
+
+foreach my $l (keys(%msgs))
+{
+ print "static const PoMessageEntry _translation_${l}\[\] = {\n";
+
+ # get the translation table for the language $l
+ my ($m) = $msgs{$l};
+
+# while (my ($msgstr, $msgid) = each (%$m))
+ foreach my $msgid (sort(keys(%$m)))
+ {
+ my ($msgstr) = "";
+
+ # make it 7-bit safe
+ foreach $c (split(//, $m->{$msgid})) {
+ if (ord($c) > 0x7f) {
+ $msgstr .= sprintf("\\%o", ord($c));
+ } else {
+ $msgstr .= $c;
+ }
+ }
+
+ print "\t{ " . $msgids{$msgid} . ", \"" . $msgstr . "\" },\n"
+ if $msgstr;
+ }
+
+ print "\t{ -1, NULL }\n};\n\n";
+}
+
+# finally, dump the languages
+
+print "struct PoLangEntry {\n";
+print "\tconst char *lang;\n";
+print "\tconst char *charset;\n";
+print "\tconst char *langname;\n";
+print "\tconst PoMessageEntry *msgs;\n";
+print "};\n\n";
+print "const PoLangEntry _translations[] = {\n";
+
+foreach my $l (keys(%msgs))
+{
+ # charset
+ $header = $msgs{$l}->{""};
+ $header =~ /charset=([^\\]+)/;
+ $charset = $1;
+ # user readable language name
+ $lang = "NULL";
+ $header = $msgs{$l}->{""};
+ $header =~ /Language:[\s]*([^\\]*)/;
+ unless ($1 eq "")
+ {
+ $lang = "\"" . $1 . "\"";
+ }
+ print "\t{ \"" . $l . "\", \"" . $charset . "\", " . $lang . ", _translation_${l} },\n";
+}
+
+print "\t{ NULL, NULL, NULL, NULL }\n};\n\n";
+
+print "// code\n";
+print << 'EOF';
+
+static const PoMessageEntry *_currentTranslation = NULL;
+static int _currentTranslationMessageEntryCount = 0;
+static const char *_currentTranslationCharset = NULL;
+
+void po2c_setlang(const char *lang) {
+ _currentTranslation = NULL;
+ _currentTranslationMessageEntryCount = 0;
+ _currentTranslationCharset = NULL;
+
+ // if lang is NULL or "", deactivate it
+ if (lang == NULL || *lang == '\0')
+ return;
+
+ // searches for a valid language array
+ for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) {
+ if (strcmp(lang, _translations[i].lang) == 0) {
+ _currentTranslation = _translations[i].msgs;
+ _currentTranslationCharset = _translations[i].charset;
+ }
+ }
+
+ // try partial searches
+ for (int i = 0; _currentTranslation == NULL && _translations[i].lang != NULL; ++i) {
+ if (strncmp(lang, _translations[i].lang, 2) == 0) {
+ _currentTranslation = _translations[i].msgs;
+ _currentTranslationCharset = _translations[i].charset;
+ }
+ }
+
+ // if found, count entries
+ if (_currentTranslation != NULL) {
+ for (const PoMessageEntry *m = _currentTranslation; m->msgid != -1; ++m)
+ ++_currentTranslationMessageEntryCount;
+ }
+}
+
+const char *po2c_gettext(const char *msgid) {
+ // if no language is set or msgid is empty, return msgid as is
+ if (_currentTranslation == NULL || *msgid == '\0')
+ return msgid;
+
+ // binary-search for the msgid
+ int leftIndex = 0;
+ int rightIndex = _currentTranslationMessageEntryCount - 1;
+
+ while (rightIndex >= leftIndex) {
+ const int midIndex = (leftIndex + rightIndex) / 2;
+ const PoMessageEntry * const m = &_currentTranslation[midIndex];
+
+ const int compareResult = strcmp(msgid, _messageIds[m->msgid]);
+
+ if (compareResult == 0)
+ return m->msgstr;
+ else if (compareResult < 0)
+ rightIndex = midIndex - 1;
+ else
+ leftIndex = midIndex + 1;
+ }
+
+ return msgid;
+}
+
+const char *po2c_getcharset(void) {
+ if (_currentTranslationCharset)
+ return _currentTranslationCharset;
+ else
+ return "ASCII";
+}
+
+int po2c_getnumlangs(void) {
+ return ARRAYSIZE(_translations) - 1;
+}
+
+const char *po2c_getlang(const int num) {
+ assert(num < ARRAYSIZE(_translations));
+ return _translations[num].lang;
+}
+
+const char *po2c_getlangname(const int num) {
+ assert(num < ARRAYSIZE(_translations));
+ if (_translations[num].langname != NULL)
+ return _translations[num].langname;
+ return _translations[num].lang;
+}
+EOF
+
+exit 0;