#!/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"; 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"); }