タイトル/名前 | 更新者 | 更新日 |
---|---|---|
技術/Linux/readline, inputrc, ビープ音オフ | msakamoto-sf | 2009-04-19 10:42:14 |
日記/2004/03/01/卒業研究 | msakamoto-sf | 2009-04-18 19:53:00 |
日記/2005/05/08/ProFTPDの認証が時間がかかる | msakamoto-sf | 2009-04-18 11:17:16 |
Perl/codepiece/constantプラグマによる定数定義 | msakamoto-sf | 2009-04-12 22:43:06 |
Perl/codepiece/array_hash2(関数への参照渡し) | msakamoto-sf | 2009-04-12 22:35:14 |
Perl/codepiece/caller関数 | msakamoto-sf | 2009-04-12 22:10:54 |
Perl/codepiece/OOP(基本) | msakamoto-sf | 2009-04-12 21:53:14 |
Perl | msakamoto-sf | 2009-04-12 21:32:48 |
日記/2004/08/05/コマンドプロンプトでのTAB補完、ビープOFF | msakamoto-sf | 2009-04-12 18:13:57 |
Perl/Devel::ptkdbによるグラフィカルデバッグメモ | msakamoto-sf | 2009-04-12 17:34:08 |
readlineとは、CUIプログラムにおいてコマンド履歴機能やTABキーによる補完機能を実現するのに使われるGPLライブラリ。
inputrcはreadlineの設定ファイル。
デフォルトのキーバインドはEmacsとよく似ている。
bash上からは以下のコマンドでキーバインドをemacs風/vi風に切り替えることが出来る。
$ set -o vi # vi風のキー・バインドに変更 $ set -o emacs # emacs風のキー・バインドに変更
設定ファイル(inputrc)の読み込み順序は以下の通り。
inputrcの変更を反映するには、readlineをリンクしているプログラムを再起動するか、bashであれば"C-x C-r"を入力する。
inputrcの書式は「set 変数名 値」の順になる。値は「on」か「off」のどちらかが多い。
set editing-mode vi (vi風) set editing-mode emacs (emacs風)
set completion-ignore-case on (無視) set completion-ignore-case off (無視しない)
set output-meta on set input-meta on set convert-meta off
set bell-style visible # audible : ビープ音を鳴らす。 # none : 鳴らさない。 # visible : 鳴らさない代わりに画面を点滅。
参考URL :
readlineはGPL。NetBSDにおいては、BSDライセンスによる同等のライブラリ、libeditを開発した。
現在、sf.net上にNetBSDよりスピンアウトして独立したlibeditプロジェクトがある。
http://sourceforge.net/projects/libedit/
GPLの制限を逃れる為のもう一つの方策として、"rlwrap"というOSSも出現した。
http://freshmeat.net/projects/rlwrap
$ rlwrap ruby
のように実行する。引数をforkした子プロセスにて実行し、自身は入出力ファイルディスクリプタのI/Oを子プロセスに流し込むブリッジになる。
卒業研究で作成したプログラムとその関連パッケージのダウンロードリンクを示す。
以下のプログラミング技術を勉強できた。
卒業「研究」というよりは卒業「制作」。
※2003/11 - 2004/1 にかけてプログラミングしています。2009年現時点では相当古くなっていますので、おそらくそのままではコンパイル出来ないと思います。 ライブラリやxawtvの改造など、順番も重要です。
対応OSはTurbolinux 8 workstation
対応Linuxカーネルは kernel-2.4.22 以上.2.6は未確認.
1. 最初にmovemasterのキャラクタデバイスドライバをコンパイルする。
arv-gsmtd-mm.tgzの中にmovemasterというディレクトリがあり、その中のmm_driver.cをコンパイルします。
$ gcc -c mm_driver.c -Wall -Wstrict-prototypes -O -pipe
RS232C(Serial)サポートを外したカーネルで使ってください(重要)。
2. 次にGSMTD(共有メモリへのアクセスをTCP越しで行うデーモン)をコンパイルします。
arv-gsmtd-mm.tgzの中にgsmtdというディレクトリがあります。Makefileがありますので、makeコマンドでコンパイルします。
3. libgsmtdclient.so をコンパイルします。
gsmtd/libgsmtdclient ディレクトリの中にMakefileがあります。
コンパイル後は、libgsmtdclient.soを適当にLD_LIBRARY_PATHを通したディレクトリにコピーします。
4. arv本体をコンパイル
arv-gsmtd-mm/arv/Makefileを最初に実行し、arv_common.o を作ります。その後、各サブディレクトリのMakeを実行します。
libgsmtdarv.soを適当にLD_LIBRARY_PATHを通したディレクトリにコピーします。
5. xawtvのコンパイル後のソースツリーを入手。
webcam-gsmtd-client.tgzの中のREADME.euc-jpを参照。
6. システムの実行
arv-gsmtd-mm/arv/arv.sh を実行すると、2. 以降を自動で処理してくれます。
ProFTPDの認証で異常に時間がかかる場合、以下の二つの指示子をoffにする事を検討してみること。
UseReverseDNS off IdentLookups off
UseReverseDNS :
Normally, incoming active mode data connections and outgoing passive mode data connections have a reverse DNS lookup performed on the remote host's IP address. In a chroot environment (such as or DefaultRoot), the /etc/hosts file cannot be checked and the only possible resolution is via DNS. If for some reason, DNS is not available or improperly configured this can result in proftpd blocking ("stalling") until the libc resolver code times out. Disabling this directive prevents proftpd from attempting to reverse-lookup data connection IP addresses.
IdentLookups :
Normally, when a client initially connects to proftpd, the ident protocol (RFC1413) is used to attempt to identify the remote username. This can be controlled via the IdentLookups directive.
実際に試した効果としては、UseReverseDNSのoffよりはIdentLookupのoffの方が劇的な効果があった。(UseReverseDNSの効果が無い、というわけではない)
定数を定義したい場合は constant プラグマ(*1)を検討すると良い。詳細はperldocの constant pragma の説明を参照。
以下に簡単なコードピースを示す。
constant.pl
#!/usr/bin/perl use strict; use warnings; { package CSample; use constant { CS_LEVEL1 => "CSample::level1", CS_LEVEL2 => "CSample::level2", CS_LEVEL3 => "CSample::level3", CS_LEVEL4 => "CSample::level4", CS_LEVEL5 => "CSample::level5", }; } print CSample::CS_LEVEL1, "\n"; print CSample::CS_LEVEL2, "\n";
実行例
DOS> perl constant.pl CSample::level1 CSample::level2
関数に配列またはハッシュのリファレンスを渡し、関数内で操作するサンプル
#!/usr/bin/perl use strict; use warnings; use Test::More qw(no_plan); sub foo { my $h = shift; $h->{'val1'} = "abcdefg"; return $h; } print "-------------------------\n"; print " Hash - Part I :\n"; print "-------------------------\n"; my $h1 = {val1 => 123, val2 => "faklsdjsd"}; my $ref_h = $h1; print "hash reference(1) : [", $h1, "]\n"; is($h1->{'val1'}, 123); is($h1->{'val2'}, "faklsdjsd"); my $h2 = foo($h1); print 'return ref of foo($h1) : [', $h2, "]\n"; is($ref_h, $h1); is($ref_h, $h2); is($h1->{'val1'}, "abcdefg"); is($h2->{'val1'}, "abcdefg"); print "-------------------------\n"; print " Hash - Part II :\n"; print "-------------------------\n"; my %h1 = (val1 => 456, val2 => "lsjakfsdl"); print "hash reference(2) : [", \%h1, "]\n"; $ref_h = \%h1; is($h1{'val1'}, 456); is($h1{'val2'}, "lsjakfsdl"); $h2 = foo(\%h1); print 'return ref of foo($h1) : [', $h2, "]\n"; is($ref_h, \%h1); is($ref_h, $h2); is($h1{'val1'}, "abcdefg"); is($h2->{'val1'}, "abcdefg"); print "-------------------------\n"; print " Arrays:\n"; print "-------------------------\n"; sub bar { my $a = shift; push @{$a}, "abcd"; return $a; } my @a1 = ( ); # is same as $a1 = [ ]; push @a1, 123; push @a1, "hogehoge"; print "array reference : [", \@a1, "]\n"; my $ref_a = \@a1; is(join(" ", @a1), '123 hogehoge'); my $a2 = bar(\@a1); print 'return ref of bar(\@a1) : [', $a2, "]\n"; is($ref_a, \@a1); is($ref_a, $a2); is(join(" ", @a1), '123 hogehoge abcd'); is(join(" ", @$a2), '123 hogehoge abcd');
実行例
DOS> perl hash_ref.pl ------------------------- Hash - Part I : ------------------------- hash reference(1) : [HASH(0x284ef0)] ok 1 ok 2 return ref of foo($h1) : [HASH(0x284ef0)] ok 3 ok 4 ok 5 ok 6 ------------------------- Hash - Part II : ------------------------- hash reference(2) : [HASH(0x1941884)] ok 7 ok 8 return ref of foo($h1) : [HASH(0x1941884)] ok 9 ok 10 ok 11 ok 12 ------------------------- Arrays: ------------------------- array reference : [ARRAY(0x1941ac4)] ok 13 return ref of bar(\@a1) : [ARRAY(0x1941ac4)] ok 14 ok 15 ok 16 ok 17 1..17
現在のサブルーチン呼び出しのコンテキストを取得するcaller関数を使うと、パッケージ名や関数名などを取得できる。
以下、簡単なコードピース
#!/usr/bin/perl use strict; use warnings; { package Sample; sub whoami { # my ($package, $filename, $line) = caller; my ($package, $filename, $line, $subroutine, $hasargs, $wantarray, $evaltext, $is_require, $hints, $bitmask) = caller(0); print "package = [${package}]\n" if defined($package); print "filename = [${filename}]\n" if defined($filename); print "line = [${line}]\n" if defined($line); print "subroutine = [${subroutine}]\n" if defined($subroutine); print "hasargs = [${hasargs}]\n" if defined($hasargs); print "wantarray = [${wantarray}]\n" if defined($wantarray); print "evaltext = [${evaltext}]\n" if defined($evaltext); print "is_require = [${is_require}]\n" if defined($is_require); print "hints = [${hints}]\n" if defined($hints); print "bitmask = [${bitmask}]\n" if defined($bitmask); print '__FILE__ = [', __FILE__, "]\n"; print '__PACKAGE__ = [', __PACKAGE__, "]\n"; } } Sample::whoami; print "\n--------------------------\n"; my ($package, $filename, $line) = caller; print "package = [${package}]\n" if defined($package); print "filename = [${filename}]\n" if defined($filename); print "line = [${line}]\n" if defined($line); print '__FILE__ = [', __FILE__, "]\n"; print '__PACKAGE__ = [', __PACKAGE__, "]\n";
実行例
C:\in_vitro\perl\basic>perl caller01.pl package = [main] filename = [caller01.pl] line = [29] subroutine = [Sample::whoami] hasargs = [1] hints = [2] bitmask = [UUUUUUUUUUUU] __FILE__ = [caller01.pl] __PACKAGE__ = [Sample] -------------------------- __FILE__ = [caller01.pl] __PACKAGE__ = [main]
PerlでのOOPの基本。
#!/usr/bin/perl use strict; use warnings; use Test::More qw(no_plan); # サンプルなので"no_plan"で手抜き。 { package Animal; sub new { my $class = shift; my $self = {}; print "in '$class' constructor...\n"; bless ($self, $class); return $self; } sub speak { my $class = shift; print "in '$class' speak method...\n"; print "a $class goes ", $class->sound, "!\n"; } } { package Mouse; @Mouse::ISA = qw(Animal); sub sound { "squeak" } sub speak { my $class = shift; #$class->Animal::speak($class); $class->SUPER::speak($class); print "[but you can barely hear it!]\n"; } } $main::obj = Mouse->new(); $main::obj->speak(); isa_ok($main::obj, 'Animal'); isa_ok($main::obj, 'Mouse'); isnt(UNIVERSAL::isa($main::obj, "Horse"), 0); can_ok($main::obj, qw(speak sound)); isnt(UNIVERSAL::can($main::obj, 'hoge'), 0);
実行結果
DOS> perl class01.pl in 'Mouse' constructor... in 'Mouse=HASH(0x284fd4)' speak method... a Mouse=HASH(0x284fd4) goes squeak! [but you can barely hear it!] ok 1 - The object isa Animal ok 2 - The object isa Mouse ok 3 ok 4 - Mouse->can(...) ok 5 1..5
PerlでのOOPの基本原理は変わりませんが、より分かりやすい書き方をサポートする為のCPANの主流が時代と共に変わるので厄介です。
上に挙げたコードはあくまでも基本原理の中核部分で、一番簡単なサンプルです。
「見るがいい、
Perl"世界(ザ・ワールド)" の力を。
真に世界を支配する力だということを!!」
by ディオ・ブランドー,「ジョジョの奇妙な冒険」第三部
本来はPOD(Plain Old Document)として使う機能。
=(label) ... =cut
とすることで、複数行をコメントアウトできる。
後ろの=以降に適切なコマンドを入れることにより、PODとして処理できる。
単にブロックコメントとして使いたい場合は、(label)の箇所は適当でよい。
Perlのsyntaxには switch は存在しない。 5.8以上であれば Core Module で use Switch; が使用できる。それ未満の場合、次のperldocに記されているように何種類かの逃げ道を利用できる。
以下はWin2k/XP用。
以上。
この記事を書いている時点ではLinux/UNIX専用の技です。(Tcl/TkがXWindowsと通信できる環境が必要)
Devel::ptkdbというCPANモジュール(Tkモジュールが必要)を使うと、グラフィカルにPerlスクリプトをデバッグできます。
以下のようなオプションでTkで構築されたGUIデバッガが起動します。
$ perl -d:ptkdb ./foo.pl arg1 arg2 ... argN