#!/usr/bin/perl
#
# dcnote-mkindex:
#
## hogehoge.des って何?
# hogehoge.des, desc.txt を読んで index.html ファイルを作成する.
#
# ●Usage : dcnote-mkindex [-o index.htm] [ -dc desc.txt ]
# [ -topdir $TOPDIR] [-tdirname $TOPDIRNAME]
# [ -prjdir $PTOPDIR] [-pdirname $PTOPDIRNAME]
# [ -wrkdir $WORKDIR]
# target_dir
#
# $TOPDIR プロジェクトトップディレクトリ
# /GFD_Dennou_Club/ftp/arch/riron
# $TOPDIRNAME プロジェクトの名前
# 地球流体理論マニュアル
# $PTOPDIR 個別資源格納用トップディレクトリ
# /GFD_Dennou_Club/ftp/arch/riron/renzoku/gaisetu
# $PTOPDIRNAME 個別資源の名前
# 連続体概説
# $WORKDIR 個別資源格コンパイル作業ディレクトリ
# /GFD_Dennou_Club/ftp/arch/riron/renzoku/gaisetu/src
# target_dir 公開資源インストール先
#
# ●作成されるファイル
#
# hogehoge/ : 作業ディレクトリ
# index.htm : html ファイル
#
# 履歴 1998/08/31 豊田英司; botindex.pl - update bottom directory lising HTML
# 1999/06/27 小高正嗣; dcnote-mkindex へ
# 1999/07/21 小高正嗣
# 1999/12/20 杉山耕一朗
#
# スカラー変数の定義
$OUTPUT= "index.htm"; # 生成ファイル名
$GROUP = "地球流体電脳倶楽部" ; #
$TOPDIRINDEX = "index.htm" ; # リンクファイル名
$DESCFILE = "desc.txt" ; # 情報記述 desc ファイル名
# 日本語文字コード変換
&initkanzi;
## オプションの判定.
## 引数 @ARGV のそれぞれ要素に対して while ループを回す.
## 先頭に "-" が付いてなければ次のループへ移る.
## 先頭に "-" が付いていれば $_ に @ARGV の最初の要素を入れる.
## "-o" 等, それぞれのオプションが現れたら, その次の要素をスカラーにいれる.
## next 関数によって次のループに移る.
# オプションの判定
while (@ARGV) {
$_ = shift;
last unless (/^-/);
if (/^-o/) { $OUTPUT = shift; next; }
if (/^-dc/) { $DESCFILE = shift; next; }
if (/^-topdir/) {$TOPDIR = shift; next; }
if (/^-tdirname/) { $TOPDIRNAME = shift; next; }
if (/^-prjdir/) {$PTOPDIR = shift; next; }
if (/^-pdirname/) { $PTOPDIRNAME = shift; next; }
if (/^-wrkdir/) { $WORKDIR = shift; next; }
die "unknown option $_";
}
## もしも引数として target_dir が指定されていないならば,
## カレントディレクトリとする.
$TARGETDIR = $_ ? $_ : ".";
# 上位のリンク先ディレクトリ名を与える.
#
## $lvdiff_ct には TOPDIR と WORKDIR のパスに含まれるディレクトリ数の差.
## $lvdiff_pt には TOPDIR と PTOPDIR のパスに含まれるディレクトリ数の差.
## $titlename には PTOPDIR のパスに含まれるが TOPDIR のパスには含まれない
## ディレクトリ名. (例では $titlename[0]=gaisetu, $titlename[1]=renzoku.
## ディレクトリ名の順番が逆になっていることに注意)
($lvdiff_ct, $lvdiff_pt, @titlename) = &ReadTitle;
# $DESCFILE から必要情報を読み込む.
#
## %setumei は desc.txt の各行の第 1 フィールドを key とし, 第 2
## フィールドを値とするような連想配列.
%setumei = &ReadDesc($DESCFILE);
# 目次用 html ファイルの作成.
#
## target_dir をオープンする. もし target_dir がなければ死んでおしまい.
## target_dir の下に存在するファイルの中で「数字 3 つ + 末尾がgif」という
## ファイル名を @file に入れる.
opendir(DIR, $TARGETDIR) || die "cannot open $TARGETDIR";
@files = sort grep(/^\d\d\d.gif$/, readdir(DIR));
closedir(DIR);
## サブルーチン open_w を呼び出す. $OUTPUT が存在しなければ死ぬ.
## $OUTPUT には index.htm が入っている.
## open_w で euc を sjis に変換する.
## STDERR に出力. (画面に表示される)
## select でデフォルトのファイルハンドルを $OUTPUT にする.
&open_w($OUTPUT) || die "$OUTPUT: cannot open";
print STDERR "output written to $OUTPUT\n";
select($OUTPUT);
# ファイルのヘッダ, 中身, フッダをファイルに書き出す.
#
## サブルーチン HtmlHeader を呼び出す.
## @file のそれぞれの要素に対して, サブルーチン ListEntry を呼び出す.
## @file には ***.gif という値が入っている.
## サブルーチン HtmlTailer を呼び出す.
&HtmlHeader;
foreach (@files) {
&ListEntry($_);
}
&HtmlTailer;
close($OUTPUT);
## $OUTPUT を target_dir に移動させる.
system ("mv $OUTPUT $TARGETDIR");
exit 0;
#
# --- subroutines
#
# 目次用 html ファイルヘッダー部の作成
#
## @titlename の要素は(ディレクトリ名)は順番が逆になっているので
## reverse 関数でひっくり返す
## (例では $titlename[0]=gaisetu, $titlename[1]=renzoku)
## .= で $title に "" を結合し, それを $title に入れる. → @title の生成
## ヘッダを標準出力(現在は index.htm ファイル)に書き出す.
### この title は意味がない. PTOPDIR の名前を入れた方がいいのでは.
### $GROUP は意味ない
sub HtmlHeader {
# for $level (reverse(0 .. $#titlename)) {
# $title .= "/$titlename[$level]" ;
# }
print "\n";
# print "
$title\n";
print "$PTOPDIRNAME\n";
print "\n";
print "$GROUP\n" if ($GROUP);
print "
\n";
## ('../' x $sigenlv) は ../ を $sigenlv 回書けということ.
for $level (reverse(0 .. $#titlename)) {
$sigenlv = $level + 2 ;
print "/$titlename[$level]\n";
}
print "
\n";
print "$TOPDIRNAME\n";
print "
$setumei{'subject:'}
\n";
print "$setumei{'from:'} $setumei{'date:'}\n" if $setumei{'date:'};
print "
$setumei{'desc:'}\n" if $setumei{'desc:'};
print "
$setumei{'note:'}\n" if $setumei{'note:'};
print "
\n";
# Pdf: フィールドがある場合
if (defined $setumei{'pdf:'}) {
# Pdf: フィールドの値が空白でない場合
unless ( $setumei{'pdf:'} =~ m/\s+/ ) {
print "
\n";
print "全体の pdf ファイル\n";
print "
\n";
}
}
print "
\n";
print "各ページの gif ファイル\n";
print "
\n";
print "\n";
}
# 目次用 html ファイル各ページ記述部の作成.
#
## @file には ***.gif というファイル名が入っている.
## $link に ***.htm というファイル名を入れる.
## $bangou に数字(***)を入れる.
## $listitem を定義し, 標準出力に書き出す.
## もしも $setumei{$bangou} が定義されていたら(ページの説明が存在するならば),
## リターンを $listitem で置換する(?)
## $listname には改行記号(\n)が含まれているのでそれを除く
### e オプションは後ろにくっつけるという意味合いらしい(要確認)
sub ListEntry {
local($link) = @_;
local($bangou) = $link;
$link =~ s/\.gif$/.htm/;
$bangou =~ s/\.gif//;
local($listitem) = "- $bangou\n";
print $listitem;
local($line);
if (defined $setumei{$bangou}) {
$line = $setumei{$bangou};
$line =~ s/\r/$listitem/ge;
print "$line\n";
}
}
# 目次用 html ファイル最下端部の作成.
#
## サブルーチン FmtTime を呼び出す.
## $ACKLINK と $ACKMSG があれば書く. 昔は「このページは hogehoge によって
## 作られました」と書くところ.
sub HtmlTailer {
print "
\n";
print "
\n";
print "last update: ". &FmtTime .";\n";
print "$ACKMSG\n" if $ACKMSG;
print "\n";
print "\n";
}
# スクリプト起動時刻を与える.
#
## なぜか $mon は +1 しないとならない.
sub FmtTime {
local($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst)
= localtime time;
sprintf "%4d/%02d/%02d %02d:%02d:%02d",
$year + 1900, $mon + 1, $mday, $hour, $min, $sec;
}
# 情報記述ファイル $DESCFILE から, 各フィールド名とその記述を読み出す.
#
## $elmfile = $DESCFILE
sub ReadDesc {
## 変数の準備
local($emlfile) = @_;
local(%hdrs, %newhdrs);
# $emlfile がない場合
## 戻り値 0 でメインループに返る.
if (!-f $emlfile) {
# not suitable for gfdsemi project
# warn "$0: $emlfile not exist\n";
return ();
}
## 漢字コードを EUC に変換
## 開けなければ返り値 0 でメインループに戻る.
&open_r($emlfile) || return ();
# 各フィールドを引数としその記述部を値に持つ連想配列を作る.
## サブルーチン ReadHeaders を呼ぶ(引数は desc ファイルを与える).
## %hdrs は desc ファイルの第 1 フィールドを key にし,
## 第 2 フィールドをその値とするような連想配列
%hdrs = &ReadHeaders($emlfile);
# gif ページ番号の記述が適切でない場合の処理.
## 連想配列の key を取り出し, 数字で始まるものに関しては 10 進数の
## 3 桁の数字に直す. その key をもとにして連想配列を定義し直す.
for (keys %hdrs) {
($newkey = $_) =~ s/\.gif//;
if ($newkey =~ /^[0-9]/) {
$newkey = sprintf("%03d", $newkey);
$newhdrs{$newkey} = $hdrs{$_};
} else {
$newhdrs{$_} = $hdrs{$_};
}
}
## 戻り値
%newhdrs;
}
# 既に開かれたファイルハンドル $emlfile から
# RFC 822 形式のヘッダを読み取りフィールド名をキーとする連想配列
# として返す.
# 値に \r または \t が存在すれば SPACE に置換される.
# 同じ名前のヘッダが複数存在する場合は値は \r で区切られる.
sub ReadHeaders {
local($emlfile) = @_;
local($name, $val, %headers);
$name = ""; undef %headers;
## desc ファイル 1 行 1 行について while ループを回す.
while (<$emlfile>) {
chop; # 改行消去
s/\r$//; # 行末が CRLF なら CR 除去(Win)
last if /^$/; # 空行はヘッダの終り
if (!/^\s/) { # 継続行でない場合
# ヘッダの開始行として適当かチェック
## カッコで括った部分が $1 に, それ以外が $2 に代入される.
if (!/^([-A-Za-z0-9]*:)\s*(.*)/) {
warn "broken header \"$_\" in $emlfile\n";
next;
}
# さっきのパターンマッチでフィールド名と値が取り出せる
($name = $1) =~ tr/A-Z/a-z/; # 大文字小文字の同一視
($val = $2) =~ s/[\t\r]/ /g; # 値に \t \r がないことを保証
if (defined $headers{$name}) {
# 前に同じ名前のヘッダがあれば \r をはさんで連結
$headers{$name} .= "\r$val";
} else {
# 前に同じ名前のヘッダがなければただ代入
$headers{$name} = $val;
}
} else { # 継続行の場合
# 値に \r \t がないことを保証
s/[\t\r]/ /g;
# 行頭の空白はただ一つにまとめる (単に審美的理由)
s/^ */ /;
# 直前の $name のヘッダに追加
$headers{$name} .= $_;
}
}
## 戻り値の指定
%headers;
}
# 上位のリンク先ディレクトリ名を与える.
# 作業ディレクトリと $TOPDIR の段数を比較し,
# 作業ディレクトリより 1 段上位のディレクトリから $TOPDIR までの
# ディレクトリ名を返す.
#
## TOPDIR と PTOPDIR と WORKDIR に共通項が存在することを前提にしている.
## 変数の用意
sub ReadTitle {
local($cwdir, $tpdir, $pjdir);
local($cwd_num, $tpd_num, $pjdir_num);
local(@cwd_item, @tpd_item, @pjdir_item, @updirname) ;
local($diff, $and);
## TOPDIR と PTOPDIR と WORKDIR のそれぞれのパスから最初と最後の / を削る.
# $cwdir=`echo pwd | /bin/bash`; # 現在の作業ディレクトリ名を出力
# $cwdir=`pwd`; # 現在の作業ディレクトリ名を出力
# $cwdir=~ s/^\/// ; # 先頭の / を削除
# $cwdir=~ s/\/$// ; # 末尾の / を削除
# print $cwdir;
$cwdir="$WORKDIR"; # 現在の作業ディレクトリ名を出力
$cwdir=~ s/^\/// ; # 先頭の / を削除
$cwdir=~ s/\/$// ; # 末尾の / を削除
$tpdir="$TOPDIR"; # 参照する最上段のディレクトリ名を出力.
$tpdir=~ s/^\/// ; # 先頭の / を削除.
$tpdir=~ s/\/$// ; # 末尾の / を削除.
$pjdir="$PTOPDIR"; # 参照する最下段のディレクトリ名を出力.
$pjdir=~ s/^\/// ; # 先頭の / を削除.
$pjdir=~ s/\/$// ; # 末尾の / を削除.
## TOPDIR と PTOPDIR と WORKDIR のそれぞれを / で分割し,
## ディレクトリ名の入った配列を作る
## 例では
## @cwd_item = GFD_Dennou_Club, ftp, arch, riron, renzoku, gaisetu, src
## @tpr_item = GFD_Dennou_Club, ftp, arch, riron
## @prj_item = GFD_Dennou_Club, ftp, arch, riron, renzoku, gaisetu
@cwd_item = split ("/", "$cwdir" ); # / で文字列を分割, 配列へ代入.
@tpd_item = split ("/", "$tpdir" ) ; # / で文字列を分割, 配列へ代入.
@prj_item = split ("/", "$pjdir" ) ; # / で文字列を分割, 配列へ代入.
$diff_ct = @cwd_item - @tpd_item ; # @cwd_item @tpd_item の配列要素数の差.
$diff_pt = @prj_item - @tpd_item ; # @prj_item @tpd_item の配列要素数の差.
# $TOPDIR と PWD の共通部分がマッチするか調べる.
## "$#" は配列の最後の要素の番号を答える(例では $#tpd_item = 3)
for ($and = $#tpd_item; $and >= 0; $and--) {
die "Warning; $TOPDIR is different"
unless ($cwd_item[$and] eq $tpd_item[$and]);
}
# $PTOPDIR と PWD の共通部分がマッチするか調べる.
## 例では $#prj_item = 5
for ($and = $#prj_item; $and >= 0; $and--) {
die "Warning; $PTOPDIR is different from $WORKDIR "
unless ($cwd_item[$and] eq $prj_item[$and]);
}
# $TOPDIR と $PTOPDIR の共通部分がマッチするか調べる.
for ($and = $#tpd_item; $and >= 0; $and--) {
die "Warning; $PTOPDIR is different from $TOPDIR"
unless ($tpd_item[$and] eq $prj_item[$and]);
}
# @prj_item の最後から 2 番目の要素から $diff 個を選ぶ.
## 例では $diff = 5 - 3 = 2.
## $updirname[1] = prj_item[3] = riron
## $updirname[0] = prj_item[4] = renzoku
for ($diff = @prj_item - @tpd_item; $diff > 0; $diff--) {
$updirname[$diff - 1] = $prj_item[@prj_item - $diff - 1];
}
## 戻り値を指定
($diff_ct, $diff_pt, @updirname) ;
}
# basename
#
### これ使っていない
sub Basename {
local($x, $suffix) = @_;
$x =~ s|/$||;
$x =~ s|^.*/||;
$x =~ s/$suffix$// if ($suffix);
$x;
}
# kanzi code convertor(日本語文字コード変換)
## Windows を想定している
sub initkanzi {
$INCONV = "nkf -e";
$OUTCONV = "nkf -E -s";
}
sub open_r {
local($file) = @_;
open($file, "$INCONV \'$file\' |");
}
sub open_w {
local($file) = @_;
# return open($file, "| $OUTCONV") if $file eq "-";
open($file, "| $OUTCONV > $file");
}