2010-11-25

MacBook Air 環境構築まとめ 追記

virtualboxの仮想環境についてちょっと設定が必要だったのでメモ


http://taksatou.blogspot.com/2010/11/macbook-air.html


仮想環境に対してSSH接続するにはvertualboxの設定からネットワークアダプタにブリッジアダプタを追加する必要がある。
そうしないと、ホスト側とアダプタを共有してしまうらしく、ゲストOS側にIPが割りあてられないみたい




ゲストOS側はubuntuがうまくやってくれるみたいでなにもしなくてOK

::

2010-11-24

MacBook Air 環境構築まとめ

MacBook Airを購入したら環境をさらすのが流行ってるみたいなので便乗です。
macは完全に初心者なのでいろんな所を参考にしつつとりあえずいれてみた。


- Xcode http://developer.apple.com/technologies/tools/xcode.html
開発者ならとりあえずいれておくらしい。

- iTerm http://iterm.sourceforge.net/
標準で付属しているTerminalだと256色が変だったのでこっちをつかうことにした。

- virtualbox http://www.virtualbox.org/
- ubuntu http://www.ubuntulinux.jp/products/JA-Localized/virtualbox
手元の環境は汚さずに仮想環境で開発するのがモダン。
VirtualBox用の仮想マシンイメージが配布されている。ただダウンロードしてvirtualboxを起動するだけ。
何もせずとも音もなるしバッテリ残量までわかる。youtubeもHD画質を要求しなければ余裕。

- AquaSKK http://aquaskk.sourceforge.jp/
mac移行ついでにIMEも移行する。

- FireFoxとか
各種ブラウザはとりあえずいれておく。
windowsからの移行はFEBEをつかった。
https://addons.mozilla.org/ja/firefox/addon/2109/

- passwordchest http://www.ohloh.net/p/passwordchest
シンプルなパスワードマネージャ。
個人的には絶妙な使用感。

- inputswitcher
いれてはみたけど端末に入力するときは英字モードにすればいいだけなのであまり必要性はなかった。

- eclipse
topcoderのSRMをやるのに便利。
日本語化するにはPleiadesをおとしてきて自分でPluginディレクトリとかコピーする必要がある。



さらに、CUI環境を充実させるために以下を行った。

- ddskk
AquaSKKだけだと端末入力時に不都合があるので。

- screen
macに標準で付属してるscreenは256color対応していないので自前でビルド。
本家のソースのままだとビルドできないので下記を参考にパッチをあてる。
http://writequit.org/blog/?p=183

configureは以下
./configure --enable-colors256 --prefix=~/Users/`whoami`/Documents/install --enable-rxvt_osc

自前ビルドしたバイナリは別のところにいれるようにすると安心感が得られる

- sudo sysctl -w net.inet.tcp.always_keepalive=1
公衆無線LANをつかってたら、ちょっと無操作なだけてすぐ接続がきれて不便だったので、これを設定してみたら治った。
微妙に不都合な時もありそうな気もするけど深く考えないことにする。

- zshrcとか
PATHとかを環境によって切りかえやすくするために、.zshrcに以下をかいて環境依存の設定は切り分ける。

[ -f ~/.zshrc.include ] && source ~/.zshrc.include

.zshrc.includeの本体は
work/git/local/dev/conf/.zshrc.include.air
とかのシンボリックリンクにしておく。
設定ファイルの実体はバージョン管理してるディレクトリにおいて、ホームディレクトリにはシンボリックリンクをおいておくと管理が楽だということに最近きづいた。

