eval関数を実現する (1) [ColdFire V2]
SilentCは、インタプリタなので、逐次、字句解析を行って処理を行っています。 このため、プログラム実行中に作成した文字列を実行する事だって出来そうです。 あるいは、ネットワークを通じて、スクリプトを送り込むこともできます。 こんな事のできる、「eval関数が欲しい」な。 何だか、危険な香りがするぞ。
CGIを利用する
SilentC のhttpサーバには、 CGI と呼ばれる機能があり、HTML文書に埋め込まれたスクリプトを実行することができます。 外部からHTML文書を入れ替えて、そのHTML文書を呼び出せば、スクリプトが実行できます。
これと同等の機能を備えた関数をSilentCから呼び出すことが出来ます。
ReplaceCgi関数を使う
"ReplaceCgi"関数は、HTML文書に埋め込んだCGI表現を置き換えるために使われる関数です。 これを使って、実行すべき関数を外部から指定するプログラムを作成しました。
char *message; main(char *func){ char *buf; if (message==0) { message=MemoryAlloc(256); } buf=MemoryAlloc(256); MemClear(buf,256); StrCpy(buf,"$EXEC'Main::"); StrCat(buf,func); StrCat(buf,"()'"); PrStr(buf);PrStr("\r\n"); ReplaceCgi(buf,255); PrStr(message); PrStr(buf);PrStr("\r\n"); MemoryFree(buf); } a(){StrCpy(message,"HELLO");} b(){StrCpy(message,"GOOD BYE");}
実行してみると、
OK Main::main("a") $EXEC'Main::a()'
どこかに飛んでいってしまいました。 グローバル変数を使用したことに問題があるのかと思いましたが、別の方法で実行結果を受け取るようにしても、飛んでいってしまいました。 原因は、不明ですが、別の方法を考えましょう。
プログラム・ファイルを入れ替えちゃえ
SilentCで実行しているプログラムは、メモリ上に展開されたソースコードではなく、ファイルシステム上のファイルということになっています。 そのため、あるファイルのある関数をメインプログラムから呼び出す前に、呼び出されるファイルを入れ替えちゃえば実行すべきプログラムを書き換えるのは簡単です。
eval(char *func){ char *filename="f"; DeleteFile(filename); CreateFile(filename); WriteFile("run(){",6); WriteFile(func, StrLen(func)); WriteFile("}\r\n",3); CloseFile(0); f::run(); }
このサンプルでは、実行するスクリプトをeval関数に渡します。
OK Main::eval("PrStr(\"HELLO WORLD\\r\\n\");") HELLO WORLD OK type f run(){PrStr("HELLO WORLD\r\n");} OK
ファイル"f"にプログラムが書き込まれているのが分かります。 この方法の難点は、"eval"の実行のたびにファイル、つまりFLASHに書き込みが発生してしまうことです。
参考文献
Interface (インターフェース) 2008年 09月号 [雑誌]
- 作者:
- 出版社/メーカー: CQ出版
- 発売日: 2008/07/25
- メディア: 雑誌
コメント 0