# HG changeset patch # User Shinji KONO # Date 1353902453 -32400 # Node ID 66a8cd81a04b70fab1bac10fbdbc6d130b9847a4 # Parent 5818128d5630fce849581f252e958135f9f4be14 fix diff -r 5818128d5630 -r 66a8cd81a04b Paper/alice.ind --- a/Paper/alice.ind Sat Nov 24 16:22:52 2012 +0900 +++ b/Paper/alice.ind Mon Nov 26 13:00:53 2012 +0900 @@ -15,96 +15,90 @@ ---歴史的経緯 - -本研究室では、並列タスク管理フレームワークCeriumの管理を行なっているが、その設計と実装を行うにあたり、並列プログラミングと分散プログラミング -は本質的には同じことを行なっていることが分かった。特にヘテロジーニアスマルチコアであり、ローカルストアをそれぞれのコアが持っているというCell の特異な環境は、分散プログラミング環境と告示している。それらを踏まえて、Ceriumのタスク管理手法を分散に応用できないかと考えた。 - - -Ceriumに置いても、タスクとそれの入出力データの取り扱いは難しい課題である。データを操作するAPIを考えて、タスクを自然に記述し、効率良く実行する方法を考えてきた。そこで考えられた手法が、データをDataSegment、タスクをCodeSegmentという単位に分割して記述する方法である。 - --分散ネットフレームワークAlice -\label{sec:ITEM} -Aliceは本研究室の卒業生である赤嶺一樹氏が、本研究室で開発を行なっている並列タスク管理フレームワーク Cerium と先行研究である Federated Linda の開発を通して得られた知見を生かされている。 -Federated Linda の設計はシングルスレッドで行われている。しかし、近年ではマルチコアのマシンが主流となっている。将来的にはメニーコアのマシンが主流になってくると考えられるそのような背景を踏まえてAliceはマルチスレッド向けに設計されている。 +Alice\cite{}は、本研究室で開発を行なっている並列タスク管理フレームワーク である。 +Cell 用の Open CL に似た Task 管理フレームワークCerium\cite{} と、Linda\cite{} を相互接続した分散フレームワークである Federated Linda\cite{} の開発を通して得られた知見を生かされている。 -AliceはData SegmentとCode Segmentという単位でデータと処理を細かく分割し、それぞれの依存関係を記述して分散プログラムを作成する。また、他のマシンとの接続トポロジーの構成の機能も有しているのでユーザーはトポロジー構成後の処理を記述するだけでよい。 -また、AliceはJavaで実装されている。 +Cerium では、Taskを小さく分割して並列実行し、データ転送はパイプライン実行により隠される。Taskには依存関係があり、その記述は煩雑になるが、実際にはデータの依存関係がそのまま Task の依存関係になることが多い。繰り返し使われるデータ構造の管理が重要であり、実行時にわかるデータ構造間の依存関係が Task を複雑にしている。 ---Data Segment +Federated Linda では、Linda サーバ内部に Meta Engine と呼ばれる Linda のタプル(データ構造)をやり取りする部分を作成した\cite{}。Meta Engine では、タプルのやり取りによって起動する call back を使うが、call back による記述が分散してしまい、可読性を落としてしまう。また、複数のタプルの待ち合わせが重要だが、その待ち合わせは single threaded な Meta Engine 内部の状態に依存する。 + +これらが示しているのは、並列分散実行はコードの並列実行だけでなく、データの単位が重要だということである。そこで、 AliceはData SegmentとCode Segmentという単位でデータと処理を細かく分割し、それぞれの依存関係を記述して分散プログラムを作成する。Code Segment は Continuation based C の実行単位\cite{} であり、その双対が Data Segment である。 -AliceではData Semgnetをデータベースとして利用している。KeyValueStoreで実装されており、キーごとにリストを持っている。Data Segment APIを用いることで、リストにデータを追加、削除を適宜行うことができる。 +Data Segment は Code Segment と分離されたデータ構造であり、オブジェクトではない。オブジェクト指向プログラミングが状態を複雑に持ち、並列実行や分散実行に向かないことは徐々に理解されてきている。一方で、状態自体は有限状態遷移機械(Finite State Machine/FSM) で記述するのが自然である。Code Segment は状態遷移記述そのものであり、その状態遷移は Data Segment の到着によってトリガーされる。 - ---Data Segment Manager +カプセル化されたデータをプロセスがやり取りするのは、DFD(Data Flow Diagram)の古典的な手法であり、それ自体は新しくはない。むしろ、メインフレーム上でのソフトウェア開発に良く使われてきた手法である。Alice では、それを再実装する。 -大量のData Segmentを管理するのがData Segment Managerである。 -Data Segment Managerは文字列のキーでData Segmentを整理する。また、各キーごとにキュー構造を持っている。それらをData Segment APIを用いて操作する。 -データの読み出し("peek" または "take")時に、希望のデータがなかった場合、ブロッキングを行う機能を持つ。 -しかし、ブロッキングといってもそこで同期するわけではない。 -非同期でデータを通信する。 -そのため、データの読み出し時には他の API とは違い、レスポンスが発生する。 +Alice は Code Segment と Data Segment を Java と Message Pack で実装したフレームワークである。トポロジーマネージャーを持ち、Bldae 上での +分散プログラムの実験を容易に行うことができる。また、SEDA Architecture \cite{} を採用しており、マルチコア上でのスループットの向上を期待している。 + +本論文では、Code Segment と Data Segment の Alice のAPIと、その設計方針を示し、それによって実装された水槽プログラムを示す。また、これまでの Federated +Linda との性能評価も行う。 + +% また、他のマシンとの接続トポロジーの構成の機能も有しているのでユーザーはトポロジー構成後の処理を記述するだけでよい。また、AliceはJavaで実装されている。 --Data Segment API +Data Segment は数値や文字列などのデータを構造体的に保持するが、Data Segment の相互参照が問題になる。 +AliceではData Semgnetをデータベースとして扱い、Data Segment は必ずキーを持つ。つまり、Data Segment を Key Value Store として考えることができる。 +通常のデータベースでは隠れているが、Key 毎のキューがあり、Key 毎に順に実行される。key 毎の追加と取得は、Linda に準じた設計になっている。 + +Data Segmentを管理するのがData Segment Managerである。ノード毎に local DS manager と remote DS manager がある。local manager は、ノードに固有の +key Value Store と考えることができる。したがって Key はノード内部で unique な文字列である。 + +remote DS manager は他のノードのlocal DS manager の proxy である。Alice のトポロジーマネージャーが remote DS manager を自動的に構成する。つまり、remote DS manager は複数あって、それぞれ対応するノードが異なる。 + +Key Value Store へのアクセスはキューによって、ノード内部で逐次化される。それ以外は、すべて Java の Thread pool により並列実行される。 +Code Segment が実行される時には、Data Segment はすべて手元に揃っているので、Blocking が起きることはない。逆に、Blocking が必要な場合は、 +Code Segment を分割する必要がある。 + 以下が用意されているData Segment APIである。これらを用いてデータの送受信を行う。 \begin{itemize} \item {\ttfamily void put(String key, Value val)} \item {\ttfamily void update(String key, Value val)} -\item {\ttfamily void peek(Receiver receiver, String key,\\ int id)} -\item {\ttfamily void take(Receiver receiver, String key,\\ int id)} +\item {\ttfamily void peek(Receiver receiver, String key} +\item {\ttfamily void take(Receiver receiver, String key)} \end{itemize} ----put -"put" はデータを追加するための API である。 -"put" は受け取ったデータ val を Data Segment 内のキューに対してエンキューする。 -この時、キーごとに重複しない連番の ID を受け取った順に振る。(図 \ref{fig:put}) +{\tt put} はデータを追加するための API である。Key Value Store のキューに追加される。 +(図 \ref{fig:put}) \begin{figure}[tb] %\begin{center} \scalebox{0.6}{\includegraphics{images/put.pdf}} %\end{center} -\caption{"put"は重複しないIDを振りながらデデータを追加する} +\caption{putはデータを追加する} \label{fig:put} \end{figure} ----update - -"update" はデータを置き換えるための API である。 - -"update" はキューの先頭にあるデータをひとつだけ削除する。 -その後は "put" と同じく、 受け取ったデータ val を Data Segment 内のキューに対してエンキューする。 -この時、キーごとに重複しない連番の ID を受け取った順に振る。(図 \ref{fig:update}) +\{tt update} はデータを置き換えるための API である。キューの先頭を置き換える特急メッセージのように動作する。 +(図 \ref{fig:update}) \begin{figure}[tb] \begin{center} \scalebox{0.6}{\includegraphics{images/update.pdf}} \end{center} -\caption{"update"は先頭データを取り除き、重複しないIDを振りながらデータを追加する} +\caption{updateはキューの先頭を書き換える} \label{fig:update} \end{figure} ----peek -"peek" はデータを読み込むための API である。 - -"peek" は前回読み込んだデータの id を引数で指定する。省略した場合は、 0 が id として渡される。 -id よりも値の大きい id のデータがキューに含まれていれば、そのデータを receiver に返す。(図 \ref{fig:peek}) +{\tt peek はデータを調べる} \begin{figure}[tb] \begin{center} \scalebox{0.6}{\includegraphics{images/peek.pdf}} \end{center} -\caption{"peek"はデータをreceiverに読み込む} +\caption{peekはデータを調べる} \label{fig:peek} \end{figure} -もし id 以下のデータしか無いならば、データの更新が前回の "peek" 発行時から更新が無いものと考え、リストに格納されて保留される。 +最新のData Segment がなければ、Code Segmentの待ち合わせ(Blocking)が起きる。 (図 \ref{fig:no_peek}) \begin{figure}[tb] @@ -115,22 +109,19 @@ \label{fig:no_peek} \end{figure} -"take" や "update" によりデータの更新があれば、 "peek" が直ちに実行される。 - ----take +{\tt put} や {\tt update} によりData Segment の更新があれば、 {\tt peek} が直ちに実行される。つまり、 +Data Segment を作成した Code Segment が active queue に移される。 -"take" もデータを読み込むための API である。 -基本的な id に関する部分は "peek" と同じである。 - -"peek" との決定的な違いは、読み込まれたデータは Data Segment 内のキューから取り除かれるということである。 +{\tt take} もデータを読み込むための API である。 +読み込まれたデータは Key Value Storeのキューから取り除かれる。これは、Linda の in() に相当する。 (図 \ref{fig:take}) - +必要な待ち合わせが行われる。 \begin{figure}[tp] \begin{center} \scalebox{0.6}{\includegraphics{images/take.pdf}} \end{center} -\caption{"peek"はデータをreceiverに読み込む。希望のデータが無いときは保留する。} +\caption{take はデータを読み込む} \label{fig:take} \end{figure} @@ -161,12 +152,45 @@ --Code Segment -Code Segmentはタスクのことである。Code Segmentをユーザーが記述するときに、Code Segment 内で使用するData Segment を記述し、依存関係を作る。依存関係により、実行される順番が一意に決まる。実際に使用するData Segment はCode Segmentの入出力に相当する。それぞれ、Input Data Segment、Output Data Segmentとする。 +Code Segmentはタスクのことである。Code Segmentをユーザーが記述するときに、Code Segment 内で使用するData Segment の作成を記述する。 +Code Segment には、Input Data Segment と Output Data Segment を作る API が存在する。 + +Input Data Segment で作成された Data segment は、remote か local かと、key を指定する必要がある。Input Data Segment がすべて揃わないと +Code Segment は active にならない。 + +Ouput Data Segment で作成された Data segment にも、remote か local かと、key を指定する必要がある。Input/Ouput が Code Segment 間の +依存関係を自動的に記述することになる。 + +\begin{verbatim} +public class SendWidth extends CodeSegment { + + Receiver width = ids.create(CommandType.PEEK); + + @Override + public void run() { + int width = this.width.asInteger(); + ods.put("parent", "widths", width); + + System.out.println("send widths: " + width); + + SendWidth cs = new SendWidth(); + cs.width.setKey("local", "width", this.width.index); + } +} +\end{verbatim} + +{\tt ids,ods} により、Input/Ouput を選択して Data Segment を作成する。Output には put 時にキーを指定する。Input は setKey を使ってキーを指定する。 +もちろん、{\tt cs.width} のようにアクセスするのは Java 的には正しくない書き方であり避けるべきである。{\tt SendWidth} は Code Segment であり、 +Data Segment が揃った時に、 {\tt Runnable} のように実行される。{\tt SendWidth} 内部で setKey する方が Java 的には望ましい。 + +どの時点でキーとノードを指定するか、どのようなAPIを用意するべきかは、まだ、議論の余地がある。 --Code Segmentの実行方法 -Code Semgnetを実行するためにはStart Code Segment (ソースコード \ref{fig:StartCodeSegment})というCode Segmentを実行させる必要がある。 -Start Code SegmentはどのData Segmentにも依存しない。つまりInput Data Segmentを持たない。このCode Segmentをmainメソッド内でnewし、executeメソッドを呼ぶことで実行を開始させることができる。(ソースコード \ref{fig:TestLocalAlice}) +Alice には、 +Start Code Segment (ソースコード \ref{fig:StartCodeSegment})というC の main に相当するような最初に実行される Code Segment がある。 +Start Code SegmentはどのData Segmentにも依存しない。つまりInput Data Segmentを持たない。 +このCode Segmentをmainメソッド内でnewし、executeメソッドを呼ぶことで実行を開始させることができる。(ソースコード \ref{fig:TestLocalAlice}) \begin{table}[tb] @@ -185,24 +209,20 @@ \lstinputlisting[label=CodeSegment, caption=CodeSegmentの例]{source/TestCodeSegment.java} \end{table} ----InputDataSegmentManager - -InputDataSegmentManagerはCode Segmentのidsというフィールドを用いてアクセスする。 +InputDataSegmentManagerはCode Segmentの\tt ids}というフィールドを用いてアクセスする。 \begin{itemize} \item {\ttfamily Receiver create(CommandType type)} \end{itemize} -createでコマンドが実行された際に取得されるData Segmentが格納される受け皿を作る。引数にはCommandTypeが取られ、指定できるCommandTypeはPEEKまたはTAKEである。 +createでコマンドが実行された際に取得されるData Segmentが格納される受け皿を作る。引数にはCommandTypeが取られ、指定できるCommandTypeは{\tt PEEK}または{\tt TAKE}である。 \begin{itemize} -\item {\ttfamily void setKey(String managerKey, String key, int id)} +\item {\ttfamily void setKey(String managerKey, String key)} \end{itemize} setKeyメソッドにより、どこのData Segmentのあるkeyに対してpeekまたはtakeコマンドを実行させるかを指定することができる。 コマンドの結果がレスポンスとして届き次第Code Segmentは実行される。 ----OutputDataSegmentManager - -OutputDataSegmentManagerはCode Segmentのodsというフィールドを用いてアクセスする。 -OutPutDataSegmentManagerは"put"または"update"を実行することができる。 +OutputDataSegmentManagerはCode Segmentの{\tt ods}というフィールドを用いてアクセスする。 +OutPutDataSegmentManagerは{\tt put}または{\tt update}を実行することができる。 \begin{itemize} \item {\ttfamily void put(String managerKey, String key, \\ Value val)} \item {\ttfamily void update(String managerKey, String key, Value val)} @@ -210,12 +230,18 @@ --Topology Manager -TopologyManagerはAlice同士の接続トポロジーを管理する。TopologyManager関連の通信処理はCode Segmentで実装してある。 +Alice は複数のノードで構成され、相互に接続される。通信するノードは、URLなどにより直接指定するのではなく、 +TopologyManagerによって管理される。 + +TopologyManager関連の通信処理はCode Segmentで実装してある。 TopologyManagerはトポロジーファイルを読み込み、参加を表明したクライアント(以下、Topology Node)に接続するべきクライアントのIPアドレスやポート番号、接続名を送り、トポロジーファイルに記述された通りにトポロジーを作成する。 +Code Segment 内部で remote DS manager にアクセスする場合は、Topology Manager によって指定されたノード内部だけで有効なlabel(文字列)を使う。これにより、 +特定のURLが Code Segment 内部に記述されることを防いでいる。 + ---Topology Managerの設定ファイル -Topology Managerはトポロジーファイルを読み込むが、トポロジーファイル自体はDOT Languageという言語で記述される。 +Topology Managerはトポロジーファイルを読み込むが、トポロジーファイル自体はDOT Language\cite{}という言語で記述される。 DOT Languageとはプレーンテキストを用いて、データ構造としてのグラフを表現するための、データ記述言語の一種である。このDOT Languageのグラフを利用して、クライアント間の接続を表現する。DOT Languageファイルはdotコマンドを用いて、グラフの画像ファイルを出力することができるので、記述したトポロジーが正しいことを可視化して確認することができる。 クライアント間の接続にはlabelを用いて名前が割り振られており、この接続名を用いてユーザーはData Segment Managerにアクセスすることができる。 diff -r 5818128d5630 -r 66a8cd81a04b Paper/o2tex --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Paper/o2tex Mon Nov 26 13:00:53 2012 +0900 @@ -0,0 +1,661 @@ +#!/usr/bin/perl +use strict; +use warnings; + + +unlink "title.tex"; +unlink "abstract.tex"; +unlink "cover.tex"; +# for msdos +system("rm -f 0*.tex 1*.tex 2.tex 3.tex 4.tex 5.tex 6.tex 7.tex 8.tex 9.tex"); + +my $alt0 = "fig000"; + +my $paper = $ARGV[0]; + +my $fh; + +open($fh,">title.tex"); select($fh); +print <abstract.tex"); select($fh); +print <00.tex"); select($fh); +print <jsss00.tex"); select($fh); +print <ohp00.tex"); select($fh); +print <trcover.tex"); select($fh); +print <) { + chop; # strip record separator + if( $verbatim && (!/^\s/) && (!/^$/) && $pre) { + print $fh "\\end{verbatim}\n}\n"; + $pre = 0; + } + if (/^-*input: (.*)/) { + open(my $fdbase,"nkf -w $1 |"); + push(@depend,$1); +# print STDOUT "$1 "; + &o2tex($fdbase); + next line; + } + if (/^-title:/) { + $file = 'title.tex'; + $title = substr($_, 8, length($_) - 7); + &Pick('>>', $file) && + (printf $fh "\\title{{\\bf %s}}\n", $title); + &Pick('>>', $ohp) && + (printf $fh "\\title{{\\bf %s}}\n", $title); + next line; + } + if (/^--*date:/) { + my $tmp; + for ($tmp = 1; substr($_, $tmp, 1) eq '-'; $tmp++) { + ; + } + $tmp += 5; + $day = substr($_, $tmp, length($_) - $tmp + 1); + next line; + } + if (/^--*number:/) { + my $tmp; + for ($tmp = 1; substr($_, $tmp, 1) eq '-'; $tmp++) { + ; + } + $tmp += 7; + $number = substr($_, $tmp, length($_) - $tmp + 1); + next line; + } + if (/^--*note:/) { + &trcover(); + $note = 2; + $file = 'trcover.tex'; + &Pick('>>', $file) && + (printf $fh "\\clearpage\n"); + (printf $fh "\\vspace*{\\fill}\n"); + (printf $fh "\\begin{quote}\n"); + next line; + } + if (/^--*author:/) { + my $tmp; + $file = 'title.tex'; + for ($tmp = 1; substr($_, $tmp, 1) eq '-'; $tmp++) { + ; + } + $tmp += 7; + $author = substr($_, $tmp, length($_) - $tmp + 1); + &Pick('>>', $file) && + (printf $fh "%%\\pagenumbering{roman}\n"); + (printf $fh "\\author{%s \\\\[5mm]\n", $author); + (printf $fh "e-mail:kono\@ie.u-ryukyu.ac.jp\\\\\n"); + (printf $fh "Information Engineering, University of the Ryukyus\\\\\n"); + (printf $fh "Nishihara-cyo 1, Okinawa, 903-01, Japan}\n"); + if ($day) { + (printf $fh "\\date{%s}\n", $day); + } + else { + (printf $fh "%% \\date{}\n"); + } + $file = sprintf('%d', $section) . '.tex'; + + &Pick('>>', $ohp) && + (printf $fh "\\author{%s \\\\[5mm]\n", $author); + (printf $fh ".Information Engineering, University of the Ryukyus\n"); + (print $fh "%% \\today"); + (print $fh "\\maketitlepage"); + next line; + } + if (/^--*author-e:/) { + $file = 'title-e.tex'; + next line; + } + if (/^--*abstract-e:/) { + $file = 'abstract-e.tex'; + $abstract = 1; + &Pick('>>', $file); # && (printf $fh "\\begin{quotation}\n"); + next line; + } + if (/^--*abstract:/) { + $file = 'abstract.tex'; + $abstract = 1; + &Pick('>>', $file); # && (printf $fh "\\begin{quotation}\n"); + (print $fh "\\mbox{}"); + next line; + } + if (/^--*begin-comment:/) { + $backup = $file; + $file = '/dev/null'; + next line; + } + if (/^--*end-comment:/) { + $file = $backup; + next line; + } + if (/^-/) { + if ($abstract == 1) { + &Pick('>>', $file); # && (printf $fh "\\end{quotation}\n"); + + $abstract = 0; + } + if ($note) { + if ($note == 2) { + &Pick('>>', $cover) && + (printf $fh "\\end{quote}\n"); + } + else { + &trcover(); + } + $note = 0; + } + for ($depth = 1; substr($_, $depth, 1) eq '-'; $depth++) { + ; + } + if ($depth == 2) { + $file = sprintf('%d', $section) . '.tex'; + &Pick('>>', $file) && + (print $fh "\\section{", substr($_, $depth, + length($_) - $depth + 1) . '}'); + &Pick('>>', $ohp) && + (print $fh "\\begin{bwslide}"); + (print $fh "\\ctitle{", substr($_, $depth, + length($_) - $depth + 1) . '}'); + (print $fh "\\end{bwslide}\n\n"); + &Pick('>>', '0.tex') && + (printf $fh "\\input{%d}\t%% %s\n", $section, substr($_, + $depth, length($_) - $depth + 1)); + $section++; +# print STDOUT "$section "; + } + elsif ($depth == 3) { + $file = sprintf('%d', $section - 1) . '.tex'; + &Pick('>>', $file) && + (print $fh "\\subsection{", substr($_, $depth, + length($_) - $depth + 1) . '}'); + &Pick('>>', $ohp) && + (print $fh "\\begin{bwslide}"); + (print $fh "\\ctitle{", substr($_, $depth, + length($_) - $depth + 1) . '}'); + (print $fh "\\end{bwslide}\n\n"); + } + elsif ($depth == 4) { + $file = sprintf('%d', $section - 1) . '.tex'; + &Pick('>>', $file) && + (print $fh "\\subsubsection{", substr($_, $depth, + length($_) - $depth + 1) . '}'); + &Pick('>>', $ohp) && + (print $fh "\\begin{bwslide}"); + (print $fh "\\ctitle{", substr($_, $depth, + length($_) - $depth + 1) . '}'); + (print $fh "\\end{bwslide}\n\n"); + } + else { + $file = sprintf('%d', $section - 1) . '.tex'; + &Pick('>>', $file) && + (printf $fh "%s\\\\\n", substr($_, $depth, + length($_) - $depth + 1)); + } + next line; + } elsif (m!^
\s*"]*)"[^>]*alt="([^>"]*)"[^>]*>\s*
!i) { + my $fig = $1; my $alt = $2; + my $caption; + if ($fig) { + $fig =~ s/\.gif|\.jpg/.eps/; + } + if (! $alt) { + $alt = $alt0++; + $caption = ""; + } else { + $caption = "\\caption{$alt}\n"; + } + &Pick('>>', $file); + # center environment disturbes caption counter and label reference + my $line = <<"EOF"; +\\begin{figure}[htb] +\\begin{center} +\\includegraphics[width=6cm]{${fig}} +${caption}\\end{center} +\\label{${alt}} +\\end{figure} +EOF + # print $fh "(fig.\\ref{$alt})\n"; + print $fh $line; + &Pick('>>', $ohp) && + (print $fh "\\centerline{$line}\n"); + if(! /^\s*%/) { + $fig =~ s/[{}]//g; + push(@depend,$fig); + push(@ohpdepend,$fig); + } + next line; + } elsif (m!^
\s*"]*)"[^>]*>\s*
!i) { + my $fig = $1; my $alt = $2; + my $caption; + if ($fig) { + $fig =~ s/\.gif|\.jpg/.eps/; + } + if (! $alt) { + $alt = $alt0++; + $caption = ""; + } else { + $caption = "\\caption{$alt}\n"; + } + &Pick('>>', $file); + my $line = <<"EOF"; +\\begin{figure}[htb] +\\begin{center} +\\includegraphics[width=6cm]{${fig}} +${caption}\\end{center} +\\label{${alt}} +\\end{figure} +EOF + # print $fh "(fig.\\ref{$alt})\n"; + print $fh $line; + &Pick('>>', $ohp) && + (print $fh "\\centerline{$line}\n"); + if(! /^\s*%/) { + $fig =~ s/[{}]//g; + push(@depend,$fig); + push(@ohpdepend,$fig); + } + next line; + } elsif (/\\epsfile\{.*file=([^{},]+)/ || + /\\includegraphics\{([^{},]+)\}/ || + /\\input (.*)/ || /\\include (.*)/) { + my $fig = $1; + &Pick('>>', $file) && + (print $fh $_); + &Pick('>>', $ohp) && + (print $fh "\\centerline{$_}\n"); + if(! /^\s*%/) { + $fig =~ s/[{}]//g; + push(@depend,$fig); + push(@ohpdepend,$fig); + } + next line; + } elsif ($verbatim && /^\s/) { + if(! $pre) { + print $fh "{\\small\n\\begin{verbatim}"; + $pre = 1; + } + print $fh $_; + } elsif (!/^-/) { + &Pick('>>', $file) && + (print $fh $_); + } + if (/\\cite\{/) { $cite = ""; } + } +} + +foreach my $arg (@ARGV) { + open(my $fdbase,"nkf -w $arg |") || die("$arg cannot open"); + &o2tex($fdbase); +} + +&Pick('>>', $zero); + select($fh); + printf $fh "%s\\bibliographystyle{jplain} %% for bibliography\n", $cite; + print <>', $zero) && + (printf $fh "\\end{document}\n"); + close($fh); +&Pick('>>', $ohp) && + (printf $fh "\n\\end{document}\n"); + close($fh); + +sub trcover { + if ($title) { + &Pick('>>', $cover) && + (printf $fh "{\\LARGE\\bf %s}\\\\[+5mm]\n", $title); + } + if ($author) { + &Pick('>>', $cover) && + (printf $fh "{\\large %s}\\\\[+5mm]\n", $author); + } + if ($number) { + &Pick('>>', $cover) && + (printf $fh "{\\large %s}\\\\[+4mm]\n", $number); + } + if ($day) { + &Pick('>>', $cover) && + (printf $fh "{\\large %s}\n", $day); + } + &Pick('>>', $cover) && + (print $fh "\\end{center}}\\\\"); + (print $fh "\\vfill"); + (printf $fh "{\\Large Information Engineering, University of the Ryukyus\\\\\n"); + (print $fh "Nishihara-cho 1, Okinawa, 903-01 JAPAN}\\\\[+2cm]"); + (print $fh "{\\small Copyright \\copyright\\ \\number\\year\\"); + (print $fh 'University of the Ryukyus'); + (print $fh "}\\\\[+1cm]"); + (print $fh "\\end{center}"); + (print $fh "\\end{titlepage}\n\n"); + return; +} + +sub Pick { + my ($mode,$name,$pipe) = @_; + if (! defined $opened{$name}) { + open(my $mfh,$mode.$name.$pipe); + $fh = $mfh; + } + 1; +} + +&Pick('>>', $cover) && +print $fh "\\end{document}\n"; +close $fh; + +if (! -f "Makefile") { +open($fh,">Makefile"); select($fh); +print "PAPER = ". $paper . "\n"; +print <\$@ +.c.tex: + tgrind -F -lC \$< >\$@ +.tokio.tex: + tgrind -F -ltokio \$< >\$@ +.fig.tex: + f2tpic \$< >\$@ +.xfig.tex: + f2tpic \$< >\$@ +.fig.ps: + f2ps1 \$< >\$@ +.x.tex: + x2tpic \$< + -rm -f \$*.pic +.tex.dvi: + jlatex \$< +.dvi.print: + \$(DVI2PS) \$(R) \$< | lpr -P\$(PRINTER) +# lpr \$(PRINTER) -d \$< +.dvi.lw: + \$(DVI2PS) \$(R) \$< | lpr -P\$(PRINTER) +.dvi.next: + dviNeXT \$< +.dvi.xdvi: + (exec xdvi \$< & ) +.dvi.ps: + -\$(DVI2PS) \$(R) \$< > \$*.ps +.ps.gs: + gs \$*.ps + +all: + -rm -f \$(MAIN).dvi + make \$(MAIN).dvi + +print: \$(MAIN).print +lw: \$(MAIN).lw +next: \$(MAIN).next +gs: \$(MAIN).gs +\$(MAIN).gs : \$(MAIN).ps +\$(MAIN).ps : \$(MAIN).dvi +\$(OHP).gs : \$(OHP).ps +\$(OHP).ps : \$(OHP).dvi +xdvi: \$(MAIN).xdvi +dvips: \$(MAIN).dvi + dvips \$(MAIN).dvi -o \$(MAIN).ps + +\$(MAIN).dvi: 1.tex + \$(LATEX) \$(MAIN) + +jsss.dvi: jsss.tex 1.tex + \$(LATEX) jsss.tex + +wc: + \$(SED) -e '/\\\\special{/d' \$(PAPER) | delatex | wc +uu: + tar cBf - \$(MAIN).[tab]* [0-9]*.tex \$(DEPENDENCY) \\ + title.tex abstract.tex ohp.tex \\ + Makefile | gzip | uuencode \$(PAPER).tar.gz > uu + + +bbl: \$(MAIN).bbl + +\$(MAIN).bbl: ref.bib 1.tex # \$(MAIN).aux + -\$(BIBTEX) \$(MAIN) + +\$(MAIN).aux: \$(MAIN).tex 1.tex + \$(LATEX) \$(MAIN) + +1.tex: \$(PAPER) \$(DEPENDENCY) + -o2tex \$(PAPER) + +# OHP with slitex +\$(OHP): \$(OHP).dvi +\$(OHP).dvi : \$(OHP).tex \$(DEPENDOHP) + \$(SLITEX) \$(OHP) + +ohpprint: \$(OHP).dvi + lpr -c \$(OHP).dvi +ohplw: \$(OHP).dvi + \$(DVI2PS) \$(R) -o landscape \$(OHP).dvi | lpr -P\$(PRINTER) +ohpnext: \$(OHP).dvi + \$(DVI2PS) -h -i /usr/lib/tex/ps/tex-j.next -o landscape \$(OHP).dvi |\\ + lpr -Pcb +ohpgs: \$(OHP).gs + +cover: \$(COVER).dvi +\$(COVER): \$(COVER).dvi +\$(COVER).dvi : \$(PAPER) +coverprint: \$(COVER).print +coverlw: \$(COVER).lw +covernext: \$(COVER).next +covergs: \$(COVER).gs + +clean: + -rm -f \$(MAIN).ps *.dvi *.log *.blg \\ + *~ \\#* ?.tex *.toc *.lof *.lot xfig/*.tex + +tgrindfig.tex: + ln -s "\$\$HOME"/paper/tgrindfig.tex . +# for MSDOS +tgrindfi.tex: + ln -s "\$\$HOME"/paper/tgrindfig.tex tgrindfi.tex +ref.bib: + ln -s "\$\$HOME"/paper/ref.bib . + +RogueRogue +close $fh; +} +if ( ! -f "main.tex") { + rename('00.tex','main.tex'); +} +if ( ! -f "jsss.tex") { + rename('jsss00.tex','jsss.tex'); +} +if ( ! -f "ohp.tex") { + rename('ohp00.tex','ohp.tex'); +} +# make depend > /dev/null + +rename("Makefile","Makefile.old"); +open(MAKE, "Makefile"); +select($fh); +print "DEPENDENCY = @depend\n"; +print "DEPENDOHP = @ohpdepend\n"; +while() { + next if(/^DEPEND/); + chop; print; +} +close($fh); + +# end