1#!/usr/bin/perl -w 2# 3# <LANG>.po to faqomatic's Language_<LANG>.pm converter. 4# 5# Usage: 6# po2pm [-h] [{inputfile|-} [outfile]] 7# 8# Copyright (c) Andrew W. Nosenko <awn@bcs.zp.ua>, 2001 9# 10# This program is free software; you can redistribute it and/or modify 11# it under the terms of either: 12# 13# a) the GNU General Public License as published by the Free 14# Software Foundation; either version 2, or (at your option) any 15# later version, or 16# b) the "Artistic License" which comes with Perl Kit. 17# 18# This program is distributed in the hope that it will be useful, 19# but WITHOUT ANY WARRANTY; without even the implied warranty of 20# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either 21# the GNU General Public License or the Artistic License for more details. 22# 23 24use strict; 25use IO; 26use File::Basename; 27use Getopt::Long; 28 29my $NAME = 'po2pm'; 30my $PROG; 31 32sub Help() 33{ 34 printf("<LANG>.po to faqomatic's Language_<LANG>.pm converter.\n"); 35 printf("Copyright (c) Andrew W. Nosenko <awn\@bcs.zp.ua>, 2001\n"); 36 printf("Usage:\n"); 37 printf(" %s [-h] [{inputfile|-} [outfile]]\n", $PROG); 38 printf("Where:\n"); 39 printf(" inputfile .po file for building Language_<LANG>.pm from which.\n"); 40 printf(" If omited or have magic name \`-' (minus sign)\n"); 41 printf(" then STDIN will be used\n"); 42 printf(" outfile Name of taget .pm file. If omited then STDOUT\n"); 43 printf(" will be used.\n"); 44 printf("Options:\n"); 45 printf(" --help | -h this Help\n"); 46} 47 48sub UseHelp() 49{ 50 printf(STDERR "%s: try \`%s --help' for help\n", $PROG, $PROG); 51} 52 53sub perlify( $ ) 54{ 55 my $s = $_[0]; 56 if (defined($s)) 57 { 58 $s =~ s/\\\\/\\/g; 59 } 60 return $s; 61} 62 63sub po_to_pm( $$$$ ) 64{ 65 my ($inhandle, $infilename, $outhandle, $outfilename) = @_; 66 my $state = 'initial'; # 'initial', 'msgid', 'msgstr' 67 68 my $line; 69 my $lineno = 0; 70 my $fuzzy = 0; 71 my ($msgid, $msgstr); 72 73 while(defined($line = $inhandle->getline())) 74 { 75 chomp($line); 76 ++$lineno; 77 78 if ($line =~ m/^\s*$/ || $line =~ m/^#/) 79 { 80 if ($state ne 'initial' && $state ne 'msgstr') 81 { 82 die("$infilename:$lineno: syntax error: current state \`$state', expected state \`initial' or \`msgstr'"); 83 } 84 85 if (defined($msgid) && defined($msgstr)) 86 { 87 $outhandle->printf(" \"%s\"\n", $msgid) 88 or die("error output into \`$outfilename': $!"); 89 if ($fuzzy) 90 { 91 $outhandle->printf("# fuzzy # => \"%s\",\n", 92 $msgstr) 93 or die("error output into \`$outfilename': $!"); 94 $outhandle->printf(" => \"\",\n") 95 or die("error output into \`$outfilename': $!"); 96 } 97 else 98 { 99 $outhandle->printf(" => \"%s\",\n", $msgstr) 100 or die("error output into \`$outfilename': $!"); 101 } 102 undef($msgid); 103 undef($msgstr); 104 } 105 $state = 'initial'; 106 107 if ($line =~ m/^#,/ && $line =~ m/, fuzzy\b/) 108 { 109 $fuzzy = 1; 110 } 111 else 112 { 113 $fuzzy = 0; 114 } 115 $outhandle->printf("%s\n", $line) 116 or die("error output into \`$outfilename': $!"); 117 next; 118 } 119 120 if ($line =~ m/^msgid "/) 121 { 122 if ($state ne 'initial') 123 { 124 die("$infilename:$lineno: unexpected msgid"); 125 } 126 $line =~ m/^msgid "(.*)"$/ 127 or die("$infilename:$lineno: syntax error"); 128 $msgid = perlify($1); 129 $state = 'msgid'; 130 next; 131 } 132 133 if ($line =~ m/^msgstr "/) 134 { 135 if ($state ne 'msgid') 136 { 137 die("$infilename:$lineno: unexpected msgstr"); 138 } 139 $line =~ m/^msgstr "(.*)"$/ 140 or die("$infilename:$lineno: syntax error"); 141 $msgstr = perlify($1); 142 $state = 'msgstr'; 143 next; 144 } 145 146 if ($line =~ m/^"/) 147 { 148 if ($state ne 'msgid' && $state ne 'msgstr') 149 { 150 die("$infilename:$lineno: unexpected string"); 151 } 152 $line =~ m/^"(.*)"$/ 153 or die("$infilename:$lineno: syntax error"); 154 if ($state eq 'msgid') 155 { 156 $msgid .= perlify($1); 157 } 158 elsif ($state eq 'msgstr') 159 { 160 $msgstr .= perlify($1); 161 } 162 next; 163 } 164 165 die("assert! state=$state, infilename=$infilename, lineno=$lineno, line=\`$line'"); 166 } 167 168 if ($inhandle->error()) 169 { 170 die("error reading from \`$infilename': $!"); 171 } 172 173 if ($state ne 'initial' && $state ne 'msgstr') 174 { 175 die("$infilename:$lineno: syntax error at EOF: current state \`$state', expected state \`initial' or \`msgstr'"); 176 } 177 178 if (defined($msgid) && defined($msgstr)) 179 { 180 $outhandle->printf(" \"%s\"\n", $msgid) 181 or die("error output into \`$outfilename': $!"); 182 if ($fuzzy) 183 { 184 $outhandle->printf("# fuzzy # => \"%s\",\n", 185 $msgstr) 186 or die("error output into \`$outfilename': $!"); 187 $outhandle->printf(" => \"\",\n") 188 or die("error output into \`$outfilename': $!"); 189 } 190 else 191 { 192 $outhandle->printf(" => \"%s\",\n", $msgstr) 193 or die("error output into \`$outfilename': $!"); 194 } 195 undef($msgid); 196 undef($msgstr); 197 } 198 199 return 1; 200} 201 202sub output_pm_header( $$$ ) 203{ 204 my ($infilename, $outhandle, $outfilename) = @_; 205 my ($inbasename, $outbasename); 206 207 $inbasename = basename($infilename); 208 $outbasename = basename($outfilename); 209 210 $outhandle->printf('#-------------------------------------------------------------------- 211# %s 212# Generated automatically from %s by %s 213#-------------------------------------------------------------------- 214 215sub translations { 216 my $tx = shift; 217 218 my %%data = ( 219 220', $outbasename, $inbasename, $NAME) 221 or die("error output into \`$outfilename' : $!"); 222 return 1; 223} 224 225sub output_pm_footer( $$ ) 226{ 227 my ($outhandle, $outfilename) = @_; 228 229 $outhandle->print(' 230 231); # end of %data hash 232 233 my $msgid; 234 235 foreach $msgid (keys(%data)) 236 { 237 $tx->{$msgid} = $data{$msgid}; 238 } 239 return 1; 240} 241') 242 or die("error output into \`$outfilename' : $!"); 243 return 1; 244} 245 246sub main() 247{ 248 my $success; 249 my $opt_help; 250 my ($infilename, $inhandle, $in_close_on_exit); 251 my ($outfilename, $outhandle, $out_close_on_exit); 252 253 $PROG = basename($0); 254 Getopt::Long::Configure('bundling', 'no_ignore_case', 'no_auto_abbrev'); 255 $success = GetOptions('help|h' => \$opt_help); 256 257 if (!$success) 258 { 259 UseHelp(); 260 exit(1); 261 } 262 if ($opt_help) 263 { 264 Help(); 265 exit(0); 266 } 267 268 if (@ARGV > 2) 269 { 270 printf(STDERR 271 "%s: too many command line arguments\n", 272 $PROG); 273 UseHelp(); 274 exit(1); 275 } 276 277 # 278 # Open input/output handles 279 # 280 $infilename = $ARGV[0]; 281 if ($infilename && $infilename ne '-') 282 { 283 $inhandle = IO::File->new($infilename, 'r') 284 or die("error opening \`$infilename' for reading: $!\n"); 285 $in_close_on_exit = 1; 286 } 287 else 288 { 289 $infilename = '(stdin)'; 290 $inhandle = IO::Handle->new_from_fd(fileno(STDIN), 'r') 291 or die("error reopening STDIN for reading: $!\n"); 292 $in_close_on_exit = 0; 293 } 294 295 $outfilename = $ARGV[1]; 296 if ($outfilename) 297 { 298 $outhandle = IO::File->new($outfilename, 'w') 299 or die("error opening \`$outfilename' for writing: $!\n"); 300 $out_close_on_exit = 1; 301 } 302 else 303 { 304 $outfilename = '(stdout)'; 305 $outhandle = IO::Handle->new_from_fd(fileno(STDOUT), 'w') 306 or die("error reopening STDOUT for writing: $!\n"); 307 $out_close_on_exit = 0; 308 } 309 310 # 311 # Main work 312 # 313 314 $success = output_pm_header($infilename, $outhandle, $outfilename) 315 && po_to_pm($inhandle, $infilename, $outhandle, $outfilename) 316 && output_pm_footer($outhandle, $outfilename); 317 318 # 319 # Finish 320 # 321 if ($in_close_on_exit) 322 { 323 $inhandle->close() 324 or die("error closing input file \`$infilename': $!\n"); 325 } 326 if ($out_close_on_exit) 327 { 328 $outhandle->close() 329 or die("error closing output file \`$outfilename': $!\n"); 330 } 331 332 return $success ? 0 : 1; 333} 334 335my $rc = main(); 336exit($rc); 337