OSDN Git Service

admin/po4a/gendraft.perl: Ensure to die when failing to open files
[linuxjm/jm.git] / admin / po4a / gendraft.perl
1 #!/usr/bin/perl
2 #
3 # Copyright (c) 2021 Linux JM project
4 #         all rights reserved.
5 #
6 # Written by Michio MATSUYAMA <michio_matsuyama@yahoo.co.jp>
7 #
8 # 内容説明
9 #   引数に与えられたオリジナル英文 man ページファイル(第1引数)
10 #   と翻訳済日本語 man ページファイル(第2引数) に基づいて、
11 #   draft ファイル文面を生成し、draft ファイル(第3引数)に出力
12 #   します。
13 #
14 # 利用制約
15 #   第1引数、第2引数の roff 構造が完全に一致していないと、
16 #   本スクリプトは動作しません。これは主に po4a を使って
17 #   翻訳処理を行った直後に(翻訳途上,翻訳完成には関係なく)
18 #   後追いで draft ファイルを生成することを意図しています。
19 #
20 # 利用方法
21 #   perl gendraft.perl origmanfile jamanfile draftfile
22 #
23 #     origmanfile: オリジナル英文 man ページファイルパス。
24 #     jamanfile:   翻訳済日本語 man ページファイルパス。
25 #     draftfile:   出力する draft ファイルパス。
26 #
27 #   実行例
28 #     perl gendraft.perl orignal/man.1 ja/man.1 draft/man.1
29 #
30
31 use strict;
32 use File::Basename;
33 use File::Path;
34
35 if (@ARGV < 3) {
36   print STDERR "perl $0 <orig> <ja> <outfile>\n";
37   exit 1;
38 }
39
40 # コマンドライン引数を取得
41 my $origmanfile = shift;
42 my $jamanfile   = shift;
43 my $draftfile   = shift;
44
45 # origmanfile, jamanfile を読み込み専用で開く
46 open (my $fhorig, '<', $origmanfile) or die "Error: file not found: ".$origmanfile;
47 open (my $fhja,   '<', $jamanfile)   or die "Error: file not found: ".$jamanfile;
48
49 # do_proc_for 呼び出しを行って @origmanarray、@jamanarray をそれぞれ取得
50 my @origmanarray = &do_proc_for($fhorig);
51 my @jamanarray   = &do_proc_for($fhja);
52
53 close($fhja);
54 close($fhorig);
55
56 # @origmanarray、@jamanarray 要素数が違う場合は終了。
57 # 当該 draft ファイルの生成は諦めるが警告するだけにとどめる。
58 # (Makefile からの順次呼び出しをすべて成功させるため。)
59 my $len_orig_elements = @origmanarray;
60 my $len_ja_elements   = @jamanarray;
61 if ($len_orig_elements != $len_ja_elements) {
62   print STDERR "Warning: number of elements in both orig and ja file should be equal.\n";
63   print STDERR "Skipped to create draft file: $draftfile\n";
64   exit 0;
65 }
66
67 #for (my $cnt = 0; $cnt < $len_orig_elements; $cnt++){
68 #  my @each_orig = @{$origmanarray[$cnt]};
69 #  my @each_ja   = @{$jamanarray[$cnt]};
70 #  print "org(".$cnt."): ".@each_orig[0]."\n";
71 #  print "  ".@each_orig[1];
72 #  print "ja(".$cnt."): ".@each_ja[0]."\n";
73 #  print "  ".@each_ja[1];
74 #}
75
76 # 出力 draftfile を開く
77 open (my $fhdraft, '>', $draftfile) or die "Error: file not created: ".$draftfile;
78
79 &output_proc;
80
81 close($draftfile);
82
83 #
84 # do_proc_for
85 #   第1引数に指定される man ページファイルのファイルハンドルから
86 #   全行を読み込みながら、以下のような配列を生成します。
87 #    ((MACRO1, PARAGRAPH1), (MACRO2, PARAGRAPH2), ...)
88 #   ここで MACROn は主要な roff マクロ [TH|SH|SS|TP|LP|PP|P|IP|HP|RS|RE]
89 #   のいずれかであり、その man ページ内に見つかったものを順に表します。
90 #   またPARAGRAPHn は1つの(改行文字も含む)文字列であり、その構成は
91 #   MACROn の行から次に見つかった MACRO(n+1) の(あるいはファイル終端の)
92 #   直前の行までを連結したものです。最後にその配列を戻り値として返します。
93 #
94 sub do_proc_for {
95
96   my $macro_name = "";
97   my $macro_found = 0;
98   my $paragraph = "";
99
100   my $fh = $_[0];
101   my @array = ();
102   my @subarray;
103
104   # 第1引数に与えられたファイルハンドルの各行を順にループ
105   foreach my $currentline (<$fh>) {
106
107     # $currentline が ".\" で始まる行は無視
108     if ($currentline =~ /^\.\\\"/) {
109       next;
110     }
111
112     # $curretline が主要 roff マクロで始まるかどうか
113     if ($currentline =~ /^\.(TH|SH|SS|TP|LP|PP|P|IP|HP|RS|RE)/ || 
114         $currentline =~ /^(\s*)$/) {
115
116       # '\fR' + '空行' となる特殊ケースを処理
117       # これを行わないと、最終的な生成配列の数が不一致となるため。
118       if ($currentline =~ /^(\s*)$/) {
119         my $laststr = substr($paragraph, -4, 3);
120         if ($laststr eq "\\fR") {
121           # 前処理の最後が "\\fR" で終わっていて、次に空行がきた場合
122           # 空行を区切り扱いとせずにループ続行
123           $paragraph = $paragraph.$currentline;
124           next;
125         }
126       }
127
128       if ($macro_name ne "") {
129         # 部分配列 (MACROn, PARAGRAPHn) を出力配列 @array に追加
130         @subarray = ($macro_name, $paragraph);
131         push(@array, [@subarray]);
132       }
133
134       # 次のループに向けて $macro_name と $paragraph を初期セット
135       $macro_name = $1;
136       $paragraph  = $currentline;
137
138     } else {
139       # 主要 roff マクロで始まらない行は順次連結
140       $paragraph = $paragraph.$currentline;
141
142     }
143   }
144   # 最後に残った部分配列 (MACROn, PARAGRAPHn) を出力配列 @array に追加
145   @subarray = ($macro_name, $paragraph);
146   push(@array, [@subarray]);
147
148   # 出力配列を返す
149   return @array;
150 }
151
152 # output_proc
153 #   上の do_proc_for を適用した @origmanarray、@jamanarray が生成済
154 #   であることを前提として、またその2つの MACROn の内容およびその順は
155 #   まったく一致しているとの前提で、両配列を同時にループして(ループ
156 #   カウントは @origmanarray に基づいて)、両方の配列内の1つずつの
157 #   要素 (MACROn, PARAGRAPHn) において、@origmanarray 側の PARAGRAPHn
158 #   は文字列先頭に ".\"O " をつけて $fhdraft に出力し、続けて
159 #   @jamanarray 側の PARAGRAPHn をそのまま $fhdraft に出力します。
160 #   そのようにして draft 文面を、@origmanarray, @jamanarray 交互に
161 #   順次出力していきます。
162 #
163 #   @origmanarray と @jamanarray を同時にループした際の、それぞれの
164 #   MACROn は一致していることが前提ですが、不一致の場合、STDERR に
165 #   エラー出力します。このエラーは発生しないことを前提としますが、
166 #   念のための処理です。これが仮に起きた場合の出力結果はどうなるかは
167 #   想定していません。
168 #
169 sub output_proc {
170
171   # @origmanarray (と同時に @jamanarray) の各要素を順にループ
172   for (my $cnt = 0; $cnt < $len_orig_elements; $cnt++){
173
174     # @origmanarray と @jamanarray の各要素 (MACROn, PARAGRAPHn) を取得
175     my @each_orig = @{$origmanarray[$cnt]};
176     my @each_ja   = @{$jamanarray[$cnt]};
177
178     # @origmanarray 側と @jamanarray 側の MACROn が不一致
179     if (@each_orig[0] ne @each_ja[0]) {
180       print STDERR "Error: each element between orig and ja file should be matched.\n";
181       print STDERR "  orig: ".@each_orig[0]."/".$cnt."\n";
182       print STDERR "  ja:   ".@each_ja[0]."/".$cnt."\n";
183     }
184
185     my $first_flag = 0;
186
187     # @origmanarray 側の PARAGRAPHn の行頭に ".\O " を付与して
188     # $fhdraft へ出力します。
189     # ただし PARAGRAPHn は改行文字も含む1つの文字列であるため、
190     # あらかじめ "\n" で分割した文字配列としておき、
191     # それをループしながら各行の先頭に".\O "を付与していきます。
192     my @orig = split(/\n/, @each_orig[1]);
193     foreach my $o (@orig) {
194       if ($first_flag != 0) {
195         print $fhdraft "\n";
196         $first_flag = 1;
197       }
198       my $commented = $o;
199       $commented =~ s/^/.\\"O /;
200       print $fhdraft $commented."\n";
201     }
202
203     # @jamanarray 側の PARAGRAPHn はそのまま出力します。
204     print $fhdraft @each_ja[1];
205
206     # 次の PARAGRAPHn 出力に向けて罫線行をコメントで挿入します。
207     print $fhdraft ".\\\"O ----------------------------------------\n";
208   }
209 }