« 2005年12月 | メイン | 2006年03月 »

2006年01月10日

C-0.02 バージョンアップ

Kazuho@Cybozu Labs: C-0.02

C-0.02 をリリースします。... このバージョンでは、以下のような機能が追加になりました。 -m オプション: デバッガのサポート: man の追加: #option ディレクティブ ...

ということで、RPMパッケージを更新しました。

Red Hat系Linuxならバージョンアップ一発です。

# rpm -Uvh http://takesako.31tools.com/redhat/RPMS/noarch/C-0.02-0.noarch.rpm

ちなみに、Plamo Linux/Slackware なら rpm2tgz した後に installpkg でインストール
Debian GNU/Linux なら alien で .deb パッケージに変換してインストールすることができるみたいです。

将来のバージョンではコンパイル結果のキャッシングとかができるようになると理想ですね。

■追記(C-0.03 バージョンアップしました)

それでは have fun !

2006年01月08日

未踏な仲間たち新年会

1/7(土)にIPA未踏プロジェクトOBの方を中心とした新年会に参加してきました。そこでゲットした戦利品。

FPGA_Gijutsu_2.jpg

試作機の写真はこちら

どう見てもハードコアバイナリアン向けの同人誌です。本当にありがとうございました。

2006年01月06日

#!/usr/bin/C でワンライナーを書く

Kazuho@Cybozu Labs: C - a pseudo-interpreter of the C programming language

 Perl や Ruby では、ワンライナーで処理が書けて便利です。でも、なぜか C では書くことができません。仕事上の都合で、小さな処理を C 言語で書く必要があったので、ワンライナーも書くことのできる C 言語のインタプリタ(?)を作ってみました。

面白そうなので、早速RPMパッケージを作ってみました。

Red Hat系Linuxならインストールは以下のコマンド一発です。

# rpm -ivh http://takesako.31tools.com/redhat/RPMS/noarch/C-0.01-0.noarch.rpm

こんなことができるようになります。

[1] C言語でワンライナー:

C -e 'printf("hello world\n");'

[2] shebangでスクリプト実行:

#!/usr/bin/C
printf("hello world\n");

処理させる内容によってはPerlの約100倍早く動作することもあるようです。

半分ジョークプログラムみたいですが、いや、これ、実は結構便利かも。。。

まだ tarball が揃っていないソフトウェアなので、specファイルはこんな感じになりました。

Summary: C - a peudo-interpreter of the C programming language
Name: C
Version: 0.01
Release: 0
License: GPL
Group: Development/Languages
Source0: http://labs.cybozu.co.jp/blog/kazuho/archives/C
Source1: C.pod
URL: http://labs.cybozu.co.jp/blog/kazuhoatwork/
Vendor: Cybozu Labs, Inc.
Requires: perl, gcc
AutoReqProv: no
BuildArch: noarch
BuildRoot: %{_tmppath}/%{name}-%{version}-root
%description
C (pronounced large-C) is a pseudo-interpreter of 
the C programming language. 
Without the need of compilation, developers can rapidly 
create scripts or write one-liners using the C programming 
language that runs at the native-code speed.
%prep
%build
%install
%{__rm} -rf $RPM_BUILD_ROOT
%{__mkdir} -p -m 0755 $RPM_BUILD_ROOT%{_bindir}
%{__install} -m 0755 %{SOURCE0} $RPM_BUILD_ROOT%{_bindir}/C
%{__mkdir} -p -m 0755 $RPM_BUILD_ROOT%{_mandir}/man1
pod2man -s 1 -c "%{vendor}" -r "%{name}-%{version}" %{SOURCE1} \
 > $RPM_BUILD_ROOT%{_mandir}/man1/%{name}.1 