- .emacsとか
.zshrcと同様に切り替えやすさのためにかきかえた。
.emacsに直接設定を書くのではなく、以下のようにしてrequireするのがよさげ。
(require 'my-keybind)
(require 'my-emacs)
(require 'my-skk)
(require 'my-coding)

::

2010-10-20

makeでちょっと便利なメタプログラミング

GNU Make 第3版を見てたら、マクロとevalを使ってちょっと便利でおもしろいことができることに気づいた。

とりあえず例を書くとこんな感じ。
rules = foo bar baz

define def-rule
$1:
 @echo $1
endef

$(foreach i, $(rules), $(eval $(call def-rule, $i)))

マクロとevalを使えば動的にルールを生成できるのだ。
これだけでfoo bar bazの三つのルールがつかえるようになる。
便利!

これを使えばサブコマンドを受け付けるコマンドを使うルールを定義したい時とか、複数のディレクトリに対して処理を行いたい時に妥協したシェルスクリプトを書く割合が減る気がする。

ただし、マクロの中は二重に評価されてしまうので、makeの自動変数やfor文、シェル変数を使いたい時は$の個数に注意が必要
rules = foo bar baz

define def-rule
$1:
 @for i in foo*; \
 do \
 echo $$$$$$$$; \
 echo $$$$i; \
 echo $$@; \
 echo $1; \
 done
endef

$(foreach i, $(rules), $(eval $(call def-rule, $i)))
これはきもい

(※ $$はそのコマンドのpidを返すシェル変数。$@はそのルールのターゲット名を表すmakeの自動変数)


2010-07-04

debian 64bitで32bitバイナリをビルドするメモ

64bit debianのgccでCプログラムをビルドするとデフォルトで64bitになる。

gccで32bitバイナリを作りたい時はgcc-multilib(C++の場合は、g++-multilib) を入れる

% sudo apt-get install gcc-4.1-multilib

として

% cc -m32 example.c

でOK

% objdump -p a.out | grep format
a.out:     file format elf32-i386
http://blog.gnu-designs.com/fix-for-incompatible-libstdc-error-message

2010-06-27

ddclientメモ

以前から使っていたDiCEではここ最近になってなぜかIPの更新ができなくなってしまったので、DynDNS.comの説明を参考にしてddclientを導入した。

ダイナミックDNSサービスはDynDNSを利用
https://www.dyndns.com/

IPアドレス更新クライアントについて
https://www.dyndns.com/support/clients/

Linux / UNIX Update Clients
https://www.dyndns.com/support/clients/unix.html


上側に書いてあったのでddclientを採用。
主要なOSのバイナリは配布されている。
debianなら導入はapt-getでも可。


DynDNSを使っていれば設定ファイルは以下から自動で生成できる
https://www.dyndns.com/support/tools/clientconfig.html

なかみはこんな感じ

## ddclient configuration file
daemon=600
# check every 600 seconds
syslog=yes
# log update msgs to syslog
mail-failure=メールアドレス # Mail failed updates to user
pid=/var/run/ddclient.pid
# record PID in file.
## Detect IP with our CheckIP server
use=web, web=checkip.dyndns.com/, web-skip='IP Address'
## DynDNS username and password here
login=ログイン名
password=パスワード
## Default options
protocol=dyndns2
server=members.dyndns.org
## Dynamic DNS hosts
ホスト名

/etc/ddclient.confに書いて、/etc/init.d/ddclient restart で完了

libmemcachedについてるlibhashkitであそぶ

libmemcachedにlibhashkitなんていう便利そうなライブラリがついていたので、各種ハッシュアルゴリズムの特性を調べてみた。
http://libmemcached.org/libMemcached.html

libhashkitでつかえるアルゴリズムは以下の通り。(libhashkit/types.h参照)
それぞれのアルゴリズムの説明は検索すればでてくるので省略。
  • HASHKIT_HASH_MD5,
  • HASHKIT_HASH_CRC,
  • HASHKIT_HASH_FNV1_64,
  • HASHKIT_HASH_FNV1A_64,
  • HASHKIT_HASH_FNV1_32,
  • HASHKIT_HASH_FNV1A_32,
  • HASHKIT_HASH_HSIEH,
  • HASHKIT_HASH_MURMUR,
  • HASHKIT_HASH_JENKINS,


テスト方法は、互いに異なる文字列のdigest値をそれぞれ計算して、conflictが発生したかどうか、標準偏差、値の分布のヒストグラムをダンプするだけ。

作成したコードは以下の通り。
#include <boost/lambda/lambda.hpp>
#include <boost/lambda/bind.hpp>

#include <libhashkit/hashkit.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stdlib.h>
#include <math.h>

using namespace std;

//#define TEST_RAND
#define TEST_CASES 10000
#define LETTER_NUM 62
static char letters[LETTER_NUM+1] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

static string rand_str(int len, unsigned int seed) {
    char buf[len+1];
    
    srand(seed + 1);
    for (int i = 0; i < len; i++) {
        buf[i] = letters[(int)((double)LETTER_NUM * rand() / (RAND_MAX + 1.0))];
    }
    buf[len] = '\0';
    return string(buf);
}

static set<string> rand_strings;

static void gen_rand_strings(int n)
{
    rand_strings.erase(rand_strings.begin(), rand_strings.end());
    
    for (int i = 0; i < n; ++i) {
        string s = rand_str(10, i);
        
        if (!rand_strings.insert(s).second) {
            cerr << "<" << s << "> is known!" << endl;
            ++n;
        }
    }
}
    
 

class TestHash {
private:
    multiset<uint32_t> results;
    Hashkit h;
    hashkit_hash_algorithm_t hash_type;
    int cases;

    void init(void) {
        results.erase(results.begin(), results.end());
    }
    
public:
    TestHash(int n, hashkit_hash_algorithm_t t) : cases(n), hash_type(t) {
        h.set_function(t);
    }
    
    void byRand(void) {
        init();
        
        for (set<string>::iterator it = rand_strings.begin(); it != rand_strings.end(); ++it) {
            string s = *it;
            results.insert(h.digest(s));
        }
    }
    
    void bySeq(void) {
        init();
        char buf[256];
        
        for (int i = 0; i < cases; ++i) {
            snprintf(buf, 256, "%010d", i);
            string s(buf);
            results.insert(h.digest(s));
        }
    }


    int conflict(void) {
        uint32_t last = -1;
        int c = 0;
        
        for (multiset<uint32_t>::iterator it = results.begin(); it != results.end(); ++it) {
            if (last == *it)
                ++c;
            last = *it;
        }
        return c;
    }

    double average(void) {        
        double sum = 0.0;

        for_each(results.begin(), results.end(), sum += boost::lambda::_1);
        return sum / cases;
    }

    double variance() {
        double avr = average();
        double sum = 0.0;

        for_each(results.begin(), results.end(), sum += bind(pow, avr - boost::lambda::_1, 2));
        return sum / cases;
    }

    double deviation(void) {
        return sqrt(variance());
    }

    vector<int> histogram(int n) {
        uint32_t max = *max_element(results.begin(), results.end());
        vector<int> ret;

        ret.assign(n+1, 0);
        for (multiset<uint32_t>::iterator it = results.begin(); it != results.end(); ++it) {
            ret[(int)((double) *it * n / max)] += 1;
        }
        ret.pop_back(); // remove max element
        return ret;
    }
    
    void dump(void) {
        cout << "conflict: " << conflict() << endl;
        //        cout << "average: " << average() << endl;
        //        cout << "variance: " << variance() << endl;
        cout << "deviation: " << (long)deviation() << endl;
        vector<int> ret = histogram(10);
        cout << "histogram: " << endl;
        for_each(ret.begin(), ret.end(), cout << boost::lambda::_1 << "\n");
    }

};

void exec_test(pair<hashkit_hash_algorithm_t, string> info)
{
    TestHash test(TEST_CASES, info.first);

    cout << ">>" << info.second << endl;
#ifdef TEST_RAND
    test.byRand();
    test.dump();
#else
    test.bySeq();
    test.dump();
#endif
    cout << endl;;

}

int main(void)
{
    map<hashkit_hash_algorithm_t, string> types;

    types.insert(make_pair(HASHKIT_HASH_MD5, "HASHKIT_HASH_MD5"));
//     types.insert(make_pair(HASHKIT_HASH_CRC, "HASHKIT_HASH_CRC"));
    types.insert(make_pair(HASHKIT_HASH_FNV1_64, "HASHKIT_HASH_FNV1_64"));
//     types.insert(make_pair(HASHKIT_HASH_FNV1A_64, "HASHKIT_HASH_FNV1A_64"));
//     types.insert(make_pair(HASHKIT_HASH_FNV1_32, "HASHKIT_HASH_FNV1_32"));
//     types.insert(make_pair(HASHKIT_HASH_FNV1A_32, "HASHKIT_HASH_FNV1A_32"));
    types.insert(make_pair(HASHKIT_HASH_HSIEH, "HASHKIT_HASH_HSIEH"));
    types.insert(make_pair(HASHKIT_HASH_MURMUR, "HASHKIT_HASH_MURMUR"));
    types.insert(make_pair(HASHKIT_HASH_JENKINS, "HASHKIT_HASH_JENKIN"));
    gen_rand_strings(TEST_CASES);
    
    for_each(types.begin(), types.end(), bind(exec_test, boost::lambda::_1));
    return 0;
}



libmemcachedのバージョンは0.4.0、boostは1.34.1その他環境は以下の通り
% c++ -v
Using built-in specs.
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.3.2-1.1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --enable-shared --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --enable-nls --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3 --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --enable-mpfr --enable-cld --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.3.2 (Debian 4.3.2-1.1)
% uname -a
Linux chameleon 2.6.26-2-amd64 #1 SMP Thu Feb 11 00:59:32 UTC 2010 x86_64 GNU/Linux

ビルドは以下コマンド
c++ -lhashkit hash.cc



ランダム文字列(10文字)の場合。(データが長くなるので全部のアルゴリズムの結果は載せてません)
>>HASHKIT_HASH_MD5
conflict: 0
deviation: 1238971077
histogram:
1051
1004
1026
1028
1019
981
996
953
949
992

>>HASHKIT_HASH_FNV1_64
conflict: 0
deviation: 1243801177
histogram:
1027
977
1002
1020
995
985
976
988
1033
996

>>HASHKIT_HASH_HSIEH
conflict: 0
deviation: 1235906590
histogram:
945
1017
999
981
1034
1036
1002
954
1005
1026

>>HASHKIT_HASH_MURMUR
conflict: 0
deviation: 1238293295
histogram:
980
964
1008
958
1015
997
1004
1013
1069
991

>>HASHKIT_HASH_JENKIN
conflict: 0
deviation: 1236833209
histogram:
975
941
1028
1019
967
1028
966
1037
1002
1036


予想通りどのアルゴリズムもそれなりにきれいに分散しているように見える。
10万個程度までならほとんど衝突もない。


数字の場合。(e.g. 0000000001, 0000000002, ...)
>>HASHKIT_HASH_MD5
conflict: 0
deviation: 1242254142
histogram:
1046
985
1031
1072
974
1003
968
938
996
986

>>HASHKIT_HASH_FNV1_64
conflict: 0
deviation: 401256730
histogram:
0
0
0
0
0
0
4000
4000
0
1999

>>HASHKIT_HASH_HSIEH
conflict: 0
deviation: 1239810127
histogram:
1031
1029
1014
1032
1058
985
956
934
959
1001

>>HASHKIT_HASH_MURMUR
conflict: 0
deviation: 1238208481
histogram:
999
971
989
989
1005
1034
1000
987
1007
1018

>>HASHKIT_HASH_JENKIN
conflict: 0
deviation: 1223190204
histogram:
933
1014
1023
989
1052
1006
1006
1022
996
958


HASHKIT_HASH_FNV1_64の偏りがひどい。(衝突はしていない)
ほかのものはそれなりの性能を発揮しているように見える。


それぞれのアルゴリズムで衝突しやすいパターンをもっと探してみようと思ったけど疲れたのでまた今度。

2010-06-23

GoogleCLをdebianで試す

ちょっと便利そうなものがでてたので試してみました。

http://japan.cnet.com/news/service/story/0,3800104747,20415466,00.htm
http://code.google.com/p/googlecl/


まずプロジェクトページからダウンロード~普通にインストール

wget http://googlecl.googlecode.com/files/googlecl-0.9.7.tar.gz
tar xzf googlecl-0.9.7.tar.gz
cd googlecl-0.9.7
sudo python setup.py install


gdataが必要らしいので同様にインストール
http://code.google.com/p/gdata-python-client/


wget http://gdata-python-client.googlecode.com/files/gdata-2.0.10.tar.gz
tar xzf gdata-2.0.10.tar.gz
cd gdata-2.0.10
sudo python setup.py install


debianの場合は起動するpythonによって/usr/binにインストールされる場合と/usr/local/binになる場合があるので、エラーがでた場合は要確認。


ためしにbloggerにポストしてみます。
実際この記事は以下のコマンドでポストしました。

google blogger post --title "GoogleCLをdebianで試す" "`cat blog`"


複数ブログがある場合、このコマンドの後に番号で選択します。
なお、初回起動時はOAuthの認証が必要になります。
ブラウザがインストールされていれば自動で起動します。

設定をすればemacsとかでbloggerに投稿したりできるので便利です。

2010-06-21

bloggerのテンプレートの出し分けをする方法のメモ

bloggerのトップページと個別の記事ページでテンプレートの出し分けをしたくなったのでやり方をメモ。


<b:if cond='data:blog.pageType == "item"'>
foo
</b:if>

これでfooの部分が個別記事のなかでのみ有効になる

2010-06-05

AMQP関連の参考リンクまとめ

最近RabbitMQをよくいじっているので、参考にした記事などをまとめておきます。


RabbitMQとはerlangで実装されたAMQPの一つです。
http://www.rabbitmq.com/

概要をつかむには以下のスライドが参考になります。サンプルコードものってます。
http://www.slideshare.net/hungryblank/rabbitmq-with-python-and-ruby-rupy-2009

英語ですがこちらのブログ記事はチュートリアル的に書かれていてとても参考になりました
http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/

下記のブログでもRabbitMQ関連の記事がよくポストされてます。
http://somic.org/category/rabbitmq/

greeのエンジニアブログでも最近紹介されてました
http://labs.gree.jp/blog/2010/06/262/



各種言語にAMQPライブラリが用意されてるのでそれを使うのが便利です。

pythonなら知る限りでは3種類のライブラリがあります。
  • py-amqplib:http://code.google.com/p/py-amqplib/
    • シンプルに使うならこれで大体のことはできるはずです。
  • pika:http://github.com/tonyg/pika
    • RabbitMQの開発者がつくってるようです。
    • asyncなのとsyncなコネクションのアダプターがついてるのでこれを使えばどんなアプリケーションでも柔軟に対応できます。tornadoのioloopと組み合わせたりも簡単にできます。
  • txAMQP:https://launchpad.net/txamqp
    • twistedベースの実装。twistedは使ったことがないのでノーコメント。


rubyならgem、perlならcpanにあります。詳細は省略しますが、その他の言語でも大体用意されてるようです。
くわしくRabbitMQのドキュメントにあるのでそちらをどうぞ
http://www.rabbitmq.com/how.html



その他、メーリングリストでの議論

2010-04-18

debianの時計を合わせる

普通はOSをインストールした時にちゃんと設定されはずですが、どういう訳かシステムの時計がずれてきていたので設定方法をメモ。

時計を合わせるにはntpdateというパッケージを使います。
debianではntpdate-debianというコマンドが使えます。

$ sudo apt-get install ntpdate
$ sudo ntpdate-debian

これでNTPサーバに問い合わせて時計を合わせてくれます。
/etc/default/ntpdateファイルを編集すればNTPサーバを変更できます。

ついでにcrontabの設定もしておきます。

$ sudo crontab -e
0 0 1 * * ntpdate-debian

  

2010-04-17

OAuth Request Body HashをつかうためにOAuthクライアントを実装してみた時のメモ

OAuth Request Body Hashとは、OAuthの拡張仕様の一つです。
OAuth Coreではapplication/x-www-form-urlencodedなリクエストに対してのみ正当性を保証します。そのためPOSTでXMLを送信したいときなどには別の手段が必要になります。OAuth Request Body Hashは、そのようなnon-form-encodedなリクエストボディに対する正当性を保証するための仕組みです。
詳細は下記をどうぞ。
http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html
(oauth body hashでググるとドラフトがトップに出るようですが(2010-04-17現在)、Finalバージョンはすでにあがっているようです)

YahooのTech Blogも参考になります。
http://techblog.yahoo.co.jp/web/openid/oauth_1/


このoauth_body_hashなのですが、日本語の情報が少なく、今のところライブラリで対応しているものがあまり無いようなので自分で実装してみました。
せっかくなので2-legged OAuthでoauth_body_hashを使う場合のサンプルコードをさらしておきます。
<?php

$consumer_key = "consumer_key";
$consumer_secret = "consumer_secret";
$version = "1.0";
$timestamp = time();
$nonce = (string)rand();
$signature_method = "HMAC-SHA1";
$url = "http://example.com/";
$request_body = '<?xml version="1.0" encoding="utf-8"?><foo>bar</foo>';

$body_hash = urlencode(base64_encode(hash("SHA1", $request_body, true)));

$params = sprintf('oauth_body_hash=%s&oauth_consumer_key=%s&oauth_nonce=%s&oauth_signature_method=%s&oauth_timestamp=%d&oauth_version=%s',
                  $body_hash, $consumer_key, $nonce, $signature_method, $timestamp, $version);
$sbs = sprintf('POST&%s&%s', urlencode($url), urlencode($params));
$signature = urlencode(base64_encode(hash_hmac("SHA1", $sbs, $consumer_secret."&",  true)));
$auth_header = sprintf('OAuth oauth_body_hash="%s",oauth_consumer_key="%s",oauth_version="%s",oauth_timestamp="%d",oauth_nonce="%s",oauth_signature_method="%s",oauth_signature="%s',
                       $body_hash, $consumer_key, $version, $timestamp, $nonce, $signature_method, $signature);

$headers = array("Host: example.com",
                 "Accept: */*",
                 "Authorization: $auth_header",
                 "Content-Type: text/xml; charset=utf-8",
                 "Content-Length: ".strlen($request_body));

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $request_body);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_exec($ch);
curl_close($ch);


なお、PHPに限らずOAuthを自分で実装する時の注意点としては以下のような感じでしょうか

* oauth_body_hashの値はurlencodeした値です。signatureを計算する時はsignature base stringに組み込んだあともう一度urlencodeします。
* oauth_body_hashの計算に秘密鍵は必要ありません。つまりHMACではなく、単なるダイジェスト値です。
* base64 encodeの実装によっては末尾に改行を付加するものがありますが、改行は不要です。(PHPの場合は上記のサンプルと通りでOKですが、Javaのcom.sun.mail.util.BASE64EncoderStreamなどでは改行を付加するものがあるようです)
* timestampは秒までの整数値です。当然と言えば当然なのですが、なにも知らずに時間取得関数を使うとミリ秒まで返してくるものがあるので、はまると気づきにくいかもしれません。
* 2-legged OAuthの場合はaccess tokenが不要ですので、signatureを計算する時の秘密鍵はconsumer_secretに&をつけたものになります。
* signature base stringをつくるときのパラメータはアルファベット順にソートする必要があります。
* signature base string自体はurlencodeする必要はありません。urlencodeするのはURLとパラメータです。



参考:http://oauth.net/core/1.0/

2010-03-08

namespaceつきのPHP extensionをつくる

仕様についてはともかく、php 5.3 からnamespaceが使えるようになりました。
今のところPHPのソースに標準でついてるエクステンションでnamespaceを使っているものは無いようだったのでちょっと試してみました。


通常のnamespaceなしの場合との違いは一カ所だけです
zend_function_entry msgpack_functions[] = {
//    PHP_FE(hoge, NULL)  /* 通常の場合 */
    ZEND_NS_FE("myspace", hoge, NULL)
    {NULL, NULL, NULL}  /* Must be the last line in msgpack_functions[] */
};

PHP_FEの代わりにZEND_NS_FEを使うだけです。
他はそのままでOKです。

ソースファイル
PHP_FUNCTION(hoge)
{
    RETVAL_STRINGL("hoge", 5, 1);
}

ヘッダファイル
PHP_FUNCTION(hoge);


サンプル
<?php
print myspace\hoge();PHP_FUNCTION(hoge);

実行結果
$ php sample.php
hoge

ざっと見たところ、今のところエクステンションでクラスをnamespaceに入れるインターフェースは用意されてないようです。(自分でマクロを書けばできなくはなさそう)
また、一つのエクステンション内でnamespaceは複数つかえますが、namespaceが別でも同名の関数を定義するのは普通の方法では難しそうです。

2010-02-22

Protocol Buffersをビルド~リンクするメモ

Cの構造体のようなものをそのままシリアライズしたくなったのでProtocol Buffersを試してみようと思います。
http://code.google.com/intl/ja/apis/protocolbuffers/docs/overview.html

Protocol BuffersはまだDebianパッケージにはなってないようなのでソースからビルドします。
ソースは以下から
http://code.google.com/p/protobuf/downloads/list

とりあえず現在最新バージョンの2.3.0を落として普通にビルドしてみます。
wget http://protobuf.googlecode.com/files/protobuf-2.3.0.tar.gz
tar xzf protobuf-2.3.0.tar.gz
cd protobuf-2.3.0
./configure
make
make check
sudo make install

以上がうまくいっていれば、
protoc --version
でバージョンが表示されるはずですが、どうやらライブラリのリンクがうまくいかないようです。
% protoc --version
protoc: error while loading shared libraries: libprotobuf.so.6: cannot open shared object file: No such file or directory

ちなみに使用環境は、
% uname -a
Linux chameleon 2.6.26-2-amd64 #1 SMP Thu Feb 11 00:59:32 UTC 2010 x86_64 GNU/Linux

こんな時は、make install した時に表示される以下のようなメッセージ従ってリンク先のパスを設定します。
If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR'
flag during linking and do at least one of the following:
   - add LIBDIR to the `LD_LIBRARY_PATH' environment variable
     during execution
   - add LIBDIR to the `LD_RUN_PATH' environment variable
     during linking
   - use the `-Wl,-rpath -Wl,LIBDIR' linker flag
   - have your system administrator add LIBDIR to `/etc/ld.so.conf'

上の方法の他に/libにシンボリックリンクを張ったりでもたぶん大丈夫ですが、バイナリファイルにリンク情報を埋め込んでやる方が安全です。
(本来は/etc/ld.so.conf で設定されているはず。当環境では/usr/local/lib をみるようにすで設定されてたけど、なぜかリンクエラーになる。原因不明。)

リンク情報を埋め込むには、MakefileのLDFLAGSの行に以下のようにしてリンカオプションを渡してやります。
LDFLAGS = -Wl,-rpath,/usr/local/lib

ちなみに、Makefileは複数ありますが、編集するのは protobuf-2.3.0/src/Makefile だけでOKです。

LDFLAGSを設定したらsrc以下だけ再度ビルド、protobuf-2.3.0/src/.libs/ 以下に生成されているバイナリをobjdumpして正しいRPATHが入っていればOKです。
$ objdump -p .libs/protoc | grep RPATH
  RPATH       /usr/local/lib

再度インストールして、きちんとバージョンがでればOKです。
$ protoc --version
libprotoc 2.3.0

2010-02-21

Bloggerでfaviconとかを設定するメモ

なんとなくアイコンとかマスコットとか、見た目のイメージは重要だと思ったのでいろいろ変えてみました。

faviconの設定方法は旧Bloggerと現Bloggerによってテンプレートが違うのでやり方も異なるようです。
現Bloggerのテンプレートは単にheadタグの間においただけではデフォルトのアイコンに書き換えられてしまいます。

そこで、</b:skin> と </head> の間に

<link href="faviconのURL" rel="shortcut icon"></link>
<link href="faviconのURL" rel="icon"></link>

を書く必要があります。

faviconは下で探しました。
http://www.favicon.cc/?action=icon_list

ぴったりのアイコンとかマスコットを探すのはなかなか難しいですね。
とくにfaviconはあんまり凝ったのにするとなんか安っぽい感じになるし、根拠もなく文字ベースのアイコンを使っても結局なにをアピールしたいのかよく分からなくなってしまいます。


テンプレートはいろいろ試してみましたが、結局なるべくミニマルなのを探して自分でカスタマイズするのがベターという結論に達しました。
最初から完成しているテンプレートはカスタマイズがしにくいにので、いまいち愛着がわきづらいです。
ちなみにベースにしたテンプレートは以下から拾ってきました。
http://www.blogcrowds.com/resources/blogger-templates/

2010-02-20

Solarisで自動起動するプログラムを制御するメモ

KVMでSolarisが使えるようになったのはいいものの、X Windowが立ち上がっているとメモリの消費が激しくてもっさりした動作になってしまいます。
わざわざ仮想マシンでブラウザ使ったりすることもないので、X Windowはデフォルトで立ち上がってほしくありません。

Debianでは/etc/init.d/で制御できますが、SolarisではSMFという仕組みがあるようです。
http://sy2920.s151.xrea.com/solaris/smf.html

とりあえずsvcsコマンドでサービスの情報を見てみます。
$ svcs | head
STATE          STIME    FMRI
legacy_run      6:57:56 lrc:/etc/rc2_d/S20sysetup
legacy_run      6:57:57 lrc:/etc/rc2_d/S47pppd
legacy_run      6:57:57 lrc:/etc/rc2_d/S72autoinstall
legacy_run      6:57:57 lrc:/etc/rc2_d/S73cachefs_daemon
legacy_run      6:57:57 lrc:/etc/rc2_d/S81dodatadm_udaplt
legacy_run      6:57:57 lrc:/etc/rc2_d/S89PRESERVE
legacy_run      6:57:57 lrc:/etc/rc2_d/S98deallocate
disabled        6:55:22 svc:/system/xvm/ipagent:default
online          6:54:44 svc:/system/svc/restarter:default
 今回無効にしたいのはX Windowですが、親プロセスの名前が分からないのでpstreeをしてみます。
 |-+- 01059 root /usr/sbin/gdm-binary
 | \-+- 01060 root /usr/sbin/gdm-binary
 |   |--- 01081 root /usr/openwin/bin/fbconsole -n -d :0
 |   |--- 01061 root /usr/X11/bin/Xorg :0 -depth 24 -nolisten tcp -audit 0 -br
 |   \--- 01084 gdm /usr/lib/gdmgreeter
どうやらgdmなんとか、というサービスを殺せば良いようです。
$ svcs -l gdm
fmri         svc:/application/graphical-login/gdm:default
name         GNOME Display Manager
enabled      true
state        online
next_state   none
state_time   2010年02月20日 07時55分03秒
logfile      /var/svc/log/application-graphical-login-gdm:default.log
restarter    svc:/system/svc/restarter:default
contract_id  100
dependency   require_all/none svc:/system/filesystem/local (online)
dependency   require_all/error svc:/milestone/multi-user:default (online)
dependency   require_all/none svc:/milestone/sysconfig (online)
dependency   optional_all/none svc:/system/xvm/vnc-config (online)
dependency   require_all/none svc:/application/font/fc-cache (online)
dependency   require_all/none svc:/system/utmp (online)
dependency   require_all/none svc:/system/hal (online)
dependency   optional_all/none svc:/application/opengl/ogl-select (online)
dependency   optional_all/none svc:/application/desktop-cache/mime-types-cache (online)
dependency   optional_all/none svc:/application/desktop-cache/desktop-mime-cache (online)
dependency   optional_all/none svc:/application/desktop-cache/pixbuf-loaders-installer (online)
dependency   optional_all/none svc:/application/desktop-cache/icon-cache (online)
dependency   optional_all/none svc:/application/desktop-cache/gconf-cache (online)
dependency   optional_all/none svc:/application/desktop-cache/input-method-cache (online)


svcadmでgdmをdisableします。
$ sudo svcadm disable gdm

きれいにX Windowが死にました。
ちなみに使っているSolarisのバージョンではデフォルトでプロセス監視デーモンが起動しているみたいで、単にgdmをkillしただけでは、自動的に再起動がかかってしまいます。

Linux(Debian Lenny) KVMの仮想マシン用ネットワーク設定

前回KVMでOpenSolarisをセットアップしましたが、ネットワーク設定については省略していたので一応メモしておきます。

とは言っても基本的にはここに書いてあるとおりにすればOKです。
http://www.howtoforge.com/virtualization-with-kvm-on-a-debian-lenny-server


ネットワーク設定は、Debianの場合は/etc/network/interfaces ファイルを編集して行います。たぶんUbuntuでも同様です。
参考までに設定内容をさらしておきます。

# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
auto eth0
iface eth0 inet manual

auto virbr0
iface virbr0 inet static
   address 192.168.1.50
   network 192.168.1.0
   netmask 255.255.255.0
   broadcast 192.168.1.255
   gateway 192.168.1.1
   bridge_ports eth0
   bridge_fd 9
   bridge_hello 2
   bridge_maxage 12
   bridge_stp offk

 仮想マシンを作成する際に、ネットワーク接続設定で共有物理装置を選択してここの設定で作成したブリッジを使用するようにします。
また、親機はLANで192.168.1.50にIP固定してますが、仮想マシンの方でもIPを固定したい場合は仮想マシン側で設定する必要があります。
最近のほとんどのOSではインストール時にデフォルトでDHCPが使われるので、IP固定する必要が無い場合は仮想マシン側で特に設定する必要はありません。

上記の設定をして、
% sudo /etc/init.d/networking restart

として、ifconfigすればvirbr0が追加されているのが確認できます。
% sudo ifconfig
eth0      Link encap:イーサネット  ハードウェアアドレス 00:1b:fc:b5:d7:16
          inet6アドレス: fe80::21b:fcff:feb5:d716/64 範囲:リンク
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:2941586 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:4429749 エラー:0 損失:0 オーバラン:0 キャリア:0
      衝突(Collisions):0 TXキュー長:1000
          RXバイト:783148810 (746.8 MiB)  TXバイト:5767081060 (5.3 GiB)
          割り込み:254 ベースアドレス:0x4000

lo        Link encap:ローカルループバック
          inetアドレス:127.0.0.1 マスク:255.0.0.0
          inet6アドレス: ::1/128 範囲:ホスト
          UP LOOPBACK RUNNING  MTU:16436  メトリック:1
          RXパケット:97752 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:97752 エラー:0 損失:0 オーバラン:0 キャリア:0
      衝突(Collisions):0 TXキュー長:0
          RXバイト:131654783 (125.5 MiB)  TXバイト:131654783 (125.5 MiB)

virbr0    Link encap:イーサネット  ハードウェアアドレス 00:1b:fc:b5:d7:16
          inetアドレス:192.168.1.50 ブロードキャスト:192.168.1.255  マスク:255.255.255.0
          inet6アドレス: 2001:c90:1440:3692:21b:fcff:feb5:d716/64 範囲:グローバル
          inet6アドレス: fe80::21b:fcff:feb5:d716/64 範囲:リンク
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:2638912 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:4277438 エラー:0 損失:0 オーバラン:0 キャリア:0
      衝突(Collisions):0 TXキュー長:0
          RXバイト:271638921 (259.0 MiB)  TXバイト:5737162576 (5.3 GiB)

ここで仮想マシンを立ち上げると、以下のように vnet が追加されていきます。
vnet0     Link encap:イーサネット  ハードウェアアドレス 00:ff:ea:f3:9d:56
          inet6アドレス: fe80::2ff:eaff:fef3:9d56/64 範囲:リンク
          UP BROADCAST RUNNING MULTICAST  MTU:1500  メトリック:1
          RXパケット:64 エラー:0 損失:0 オーバラン:0 フレーム:0
          TXパケット:306 エラー:0 損失:0 オーバラン:0 キャリア:0
      衝突(Collisions):0 TXキュー長:500
          RXバイト:7259 (7.0 KiB)  TXバイト:59290 (57.9 KiB)
以上で設定は終わりです。
一応仮想マシン側の方も確認してみます
$ ifconfig -a
lo0: flags=2001000849 mtu 8232 index 1
        inet 127.0.0.1 netmask ff000000
rtls0: flags=1004843 mtu 1500 index 2
        inet 192.168.1.15 netmask ffffff00 broadcast 192.168.1.255
lo0: flags=2002000849 mtu 8252 index 1
        inet6 ::1/128
rtls0: flags=2000841 mtu 1500 index 2
        inet6 fe80::5652:ff:fe34:e14/10
rtls0:1: flags=2080841 mtu 1500 index 2
        inet6 2001:c90:1440:3692:5652:ff:fe34:e14/64

こまかい内容はよく分かりませんが、とりあえずDHCPで192.168.1.15が割り当てられているようです。

2010-02-14

Linux(Debian Lenny)のKVMでOpenSolarisを動かすメモ

前回、仮想環境について調査を行った結果(http://taksatou.blogspot.com/2010/02/virtualbox-vs-vmware-vs-kvm-on-linux.html )KVMが良さそうだったので、実際に導入してみました。

当初はCUIだけで行くつもりでしたが、virt-managerを使えば簡単にできそうだったし、仮想環境をインストールしたときの感動が欲しかったのでGUIでやることにしました。

参考:http://wiki.debian.org/KVM#Lenny
http://www.linux-kvm.org/page/HOWTO1
http://www.howtoforge.com/virtualization-with-kvm-on-a-debian-lenny-server

今回利用した環境は以下です。KVMをフルで利用するにはそれなりに新しいバージョンのカーネルが必要なようです。少なくとも2.6.18以上である方が良いようです。(http://www.linux-kvm.org/page/Choose_the_right_kvm_%26_kernel_version)
% uname -a
Linux chameleon 2.6.26-2-amd64 #1 SMP Wed Aug 19 22:33:18 UTC 2009 x86_64 GNU/Linux

また、CPUのハードウェアの仮想化もサポートしている必要があります
egrep '(vmx|svm)' --color=always /proc/cpuinfo
でvmxかsvmが見つかればOKです。

以上問題なければパッケージをインストールします。
sudo aptitude install kvm virt-manager
今回はGUIのマネージャーを使ってみようと思うので、virt-managerをインストールします。硬派にCUIだけで行きたい人は代わりにlibvirt-binをインストールします。(virt-managerをインストールすればlibvirt-binもインストールされます)


バーチャルマシンを一般ユーザ権限で動かすためにユーザグループに追加します。
sudo adduser `id -un` libvirt
(グループを追加したら一旦ログインし直す必要があります。)

ここで、ちゃんとKVMがインストールできたか確認してみます。
% virsh -c qemu:///system list
virsh Id Name State
----------------------------------

うまくできていればこのように表示されるはずです。
ここまでできればあとはGUIでほぼすべてできます。

まずコンソールからvirt-managerを起動します。
% virt-manager

すると仮想マシンマネージャーというウィンドウが立ち上がります。
日本語化されてるので雰囲気で大体分かると思いますが、以下のような手順で設定します。WindowsのVirtualPCとかとほぼ同様なはずです。



新規をクリックします。


名前をつけます。


細かいことはよく分かりませんが、完全仮想化しか選択できないようになってました。
今回はKVMを使いますが、QEMUをつかえばSPARCとかPPCも使えます。


インストール方法を選択します。今回はディスクイメージから入れます。


ディスクイメージのファイルパスを設定するか、インストールメディアを挿入します


ストレージファイルの割り当てサイズと置く場所を決めます。
とりあえず8Gで、「今、仮想ディスク全体を割り当てますか?」というチェッ クは外しておきました。


ネットワーク設定をします


メモリとCPU割り当てを決めます。後からでも変えられるのでとりあえずデフォルトでいきます。


確認して完了を押します


新しくできた仮想マシンを開きます


LinuxでSolarisが動いています。

簡単ですね。

VirtualBox vs VMware vs KVM on Linux

自宅の開発環境を仮想化したくなってきたので仮想化技術について調査を行いました。

まず仮想化技術一般については下を参照。
http://itpro.nikkeibp.co.jp/article/lecture/20061228/258010/
http://www.atmarkit.co.jp/flinux/rensai/kvm01/kvm01a.html

今回仮想化するにあたっての条件は、
  • Linux(Debian Lenny)上で動く
  • 導入が楽
  • デスクトップ環境は不要
です。というわけで主に以下の3つを調べることにしました。
  • VMware Server
  • VirtualBox
  • KVM

検索してみたらこれらについて実際にベンチマークをとった人がいたようです。
http://forum.virtualbox.org/viewtopic.php?f=1&t=21314&sid=627b4d97f3252a9fe8813305c6f072d3
http://ezjd.blogspot.com/2009/08/virtualbox-vs-vmware-server-vs-kvm-part.html

ここらへんにのってるのは半年ほど前の情報ですが、
ざっとまとめると
  • 速さ:KVM>VMware Server≒VirtualBox
  • 安定性:VMware Server≒VirtualBox>KVM
  • ゲストOS上のクロックは高負荷時にずれることがあるので、測定結果はあまり信用しない方がいい
という感じっぽいです。

また、便利さという観点からみると調べた限りでは以下のような感じでした。
  • VirtualBoxのドキュメントはなかなか良いっぽい
  • VMware ServerのDebianパッケージはないけどVirtualBoxとKVMはある

以上を総合的に考えるとVirtualBoxのポイントが若干高いですが、デスクトップ環境は別にいらないし、速いほうがうれしいのでKVMを導入することに決めました。

2010-02-01

あえて自分に不快感を与えることで作業効率を上げるLifehack - zsh プロンプト編 -


作業をしているとついつい時間を忘れてしまいがちです。
特に深夜に作業をしている時は、気づいたら明け方だったなんてことはよくあります。

体力的にも精神的にも深夜の作業はよくありません。
そんな深夜の作業を避けるためにはどうしたらよいでしょうか?

答えは簡単です。
深夜になると作業が不快になる仕組みをつくればばよいのです。
そうすれば必然的にモチベーションが下がってあきらめムードになります。
朝起きてやろうという意志がでてくるはずです。

どういうときに作業が不快になるかというと、シェルやエディタが思い通りにうごかなかったり、文字化けしたり見づらい文字が表示されるときなど、色々あります。

今回はとりあえず手始めとして、深夜になるとプロンプトが見づらくなってくる設定を書きました。
プロンプトが見づらいのは不快です。
設定の中身はこんな感じです。

COLOR_LIST=(60 55 57 63 109 111 117 116 115 114 113 112 184 178 172 166 160 124 125 126 127 128 129 93)
preexec () {
    PROMPT="%B%(?..[%?] )%b%{^[[38;5;"$COLOR_LIST[`date | awk -F"[ :]" '{print $7}'`]"m%}%n@%U%m%%%u%{^[[m%} "
}

※注
dateコマンドの出力結果に依存します。環境に合わせて適当に変更してください。
コマンドを打つたびにスクリプトが走ることになるので環境によってはもっさりするかもしれません。

設定の中身は単にpreexecを使ってコマンドを実行するたびに時間に対応する色を再設定しているだけです。
COLOR_LISTの色をうまく調整すれば不快度は自由に設定できます。
深夜の色を背景色と近い色にしておけば自然と不快感が得られます。
ここの例で使っている色はとりあえず適当に選んだだけなので深夜でもそこそこ見やすい色ですが、モニタにあわせて絶妙にやる気がなくなる色を探す必要があります。

もっとアグレッシブに標準出力の文字すべてを見えなくすることもできなくはないですが、さすがにそれはやり過ぎです。あまりやり過ぎると設定ファイルをもとに戻すという無意味な結果になってしまう恐れがあります。

まあそもそもエディタで作業をしてる間はプロンプトの色には気づかないので無意味と言えば無意味ですが、要は気持ちの問題です。

2010-01-31

zshをカラフルにするメモ

^[[38;5;10m%「ここに色を変えたい文字を入れる」^[[m

上のような文字列を標準出力にはくと色が変わります。
数字の部分を変えれば文字色や背景色を変えたりできます。
ちなみに^[はエスケープ文字で、emacsだとC-q ESC で入力できます。

これとzshの関数を使えば、特定のコマンドの出力結果だけの色を変えたりできます

function sudo() {
    echo "^[[38;5;200m"
    /usr/bin/sudo $*
    echo "^[[m"
}

こんな関数を定義しておけばsudoのときだけ色が変わるので、見分けがつきやすくて便利です。

2010-01-25

JetpackでFirefoxを拡張

Firefoxの拡張が簡単にできてしまうJetpackというものを試してみました。

https://jetpack.mozillalabs.com/

Jetpackをインストールすると、about:jetpackというページにアクセスできるようになります。
このページから、
  • インストール済みのjetpackスクリプトの管理ページ
  • 開発用のコンソール
  • メモリ使用量の確認
  • チュートリアル
  • APIリファレンス(現状動いてないっぽい)
などが参照できるので楽に開発ができそうです。
jQueryが組み込みなのも助かります。

とりあえずチュートリアル通りにやればちゃんと動きます。
やり方はhttp://d.hatena.ne.jp/amachang/20090521/1242884854
でも紹介されてます。

まだあまり数は多くないようですがギャラリーを見れば大体どんなことができるかわかります。
http://jetpackgallery.mozillalabs.com/

ちなみにjetpackで作ったスクリプトはjetpackをインストールしないと使えません。
firefox3.6に組み込まれたのかと思いきや、どうやらそれはまだのようです。
本格的に使われるようになるにはもうちょっと時間がかかりそうな気がしてきたので、しばらく様子見です。

2010-01-11

jQueryプラグインjTemplatesのHTMLエンティティ変換処理について

Javascriptのテンプレートエンジンっぽいものはいくつかあるみたいですが、今回はjQueryプラグインのjTemplatesを使ってみてちょっとはまったところをメモしておきます。

Javascriptのテンプレートエンジンについてはこちらでまとめられています。
http://tanarky.blogspot.com/2009/11/javascript-template-engines.html

jTemplatesの本家ページ
http://jtemplates.tpython.com/


試しにYahooのAPIを叩いてみます。
サンプルのソースコードは以下の通り
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.2.6/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript" src="http://jtemplates.tpython.com/jTemplates/jquery-jtemplates.js"></script>
<div id="test_result"></div>
<script type="text/javascript">
jQuery(function(){
    var appid =
        jQuery.ajax({
                   url: "http://shopping.yahooapis.jp/ShoppingWebService/V1/json/itemSearch",
                   data: {
                       "appid": "cPvQ.eCxg67GFHywsAFH2KW2bVkOlYSz_pBz9.V3sOefgLF09GM8gJw8PJHRqII-",
                       "query": "amp",
                       "hits": 5
                   },
                   dataType: "jsonp",
                   cache: false,
                   error: function(data, status) {
                       alert(status);
                   },
                   success: function(data, status) {
                       jQuery("#test_result").setTemplate("<table id=\"dataTable\" border=\"1\">" +
                                                "{#foreach $T as item begin=2 count=5}" +
                                                "<tr><td><a href={$T.item.Url}>{$T.item.Name}</a></td>" +
                                                "<td><img src={$T.item.Image.Small} /></td></tr>" +
                                                "{#/for}" +
                                                "</table>");
                       jQuery("#test_result").processTemplate(data.ResultSet[0].Result);
                   }
               });
});
</script>


これを実際に実行するとこんな感じになります。





でもこれだと&amp;がそのまま残ってしまってしまってます。
おかしいなーと思ってjTemplatesのソースを見てみたら、案の定HTMLエンティティを変換している部分がありました
/**
         * Replace chars &, >, <, ", ' with html entities.
         * To disable function set settings: filter_data=false, filter_params=false
         * @param {string} string
         * @return {string}
         * @static
         * @memberOf TemplateUtils
         */
        TemplateUtils.escapeHTML = function(txt) {
                return txt.replace(/&/g,'&').replace(/>/g,'>').replace(/</g,'<').replace(/"/g,'"').replace(/'/g,''\
');


ソースをたどっていくと、どうやらsetTemplateするときにオプションで設定できることが分かりました。
/**
         * Create new template from string s.
         * @name Template
         * @class A template or multitemplate.
         * @param {string} s A template string (like: "Text: {$T.txt}.").
         * @param {array} [includes] Array of included templates.
         * @param {object} [settings] Settings.
         * @config {boolean} [disallow_functions] Do not allow use function in data (default: true).
         * @config {boolean} [filter_data] Enable filter data using escapeHTML (default: true).
         * @config {boolean} [filter_params] Enable filter parameters using escapeHTML (default: false).
         * @config {boolean} [runnable_functions] Automatically run function (from data) inside {} [default: false].
         * @config {boolean} [clone_data] Clone input data [default: true]
         * @config {boolean} [clone_params] Clone input parameters [default: true]
         * @config {Function} [f_cloneData] Function using to data cloning
         * @config {Function} [f_escapeString] Function using to escape strings
         * @augments BaseNode
         */
        var Template = function(s, includes, settings) {
  
(※setはTemplateのラッパーメソッド)

というわけで、setTemplateの第二引数にundefined, 第三引数に{filter_data : false}を与えてやるとうまくエンティティが文字として表示されました。



要するに、jTemplateに渡されるデータの中にHTMLエンティティが含まれているとjTemplateが気を利かしてエンコードしてくれるけど、すでにエンコード済みのデータを渡すと二重にエンコードすることになって、結果として&amp;amp;みたいなことになってしまいます。
jTemplatesはエンコードするかどうかのオプションを引数で渡すことができるので、渡すデータによって使い分ける必要がありそうです。

bloggerにソースコードハイライト機能を

bloggerはソースコードの貼り付けが面倒な上に見づらい、というのが大きな不満だったんですが、こんな便利なものがありました。

http://www.kuribo.info/2008/06/blogger-syntax-highlighter.html


これを使うと、

#include <stdio.h>

int main(void)
{
    printf("hello, world!\n");
    return 0;
}


こんな風にきれいに表示できます

ZenBackWidget