Linux Journal 4月号発売中。今月の特集はインターネット
▼▼▼ディストリビューション関連ニュース▼▼▼ ●SuSE と MandrakeSuSE、Mandrake、Linux Network Computing は今後の開発で提携することになった。SuSE と Mandrake はよく知られた Linux のディストリビュータだ。Linux Network はディスクレスの Linux ネットワークコンピューティング開発企業だ。その製品は Linbox Net Station や Linbox Net Server として知られている。Linbox と Linux ディストリビュータ2社の提携により Linbox Network アーキテクチャのオープンな開発が行われることになる。
●BestSOT は同社初の Best Linux 英語版を出荷する。発表は2月24日に CeBIT の会場で行われる予定。Best Linux 2000 の特徴は無期限のサポートとアップデートだ。ユーザには自動的に最新バージョンが送られる。ボックス版もリリースされる予定。
http://www.bestlinux.net
Macmillan USA はプロのサーバ管理者用の Secure Server 7.0 を発表した。これは Linux−Mandrake(tm) 7.0 に基づいた Linux ウェブサーバだ。
●MaxOS (Alta Terra)Mosaic Technologies Corp. の Linux トレーニングプログラムが Alta Terra Ventures Corp. の Linux OS にバンドルされることになった。両社は Linux を PC デスクトップして普及させることを目標にしており、Mosaic は Windows 環境で動作する Linux を提供する予定。
Mosaic Technologis Corporation
Alta Terra Ventures Corp.
SCO と SuSE Linux AG が提携。SuSE のユーザはSCO プロフェッショナルサービスを受けられるようになる。SCO のプロフェッショナルサービスは SuSE inux システムの企画、インストール、環境設定、配備などの支援をする。
● TurboLinuxLutris Technologies Inc. と TurboLinux Inc. はオープンソース e-business プラットフォームの強化に向け協力することになった。Lutris の Enhydra Java/XML アプリケーションサーバが TurboLinux OS に組み込まれ、Lutris はサポート、トレーニング、プロフェッショナルサービスを提供する。
▼▼▼その他のニュース▼▼▼|
Colorado Linux Info Quest |
April 1, 2000 Denver, CO thecliq.org
|
|
Corel Linux Roadshow 2000 |
April 3-7, 2000 Various Locations www.corel.com/roadshow/index.htm
|
|
Montreal Linux Expo |
April 10-12, 2000 Montreal, Canada www.skyevents.com/EN/
|
|
Spring COMDEX |
April 17-20, 2000 Chicago, IL www.zdevents.com/comdex
|
|
HPC Linux 2000: Workshop on High-Performance Computing with
Linux Platforms |
May 14-17, 2000 Beijing, China www.csis.hku.hk/~clwang/HPCLinux2000.html (In conjunction with HPC-ASIA 2000: The Fourth International Conference/Exhibition on High Performance Computing in Asia-Pacific Region)
|
|
Linux Canada |
May 15-18, 2000 Toronto, Canada www.linuxcanadaexpo.com
|
|
Converge 2000 |
May 17-18, 2000 Alberta, Canada www.converge2000.com
|
|
SANE 2000: 2nd International SANE (System Administration and
Networking)
Conference |
May 22-25, 2000 MECC, Maastricht, The Netherlands www.nluug.nl/events/sane2000/index.html
|
|
ISPCON |
May 23-25, 2000 Orlando, FL www.ispcon.internet.com
|
|
Strictly Business Expo |
June 7-9, 2000 Minneapolis, MN www.strictly-business.com
|
|
USENIX |
June 19-23, 2000 San Diego, CA www.usenix.org
|
|
LinuxFest |
June 20-24, 2000 Kansas City, KS www.linuxfest.com
|
|
PC Expo |
June 27-29, 2000 New York, NY www.pcexpo.com
|
|
LinuxConference |
June 27-28, 2000 Zürich, Switzerland www.linux-conference.ch
|
Computer I/O Corporation は Easy I/O サーバを発表。Easy I/O サーバは Linux ベースのネットワーク I/O サーバで、コスト効率のよいリアルタイムネットワークデータストリーミングを可能にする。Easy I/O はローレベル、リアルタイム、ネットワークプログラミングなどの知識がなくてもストリーミングデータサーバを構築できる。
www.computerio.com
Internet Technologies, Inc. は非常に効率的な e-Coomerce システムを開発した。RedHat Secure Server、MySQL データベースエンジン、PHP、オープンソースの画像処理ソフト、PGP 暗号技術などを利用している。セキュアウェブサーバに接続された Hell's Kitchen System CCVS がクレジットカード情報を保持し不正なアクセスからシステムを防御している。クレジットカード情報はウェブサーバではなくCCVSサーバ上に保管されている。
Viewlets はヘルプファイルやFAQを HOWTO デモンストレーションに変換する。Linux の精神に則り Viewlets はフリーで公開される。 www.teach2earn.com/linux で SuSE Linux 6.3 で構築された Viewletsを見ることができる。
ヨルダンの Quality Internet がフリーのオフィススイートを提供。MyFreeDeskにはワープロ、表計算、プレゼンテーション、データベース、メール、HTMLエディタなどが含まれる。
インフォメーションはディストリビューションや Linux OS などをカバーする20のディレクトリだ。ディレクトリには Caldera、Open Linux、Corel Linux、Debian、Linux Mandrake、MK Linux、Red Hat、Slackware、SuSE、WinLinux 2000などが含まれている。
LinuxMall.com は LPI(linux Professional Institute)の標準認定を支援している。LPI はベンダにとらわれないLinux OS の認定確立に努力している。LPI 最初の認定テストは今年の1月に行われた。
LinuxMall.com からDice.com のジョブ検索が可能になる。LinuxMall ではトレーニングや教育に関する情報も充実させる。
LinuxMallの商品にペンギンのデザインのカードが加わる。キング、クイーン、ジャックのデザインもペンギンだ。LinuxMall.com にはその他多数の商品が揃っている。 http://www.linuxmall.com/shop/01840
KDevelop 1.1 のファイナルバージョンが発表された。いくつかの新機能と多数のバグフィックスを含んでいる。これは KDE 1.1.2 の最終バージョンになる予定だ。次のバージョンはKDevelop 2.xになる。ファイナルバージョンではテンプレートの増加、デバッガ内臓、充実したドキュメント、エディタの改善、コンポーネント、dlg、クラスビューアなど機能が充実しており、Linux、NetBSD、FreeBSD、Solaris、Unixwareなどに対応している。
http://www.kdevelop.org
Progress Software Coporation の Progress SonicMQ インターネットメッセージングサーバが Linux に対応する。SonicMQ は現在のところ Sun の Java 仕様に基づいた唯一のメッセージングサーバだ。
www.progress.com
次のようなスクリプトを作成してコマンドラインで
dict 語彙のようにタイプすると語彙の意味が表示される。
lynx "http://www.m-w.com/cgi-bin/dictionary?book=Dictionary&va=$*"●FAQ を作成するPerlスクリプト
faq_builder.pl を使えばアスキーテキストファイルをFAQに変換してくれる。
●winmodemWinmodem は Linux では使えなかったが試しに linmodems.org をチェックしてみよう。LUCENT は LT MODEMS のバイナリを公開しているしその他のドライバでも開発中のものがある。
●Linux に関する本www.infocom.cqu.edu.aut99/85321 では "An Introduction to Linux Systems Administration (David Jones and Bruce Jamieson 著) という優れた本がオンラインで公開されている。
●ページ番号を入れたページを印刷するにはテキストファイルなら "pr -f - | 55 somefile.txt | lpr" と打ち込めばできる。html ファイルなら "html2ps" というツールを使う。ワープロならアプリケーションの中で操作できるはず。その他 "man pr", "man nenscript" など自分で調べることを促すもの。mpage を使って "mpage -2 -H document | lpr" など。
●安価で強力な分散処理型のデータベースはLinux.org のアプリケーションセクションをチェックする。商用なら DB2、Oracle、Informix、Ingres など。フリーなら PostgreSQL、MySQL など。
●IP Masquerade での接続が不調Red Hat 6.1 なら PPP パッケージにバグがある。アップデートしよう。
●Linux と win98 でインターネット接続の共有winroute.com から WinRoute をダウンロードして Win98 にセットアップしよう。Win98 マシンを「デフォルトゲートウェイ」に設定すれば Linux マシンからもインターネットへアクセスできる。
●AS/400 エミュレーション tn5250 で AS/400 にアクセスできる。
http://www-4.ibm/software/network/hostondemand で IBM がjava ベースのクライアントを公開しており Linux でも動作すると報告されている。
オートマウントや "mount", "umount" などのコマンドも使わずにマウントを処理するスクリプト。
#!/bin/bash d="/mnt/fd0" if [ -n "$(mount $d 2>&1)" ]; then umount $d; fi応用すれば他のデバイスにも利用できる。 ●Red Hat Linux 6.0 用の アンチバイルスプログラムは?
いくつかのプログラムが利用できる。 http://freshmeat.net/appindex/daemons/anti-virus.html をチェックしよう。
●モデムが反応するがダイアルしないsetserial コマンドを使って設定をやり直す。
setserial /dev/ttyS2 irq 5 uart 16550Sブート時の設定ファイルに入れておけばいい。 ●FD/CD のスロットが一つのラップトップに Linux をインストール
Debian
Windows パーティションに C:\linux のようなディレクトリを作成してディストリビューション CD-ROM から "loadlin.exe, root.bin, linux" をコピーする。
再起動して DOS を立ち上げる。Linux ディレクトリに移動し
loadlin linux root=/dev/ram initrd=root.binRed Hat
loadlin vmlinuz initrd=initrd.img●Mandrake 7.0 で vi 風のエディットモードを使用する
ルート権限で /etc/inputrc ファイルを別のファイル名で保存し、/etc/inputrc の内容を次のように変更する。
set conveet-meta off set input-meta on set output-meta on set keymap vi set editing-mode vi●Red Hat 6.1 でダイアルインがハングアップする
ppp を ppp-2.3.11-1、カーネルを 2.2.14 にしたら不具合が解消した。
●Linux 起動時に64MB 以上のメモリを認識させるLilo 設定ファイルに 「append = "mem=128M" 」を追加する。または起動時にコマンドラインからの引数として渡す。
●Linux で複数のビデオカードを利用するXFree4.0 を待つg
●Linux で画面のキャプチャImageMagick の import コマンドを利用したスクリプトを使う。
#!/bin/bash
max=5 # キャプチャする画面の枚数
pause=1 # キャプチャの間隔
count=1
while
[ $count -le $max ]
do
sleep $pause
import -window root shot$x.gif
let count=count+1
done
マイクロソフトは独占禁止法に違反していると告発されて以来何度も意見を変えてきた。ほとんど脅威にもなっていない Linux を競争的な OS と表現したかと思えば株主への説明では絵に描いた餅と表現している。司法の場では驚異的な OS と言い、実際には取るに足らないもの言っている。しかし Linux は多数の プラットフォームに対応した非常に優れた OS です。現在ではサーバとして Windows NT や Windows 2000 にも競合する OS となっています。
GUI に関してはどうでしょうか。裁判では KDE が Winodws 98 のようなデスクトップ環境を提供していると言い、Linux Myth ではカーネルの複雑さと GUI の未熟さとでユーザにはかなりのトレーニングが必要になると言っている。実際には Corel の KDE インタフェースは非常に優れたものでありユーザフレンドリとなっている。Linux コミュニティの支持を考えればこれらデスクトップ環境が近い将来非常に使いやすいものになる可能性がある。
OS は GUI として認識されているとしよう。ではアプリケーションはどうだろう。裁判でのマイクロソフトの意見は多数の開発者がアプリケーション開発に従事しており、将来も継続されるだろうというものだが、Linux Myth では デスクトップ OS としては問題外、ユーザにとってはアプリケーションが少なく直感的に操作することもできないと評価している。訴訟と実際とでは意見が異なっています。実際には Wine のようなフリーで公開されているエミュレーションアプリケーションにより Windows のアプリケーションを動作させることも可能になっています。VM-Ware を使えば Linux と Windows を同時に動作させることも可能です。それに Windows のアプリケーションを Linux に移植しようという試みはますます加速するでしょう。マイクロソフトはこの問題に関しては正直ではない。現に Windows 2000 はかなりの互換性の問題を抱えている。今後64ビット OS が登場すれば Linux も Windows と同じ土俵に立てるだろう。
ハードウェアの対応はどうだろう。ここでもマイクロソフトは意見を巧妙に区別している。司法の場では Sun、Dell、Gateway、東芝、IBM、Silicon Graphics など多数の企業が Linux をサポートしていると言っているが Linux Myth では現実的なバックアップがないと言っている。マイクロソフトの顧客リストはすばらしいものだろうが Linux のそれにもフォーチュン2000の顧客が多数リストアップされている。この記事を書いている現在でも Linux 対応のハードウェアを出したいという企業は増加している。
ユーザサポートに対してもマイクロソフトの意見は「Linux はサポートにコストがかかりすぎる」というものだが、現実に多数のユーザが存在している。今後ますます増加するだろう。それにマイクロソフトは Linux OS のコストに関しては言及していない。Windows NT/2000 をサーバとして運用している企業はかなりのコストがかかりる。それに問題が発生した場合には Windows は再起動を要求される。Linux はほとんと再起動をする必要がなく連続で動作させることができる。
Linux はいずれ優れた OS となるだろう。その開発も止むことはない。マイクロソフトは非常に戦略的に優れた企業ですから意見があちこちで相違を見るのも当然なのかもしれません。今後の問題はLinux がデスクトップとして利用できるかどうかではなく一般的に受け入れられるかどうかなのです。
今月の HelpDex は こちらを ご覧ください。
毎月 Linux に関連したサイトを一つ取り上げて紹介していくコーナーです。今月紹介するのは Glade (http://glade.pn.org/) です。
GUI に慣れてしまうとコマンドラインを使うというのは面倒になることが多く、プログラマの観点からもエディタとコンパイラで GUI のアプリケーションを作るのは時間がかかる。こう言う場合に役に立つのがこのサイトだ。Glade は GTK+ を使ったインタフェース構築を容易にする。GNOME がインストールされていれば ネーティブのGNOME インタフェースを構築する。さらに C、C++、Ada95、Python、Perl などのコードを作ることも可能。Glade はまだ開発途上で最新バージョンは現在 0.5.7だ。
Glade のウェブサイトは派手なサイトではないが、大きな画像をダウンロードするのに時間がかかるサイトよりも好感が持てる。Glade の機能紹介のページは Glade 自身で作られている。リンクセクションからは Glade を使ったページ、Glade に対応したページへ移動することができる。規模の大きなサイトではないがそれを質でカバーしている。このサイトだけで Glade のインストール、アプリケーションの構築、サンプルプログラムの参照など一通りのことが間に合ってしまう。
記事を書く前に遭遇した話題から。MUA/MTA をインストールしたら root 以外のユーザでログインできなくなった。そのときのエラーメッセージが "Cannot execute /bin/bash: Permission denied" だった。原因を調べようと /etc/password, /etc/groupe をチェックし、/etc 以下のファイルも調べたが異常がない。通常ならログインに失敗すると "Login incorrect" が表示されるはず。/bin 以下のファイルのパーミションもチェックするが異常はない。/home のパーミションも同じように異常はない。一番簡単な解決法はOS の再インストールだがそれでは原因がわからない。"System Administrator's Guide" やウェブサイトで調べても十分な答えが得られない。そこで "strace" を使ってプログラム実行をトレースすることした。使ったコマンドは次の通り。
strace -s 10000 -vfo login.ben login ben strace -s 10000 -vfo login.root login rootroot のログイン過程もトレースして比べてみる。これで違いがわかるはず。ログインの過程をトレースした結果目に付いたポイントはこれだ。
(300+ lines elided)
execve("/bin/bash", ["-bash"], ["TERM=linux", "HZ=100", "HOME=/home/ben",
"SHELL=/bin/bash", "PATH=/bin:/usr/bin", "USER=ben", "LOGNAME=ben",
"MAIL=/var/spool/mail/ben", "LANG=C", "HUSHLOGIN=FALSE"]) = -1 EACCES
(Permission denied)
write(2, "Cannot execute /bin/bash: Permission denied\n", 44) = 44
この結果 "login" から起動されるライブラリに問題がありそうだと見当をつけ、/lib にある ld-2.0.7.so のパーミッションが 644 になっていることに気がついた。これは 755 でなければならないはず。そこで パーミッションを 755 に変更して問題は解決した。
問題が発生した場合に OS を再インストールして解決するのは簡単だがそれでは今後同じ問題が発生しても自力では解決できなくなってしまう。なるべく "System Administrator's Guide" や man や HOWTO を利用して問題の解決に努めるようにしよう。そうすれば Linux がもう少し楽しくなるはずだ。
シェルスクリプトは非常にシンプルなツールだが柔軟で強力な Linux のパワーを引き出すことができる。PC 上で DOS のバッチファイルを使っていたが、今考えると DOS は Unix のシェルスクリプトの貧弱な模倣でしかない。Linux は初心者にやさしいシステムではない。シェルスクリプトもプログラムの一部だ。が、プログラムそのものよりは簡単だ。再利用可能のスクリプトを書けばそれだけ後々楽になる。
筆者の好みのシェルは "bash" だ。気をつけなければならないことは、作業ディレクトリはホームディレクトリにする、シェルスクリプトファイルの名前はパスの通った実行可能ファイルと同じものは使わない。また決して "test" というファイル名を用いないこと。同名の実行可能ファイルが /bin ディレクトリに存在する。さらにファイルオペレーションやファイルシステムに関する若干の知識が必要で、エディタを利用できること。今回使用するエディタは mcedit だ。
実際に簡単なシェルスクリプトを書いてみよう。シェルスクリプトはコマンドラインで入力する一連のコマンドと同じだ。それをシェルにスクリプトであることを知らせればいい。最初の例は指定したファイルを指定したディレクトリへバックアップするスクリプトだ。まずファイルを作成しパーミッションを設定する。
> bkup chmod +x bkup1行目のコマンドはカレントディレクトリに "bkup" というファイルを作成する。
mcedit bkupスクリプトファイルの最初はいつもこれで始まる。なお、行頭の番号は分かりやすいように付けているだけなので無視すること。
スクリプトファイルの中で#で始まる行はコメントとしてシェルから無視されるのだがこれだけは特別だ。スクリプトが開始するときに現在のシェルは別の bash プロセスを起動してスクリプトを実行する。スクリプトが終了すれば元のシェルにプロセスが戻る。
1: #!/bin/bash
スクリプトを続けよう。
前述の通り、# で始まる行はコメントだ。シェルからは無視される。でもスクリプトに説明をつけておくことはいいことだ。
2: # "bkup" - 指定されたファイルをファイル名の競合をチェックしてから 3: # ~/Backup ディレクトリにコピーする
"cp" コマンドの "-i" オプションは "cp" コマンドをインタラクティブに動作させる。もし Backup ディレクトリに 同名のファイルが存在すると上書きするかどうか問い合わせる。$1 は特定の引数を表す。この場合は2つ目の引数だ。一つ目の引数 $0 はコマンド名、この場合は bkup になる。#@ は引数のリスト、$# は引数の数を表す。引数を操作する方法はその他にもあるが bash のマニュアルを参照して欲しい。
4: cp -i $1 ~/Backup
このままではあまり役に立つスクリプトではない。そこでバックアップの際にバージョンを付加するように変えてみよう。
&(コマンド)は括弧内のコマンドを実行して全体をその結果に置き換える。この例では日付時間を取得して変数 "a" に代入しそれをファイル名に付加している。変数 "a" を参照するには "$" を変数名の前に付ける。変数名は自由に使えるが予約語や予約された記号、シェルで使用される変数名は使用できない。
4: a=$(date +%T-%d_%m_%Y) 5: cp -i $1 ~/Backup/$1.$a
さてここまで作成したシェルスクリプトは次の通りだ。
#!/bin/bash
# "bkup" - 指定されたファイルをファイル名の競合をチェックしてから # ~/Backup ディレクトリにコピーする
a=$(date +%T-%d_%m_%Y) cp -i $1 ~/Backup/$1.$aわずか2行のシェルスクリプトだがシェルスクリプトを学ぶにはいい材料だろう。ところでこのスクリプトを
bkupのように実行してみると
bash: bkup: command not foundのようなメッセージが表示されるはずだ。これは DOS などと違い、カレントディレクトリにパスが通っていないためだ。このスクリプトを実行するには次のようにする。
./bkup file.txt
シェルスクリプトは Unix のパワーを引き出すツールだ。来月はエラーチェック、ループ、条件分岐、それに強力なツールにも触れる予定だ。
コンパイラやインタプリタを作成するというのは難しい。プログラムを書くことの他にもいろいろな知識を要求する。Python のユーザとして今学んでいるものを Python で試してみようと思う。でもオブジェクト指向やガベージコレクションなど高度な話題ではなく非常に初歩的なものだ。例えば次のようなコマンドを実行するようなものだ。
1+2*3-4 1/2+3-4/5 .....最初はこのような式を読み込んで処理をし、次は構文解析木を使い、最後は仮想マシンへの命令を作成してディスクから必要に応じて動作させるようにしたい。
E ::= T { ADDOP T }
T ::= F { MULOP F }
F ::= 0 | 1 | 2 | 3 | .....
ADDOP ::= + | -
MULOP ::= * | /
まず数学の式を上のように表してみる。E は式、T は項、F は要素だ。{} の中は0個以上の繰り返しとなる。これを Python で実行するコードは次のようなものだ。
#--------------------単純な式の評価---------------#
import re, string
Inputbuf = []
# トークンは数字か演算子
# プログラムの main はinput から1行ずつ読み込み
# Inputbuf という配列に保存する
# 関数 gettoken() はこの配列から個々のトークンを返す
def gettoken():
global Inputbuf
p = re.search('^\W*[\+\-\*/]|^\W*[0-9]+', Inputbuf)
token = p.string[p.regs[0][0]:p.regs[0][1]]
token = string.strip(token)
if token not in ['+', '-', '*', '/']:
token = int(token)
Inputbuf = Inputbuf[p.regs[0][1]:]
return token
# lookahead() はインプットストリームを調べ
# 次のインプットトークンを返す
def lookahead():
global Inputbuf
try:
p = re.search('^\W*[\+\-\*/]|^\W*[0-9]+', Inputbuf)
token = p.string[p.regs[0][0]:p.regs[0][1]]
token = string.strip(token)
if token not in ['+', '-', '*', '/']:
token = int(token)
return token
except:
return None
def factor():
return gettoken()
def term():
e1 = factor()
tmp = lookahead()
while (tmp in ['*', '/']):
gettoken()
if (tmp == '*'):
e1 = e1 * factor()
else:
e1 = e1 / factor()
tmp = lookahead()
return e1
def expression():
e1 = term()
tmp = lookahead()
while (tmp in ['+', '-']):
gettoken()
if (tmp == '+'):
e1 = e1 + term()
else:
e1 = e1 - term()
tmp = lookahead()
return e1
def main():
global Inputbuf
Inputbuf = raw_input()
print expression()
if __name__=='__main__':
main()
上の例は単純に数学の式を評価するだけのものだ。これを構文解析木を作成できるように修正する。式 1+2*3 の構文解析木は次のようになる。
+
/ \
/ \
1 *
/ \
/ \
2 3
項分解析木はボトムズアップで作成される。関数 factor は数字を持ったノードを作成し、左右のノードを NULL ポインタで作成しノードを返す。関数 expression() は演算子のノードで "+" や "-" を格納し左右のノードには term() が返す数字へのポインタを保持する。term() の動作も同様だ。#--------------------構文解析木の作成---------------------# # gettoken() と lookahead() は最初の例と同じ NULL = 0 import re, string Inputbuf = [] class Tree: pass def factor(): newnode = Tree() newnode.number = gettoken() newnode.left = newnode.right = 0 return newnode def term(): left = factor() tmp = lookahead() while (tmp in ['*', '/']): gettoken() right = factor() newnode = Tree() newnode.op = tmp newnode.left = left newnode.right = right left = newnode tmp = lookahead() return left def expression(): left = term() tmp = lookahead() while (tmp in ['+', '-']): gettoken() right = term() newnode = Tree() newnode.op = tmp newnode.left = left newnode.right = right left = newnode tmp = lookahead() return left def treeprint(ptree): if (ptree): try: print ptree.op except: print ptree.number treeprint(ptree.left) treeprint(ptree.right) def main(): global Inputbuf Inputbuf = raw_input() ptree = expression() return ptree if __name__=='__main__': ptree = main() treeprint(ptree)
上記の構文解析木は再帰関数により評価されるが今回はスタックマシンという仮想マシンを使って処理をしてみよう。このマシンの命令は単純だ。数字をスタックに積み、二つの数字を加算、乗算・・・するというものだ。式 1+2*3 は次のようなコードを生成する。
push 1 push 2 push 3 mul addPush, mul, add などは配列に格納された命令だ。配列の命令は直接実行され、配列の要素に格納された関数やディスクにファイルとして保存されている関数が実行される。筆者の書いたコードはこのように動作する。引数なしでプログラムを実行するとキーボードから式を読み込み、仮想マシン用のコードを作成し実行する。コードは "code.out" というファイル名でディスクに保存されるので "code.out" を引数にプログラムを起動するとキーボードからの入力なしで実行される。
import re, string, sys, pickle
# プログラム中に存在しない関数は上記のプログラムからコピーする
NULL = 0
Inputbuf = []
NCODE = 100
NSTACK = 100
Code = []
Stack = [0] * NSTACK
Pc = 0
Stackp = 0
class Tree:
pass
class CodeItem:
pass
def initcode():
global Code
for i in range(0, NCODE):
t = CodeItem()
Code.append(t)
def pushop():
global Stack, Stackp, Code, Pc
Stack[Stackp] = Code[Pc].number
Stackp = Stackp + 1
Pc = Pc + 1
def addop():
global Stack, Stackp, Code, Pc
Stackp = Stackp - 1
right = Stack[Stackp]
Stackp = Stackp - 1
left = Stack[Stackp]
Stack[Stackp] = left + right
Stackp = Stackp + 1
# subop, mulop, divopをここで宣言する
def generate(codep, ptree):
try:
# 'number' という項目が存在しないと
# 例外が発生する
n = ptree.number
Code[codep].op = pushop
codep = codep + 1
Code[codep].number = n
codep = codep + 1
return codep
except:
if (ptree.op == '+'):
codep = generate(codep, ptree.left)
codep = generate(codep, ptree.right)
Code[codep].op = addop
codep = codep + 1
return codep
# elif (ptree.op == '-'): ここに '-', '*', '/' 等の
# コードを書く
def eval(ptree): # 命令を作成して実行
global Pc, Stackp, Code, Stack
Pc = generate(0, ptree)
Code[Pc].op = NULL
Stackp = 0
Pc = 0
while Code[Pc].op != NULL:
tmp = Pc
Pc = Pc + 1
Code[tmp].op()
return Stack[0]
def eval2(): # 読み込まれたコードを直接実行
global Pc, Stackp, Code, Stack
Stackp = 0
Pc = 0
while Code[Pc].op != NULL:
tmp = Pc
Pc = Pc + 1
Code[tmp].op()
return Stack[0]
def main():
global Inputbuf, Code
try:
f = open(sys.argv[1])
Code = pickle.load(f)
f.close()
result = eval2()
print 'result is:', result
return result
except:
print 'Not opening code file, reading from k/b'
initcode()
Inputbuf = raw_input()
ptree = expression()
result = eval(ptree)
f = open('code.out', 'w')
pickle.dump(Code, f)
print 'Code dumped in a file called dat'
print 'result is:', result
return result
if __name__=='__main__':
result = main()
"generate()" と "eval()" は非常に重要な関数だ。"gererate()" は仮想マシン用のコードを作成し配列に格納する。"eval()" はスタックを使用して配列に格納された命令を実行する。
このコードを拡張して変数、アサインメント、goto や if などを組み込むことも可能だ。そうすると単純な Basic のような言語になる。