%{__chmod} 0644 $RPM_BUILD_ROOT%{_mandir}/man?/*
%clean
rm -rf $RPM_BUILD_ROOT
%files
%defattr(-,root,root)
%{_bindir}/C
%{_mandir}/man1/*
%changelog
* Fri Jan  6 2006 Cybozu Labs  0.01-0
- Initial package.

PODファイルから pod2man で man1 のファイルを生成しているのがミソです。

そういえば、たまにspecファイルの書き方/勉強の仕方を聞かれることがあるのですが、紹介しやすい参考文献ってあまりないですよね。他人の(ディストリビュータが)書いたspecファイルを参考にするのが早いけど、変な癖がつくし。お勧めできるものとしては、ちょっと古いですが、Maximum RPM13. Inside the Spec Fileあたりでしょうか。

■追記(2006-01-07)

Plamo Linux/TOWNS の nmaruichi さんから動作報告をいただきました。ありがとうございます。



RPMバイナリを Plamo Linux の rpm2tgz で変換することでインストールできました。

以下の100万回の単純なループで bash と比較すると 100 倍位になりました。
この /usr/bin/C って面白いですね。(変な比較をしてすいません)

bash-3.00# time C -e 'int counter;for(counter=0;counter<1000000;++counter) printf("%d\n", counter);' >/dev/null

real 0m0.614s
user 0m0.610s
sys 0m0.010s
bash-3.00# time for((counter=0;counter<1000000;++counter)) do printf "%d\n", $counter ; done >/dev/null

real 0m59.351s
user 0m57.790s
sys 0m0.770s

ちなにみ先にダウンロードしたのは、ソースだったんですが『中身を見て「これを元にビルドスクリプト」を書くのは、さらに意味が無いな…』って思ったので rpm2tgz にしたと言うのが、実際です。
まぁ、RPMバイナリが noarch だったんでなんとなくよめてました。


■追記(2006-01-09) /usr/bin/C をデバッガ(gdb)経由での使用

nmaruichiさんがブログのコメントにうまく書き込めなかったみたいなので原文を追記。

/usr/bin/C に実行ファイルを呼び出す段階で gdb 経由で呼び出すように修正し
たコマンド "C.gdb" をつくって試してみました。
# なお、コマンド内で indent を使用しているのは、コンパイル前に成形してお
いた方が分かりやすいかと思ったためです。
----
$ C.gdb -c'g' -e "`echo 'int
counter;for(counter=0;counter<10;++counter)printf("%d\n", counter)' |
indent -kr`"
GNU gdb 6.1.1
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i586-pc-linux"...Using host libthread_db
library "/lib/libthread_db.so.1".
(gdb) list
1 #include 
2 #include 
3
4
5 int main(int argc, char** argv)
6 {
7 #line 1
8 int counter;
9 for (counter = 0; counter < 10; ++counter)
10 printf("%d\n", counter);
(gdb) list
11 return 0;
12 }
(gdb) break 8
No line 8 in file "/tmp/filedCHG4R.c".
(gdb) run
Starting program: /tmp/filedCHG4R
0
1
2
3
4
5
6
7
8
9
Program exited normally.
----
上記のテスト結果では、ブレークポイントを設定しているにも
係わらず。機能していないようです。
それで、list 表示の中にある #line のプリプロセッサが良く
分からないので、省くために /usr/bin/C.gdb から取り除いて
みました。
修正済みのもので試すと。
----
$ C.gdb -c'g' -e "`echo 'int
counter;for(counter=0;counter<10;++counter)printf("%d\n", counter)' |
indent -kr`"
GNU gdb 6.1.1
Copyright 2004 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i586-pc-linux"...Using host libthread_db
library "/lib/libthread_db.so.1".
(gdb) list
1 #include 
2 #include 
3
4
5 int main(int argc, char** argv)
6 {
7 int counter;
8 for (counter = 0; counter < 10; ++counter)
9 printf("%d\n", counter);
10 return 0;
(gdb) list
11 }
(gdb) break 7
Breakpoint 1 at 0x8048338: file /tmp/file9CUgWl.c, line 7.
(gdb) run
Starting program: /tmp/file9CUgWl
Breakpoint 1, main (argc=1, argv=0xbffff834) at /tmp/file9CUgWl.c:8
8 for (counter = 0; counter < 10; ++counter)
(gdb) step
9 printf("%d\n", counter);
(gdb) step
0
8 for (counter = 0; counter < 10; ++counter)
----
この場合は、上記のようにブレークポイントも正常に動きました。
この「#line 1」の行は必要なのでしょうか?
この行があると無いとでは、gcc -E でプリプロセッサの処理を通したソース
コードにも違いが見られます。
なお、「#line 1」を省いた C.gdb にするための差分を以下のよう
にして
$ diff -u C{,.gdb} | gzip -c | uuencode -m C.gdb.diff.gz.uuencode
固めたものを載せておきます。
begin-base64 644 C.gdb.diff.gz.uuencode
H4sIAKEDwEMAA32RXW+CMBSGr9df8Qa3BOUjxfmBIozFi93vYldLDJaKTaAS
KItm2X9fQdRsS9YL2tPnHN5z3jqOg/XdmNKZQz2HzjCmS2++fJy69LJg0QWl
xLIsrN0s3d6yfdDxckKXk9mf7DiGMx3bM1j66yOOCQiKE+7rim0UP6rgHB4a
tdmJnCOEKkqZFOYwINagY/zI2YYVqWbXPA1/obqshFQ709Ct4aE27FvyMLhp
9iLGFbrM6LGQLG9SXrd40AdY1SoVB3cfvcsfd7nYdpd9cZwxtjmUqg66kRe+
PYflUaonP8+se0ORCGm2h6TKmA22T6rRqA0+hgSfxBnkQnJ4BO26OnQOK66a
SoJqua9OwvPOGt5Cb60GPwpl3j8hiuAPIXbQ51UYdSUEA7ReNYoTpz7Vihfm
1QEb8fPry1tr+AVdfL0hsJwnsinbd0EqOIxdomtTqMPlz1B7joxLXiVKg62Q
SXXSDvW9hCG84N82vwGKFyuXhQIAAA==
====
上記の部分を「cat > C.gdb.diff.gz.uuencode」などとして(ペーストすること
で)ファイルに保存して以下のコマンドで取り出すことが出来ます。
$ uudecode C.gdb.diff.gz.uuencode
$ gzip -cd C.gdb.diff.gz