-->

2010-02-28

mmm-mode でヒアドキュメントの色付け

この記事は emacs の mmm-mode で phpファイルのヒアドキュメントに色付けする際の例です。

ヒアドキュメントと、phpタグ以外の部分と、コンパイラ停止、を認識しやすくします。
背景色をつけるだけですので、インデントすると EOF; の部分などが破壊されます。
(始めの部分)<?php ... ?>(終わりの部分) は背景色は変わりません。
(require 'mmm-mode)
(setq mmm-global-mode 'maybe)
(setq mmm-submode-decoration-level 1)
(invert-face 'mmm-default-submode-face nil)
(set-face-background 'mmm-default-submode-face "navy")
(setq mmm-font-lock-available-p t)
(mmm-add-mode-ext-class nil "\\.php\\'" 'php-others)
(mmm-add-group
 'php-others
 '(
   (php-heredoc
    :include-front t
    :include-back t
    :front-offset 0
    :back-offset 0
    :front "<<<\\s-*[\"\']?\\([a-zA-Z_][a-zA-Z0-9_]+\\)"
    :back "^\\s-*~1;$"
    :save-matches 1
    :submode fundamental-mode
    :face mmm-code-submode-face
    :delimiter-mode nil
    )
   (php-outside
    :include-front nil
    :include-back nil
    :front-offset 0
    :back-offset 0
    :front "\\(\\?\\|%\\)>"
    :back "<\\(\\?\\|%\\)"
    :save-matches 1
    :submode fundamental-mode
    :face mmm-code-submode-face
    :delimiter-mode nil
    )
   (php-halt-compiler
    :include-front t
    :include-back t
    :front-offset 0
    :back-offset 0
    :front "__halt_compiler\\s-*("
    :back ")\\s-*;"
    :save-matches 1
    :submode fundamental-mode
    :face mmm-code-submode-face
    :delimiter-mode nil
    )
   ))

コメント部分にphpの開始タグ、終了タグがあると失敗します。
phpの開始タグ、終了タグの%,?の種類が違うと失敗します。
背景色が変化した部分をインデントすると失敗します。
xml宣言などのphpの開始タグ、終了タグと同じ文字があると失敗します。
phpの文字列に <?, ?> などがあると失敗します。

mmm-sample.el に perl, bash 用のヒアドキュメントと php-mode 用のサンプルがあります。
(例) /usr/share/emacs/site-lisp/mmm-mode/mmm-sample.el

http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-list/31151
http://d.hatena.ne.jp/Tetsujin/20070808/1186582582
http://d.hatena.ne.jp/jimo1001/20071111/1194770814
http://www.bookshelf.jp/pukiwiki/pukiwiki.php?refer=MeadowMemo&cmd=read&page=MeadowMemo%2F%CA%A3%BF%F4%A4%CE%A5%E1%A5%B8%A5%E3%A1%BC%A5%E2%A1%BC%A5%C9%A4%F2%B6%A6%C2%B8%A1%BDmmm-mode
http://www.emacswiki.org/emacs/HtmlModeDeluxe

2010-02-25

php-mode.el の差分

この記事は emacs の php-mode.el の色付けに関する設定例です。

pecl, emerge dev-php/* dev-php5/*, php3, php4, php5.0-5.3, php6, manual の定数、関数を色が付くように、できるだけ反映させました。
足りない、もしくは、余分な値があります。

php の pear などの define(xxx, ...), function xxx(...){...} はありません。
php-search-documentation の部分に余分な修正が入るので手動で戻してください。
$ cp -pi php-mode.el php-mode.el.aaaaaaaaaaa
$ md5sum php-mode.el.aaaaaaaaaaa
d9a1e06bb579950c58fd3c1d8e813ce6  php-mode.el.aaaaaaaaaaa
$ grep -i "defconst.*php-mode-version-number" php-mode.el.aaaaaaaaaaa
(defconst php-mode-version-number "1.5.0"
$ md5sum -c heavy.php-mode.el.2010-02-25.patch.gz.md5sum
heavy.php-mode.el.2010-02-25.patch.gz: OK
$ gunzip heavy.php-mode.el.2010-02-25.patch.gz
$ patch php-mode.el heavy.php-mode.el.2010-02-25.patch
$ md5sum php-mode.el
07e14e3d5e9d1f161c37dac7c03d3efc  php-mode.el
$ emacs -batch -f batch-byte-compile php-mode.el

heavy.php-mode.el.2010-02-25.patch.gz
heavy.php-mode.el.2010-02-25.patch.gz.md5sum

2010-02-23

php-mode の php-search-documentation

この記事は emacs の php-mode.el の設定例です。

w3m-mode で function.xxx.html にアクセスできるように修正します。
$ diff -u php-mode.el.orig php-mode.el.w3m
--- php-mode.el.orig    2008-11-05 01:29:19.000000000 +0900
+++ php-mode.el.w3m     2010-02-23 14:51:26.000000000 +0900
@@ -544,7 +544,15 @@
 (defun php-search-documentation ()
   "Search PHP documentation for the word at point."
   (interactive)
-  (browse-url (concat php-search-url (current-word t))))
+  (w3m-browse-url (concat php-search-url "function."
+                          (my-str-replace "_" "-" (downcase (current-word t)))
+                          ".html")))
+(defun my-str-replace (search replace subject)
+  (let ((xxx -1))
+    (while xxx
+      (setq xxx (string-match search subject (+ 1 xxx)))
+      (if xxx (setq subject (replace-match replace nil nil subject)))))
+  subject)

 ;; Define function for browsing manual
 (defun php-browse-manual ()

string-match, replace-match でセットで扱うので replace-match に変数が足りないように見えますが動作します。
phpで書くと下記のようなイメージになります。
この例の場合 elisp の方は search に指定する文字が2バイト以上でも変換できますが php の方はできません。
<?php
function my_str_replace($search, $replace, $subject)
{
    $xxx = -1; // phpの場合は、すでに関数内でローカル変数です。
    while ($xxx !== false)
    {
        $xxx = strpos($subject, $search);
        if ($xxx !== false)
        {
            $subject[$xxx] = $replace; // 推薦されない文字列のアクセス方法です。
        }
    }
    return $subject;
}
print my_str_replace("_", "-", "_1_2_3_4_5_6_7_8_9_0_") . "\n";
print my_str_replace("_", "-", "") . "\n";
print my_str_replace("_", "-", "__") . "\n";
print my_str_replace("_", "-", "--") . "\n";
print my_str_replace("_", "-", "str_replace") . "\n";
print my_str_replace("_", "-", "htmlspecialchars") . "\n";
?>

2010-02-16

meadowからemacsへ

この記事は emacs の設定の例です。

emacs23.1 が linux の方に入っているので ntemacs23.1 へ変更しました。
http://d.hatena.ne.jp/galaxy9est/20091206/1260073096でバイナリ配布されていたのをそのまま使いました。
使う機能が大体動いたので、移行できそうなので設定を続けました。

しかし shell-mode が使えないです。
bash のビルドインコマンド (cd, test など) が動作しません。
cd sjisの文字列; test -e sjisの文字列; cat utf8の文字列; ls utf8 の文字列 がそれぞれ成功します。

.emacs に setenv を足すと cd が成功しました。
cygwin では無いコマンドは sjis を返す場合があるので command 2>&1 | nkf などが必要な場合があります。
nkfのインストールは、http://blog.goo.ne.jp/rm_-rf/e/63aa37f245f401d1404b107355d27a52のページを参考にしました。

;; ~/.bashrcで文字コード指定。
;; ...
;; LC_ALL=ja_JP.UTF-8
;; LANG="${LC_ALL}"
;; ...
;; ja_JP.UTF-8 はフックの中で指定すると2回目以降のshell-modeの起動で反映されます。
(setenv "LANG" "ja_JP.UTF-8")
(setenv "LC_ALL" "ja_JP.UTF-8")
(setq explicit-shell-file-name "bash.exe")
(setq shell-file-name "sh.exe")
(setq shell-command-switch "-c")
(set-language-environment "Japanese") ;; ここより上の方にある場合ここはコメントアウトします。
(prefer-coding-system 'iso-2022-jp)
(prefer-coding-system 'euc-jp)
(prefer-coding-system 'shift_jis)
(prefer-coding-system 'utf-8)
(set-default-coding-systems 'utf-8-unix)
(set-keyboard-coding-system 'utf-8-unix)
(set-terminal-coding-system 'utf-8-unix)
(setq file-name-coding-system 'sjis) ;; これが無いとemacs自体が日本語ファイルにアクセスできません。
(set-clipboard-coding-system 'sjis) ;; コピペが文字化けする場合、ここをコメントアウトして下さい。
(set-w32-system-coding-system 'sjis) ;; 時計部分などのシステム関連。
(set-buffer-file-coding-system 'utf-8-unix)

switch でcaseを2個書くとインデントがおかしくなります。
case 1 は大丈夫で case "1", case '1' だとおかしくなります。
http://debbugs.gnu.org/cgi/bugreport.cgi?bug=5388
$ sudo CFLAGS="" CXXFLAGS="" USE="-X -alsa -dbus -gif -gpm -gtk -jpeg -png -svg -tiff -xpm" emerge -av emacs
$ LANG=C LC_ALL=C eix app-editors/emacs$
[I] app-editors/emacs
     Available versions:
        (18)    18.59-r6
        (21)    21.4-r19
        (22)    22.3-r3!s
        (23)    23.1-r2!s
        {X Xaw3d alsa dbus gif gpm gtk gzip-el hesiod jpeg kerberos leim m17n-lib motif png sendmail sound source svg tiff toolkit-scroll-bars xft xpm}
     Installed versions:  23.1-r2(23)!s(17:05:58 02/25/10)(-X -Xaw3d -alsa -dbus -gif -gpm -gtk -gzip-el -hesiod -jpeg -kerberos -m17n-lib -motif -png -sound -source -svg -tiff -toolkit-scroll-bars -xft -xpm)
     Homepage:            http://www.gnu.org/software/emacs/
     Description:         The extensible, customizable, self-documenting real-time display editor
$ emacs -Q
M-x c-mode
M-x c-set-style bsd
M-x c-syntactic-information-on-region

switch($a)                      /* ((topmost-intro 192)) */
{                               /* ((substatement-open 192)) */
case 1:                         /* ((case-label 233)) */
case 2:                         /* ((case-label 233)) */
        $a=1;                   /* ((statement-case-intro 306)) */
        break;                  /* ((statement 343)) */
case "1":                       /* ((case-label 233)) */
case "2":                       /* ((case-label 233)) */
        $a=1;                   /* ((statement-cont 457)) */
break;                          /* ((statement 457)) */
}                               /* ((block-close 233)) */

2010-02-13

PHP: socket_select - Manual

この記事は php の socket_select に関する参考です。

PHP: socket_select - Manual: "vardhan ( at ) rogers ( dot ) com
28-Aug-2005 02:46"

上記のサンプルは、(B)と(C)の入力(文字+改行)が(B)と(C)の両方に出力されました。
(A) phpを起動(終わらない)
(B) telnet (A)のIPアドレス 9050
(C) telnet (A)のIPアドレス 9050

この例だと(B),(C)のtelnetのプロセスを落とすと(A)でエラーが大量に出ます。
pear 使うと良いようです。
Manual :: Net_Server の利用: "例 – Net_Server の利用
シンプルなデーモンを生成する"

echo "test" | nc 127.0.0.1 -q10 9090

1つのプロセスがずっと動いて複数のなにかを監視する場合は stream_select, socket_select などを使うらしいです。
pcntl_signal で kill xxx に対応すると本格的になります。

munin の state has changed, notifying xxx

この記事は munin に関する参考です。

muninでメールの設定をしたらメールが5分おきに毎回来ます。
内容に数字やwarningなどの文字が無いです。
項目のタイトルだけの内容のメールが来ます。
munin-limits.logに下記のようなログが残ります。
Feb 09 20:25:02 - state has changed, notifying xxx

muninのcrontabを実行するサーバーを1.4.3に変更しました。
メールが、内容の意味がわかる内容になりました。
cogentoo-1 :: cogentoo-1 :: CPU usage
 WARNINGs: system is 47.80 (outside range [:30]).

http://munin.projects.linpro.no/ticket/615

2010-02-12

fifo

この記事は php で fifo を扱う例です。

1つのfifoを複数のプロセスで監視します。
<?php
$log_file = "/tmp/abc.txt";
$log_fp = fopen($log_file, "a");
$read_file = "./fifo_read";
posix_mkfifo($read_file, 0600);
$read_fp = fopen($read_file, "r");
$pid = posix_getpid();
while (true)
{
    $buf = stream_get_contents($read_fp);
    if (is_string($buf) && $buf != "")
    {
        foreach (preg_split("/\r\n|[\r\n]/", $buf, -1, PREG_SPLIT_NO_EMPTY) as $line)
        {
            fwrite($log_fp, $pid . ":" . date("Y-m-d H:i:s") . ":" . $line . "\n");
        }
    }
    fopen($read_file, "r");
}
?>

確認します。
for i in $(seq 1 10); do (php test.php &); done
echo -n "" > /tmp/abc.txt
for xx in $(seq 1 100); do ((for i in $(seq 1 1000); do echo "cat /proc/meminfo" > fifo_read; done) &); done
wc -l /tmp/abc.txt
grep /proc/meminfo /tmp/abc.txt |wc -l
cat /tmp/abc.txt |awk -F\: '{print $1}'|sort|uniq -c
killall php

1つプロセスで複数の fifo を監視するには inotify, dio (pecl)などを使うらしいです。
open(file, O_RDONLY)でノンブロックではないので止まります。strace
ログの書き込みが遅れます。
openの動作で一時停止させるのは、良くないかもしれません。

2010-02-09

Connection lost in middle of processing

この記事は postfix の参考です。

単純なのが良いのでメール送信ソフトをssmtpにしていたが配送に失敗すると再送されません。
$ sudo grep "Connection lost in middle of processing" /var/log/mail.log*
Feb  6 00:15:02 amdgentoo sSMTP[3295]: Connection lost in middle of processing
Feb  9 00:15:05 amdgentoo sSMTP[16511]: Connection lost in middle of processing
Feb  9 02:36:04 amdgentoo sSMTP[2334]: Connection lost in middle of processing

postfixに変更しました。
/etc/postfix/main.cf, /etc/mail/aliases の変更箇所
$ diff /etc/postfix/main.cf.2010-02-09 /etc/postfix/main.cf; echo "==="; diff /etc/mail/aliases.2010-02-09 /etc/mail/aliases
262a263
> mynetworks = 127.0.0.0/8
313a315
> relayhost = プロバイダのsmtpサーバー
===
18a19
> root:自分のメールアドレス

インストールのコマンドの概要
$ sudo emerge -Cav ssmtp
$ sudo emerge -av postfix 
$ cd /etc/postfix
$ sudo cp -i main.cf main.cf.`date +%Y-%m-%d`
$ sudo vi main.cf
$ cd /etc/mail
$ sudo cp -i aliases aliases.`date +%Y-%m-%d`
$ sudo vi aliases
$ sudo newaliases
$ sudo /etc/init.d/postfix restart
$ sudo rc-update add postfix default
$ php -r 'mail("root", "subject", "message to:root ".`hostname`.`date`, "From: username@example.com");'

bash: bind: warning: line editing not enabled

この記事は emacs の shell-mode に関する参考です。

emacs の shell-mode でワーニングが表示されます。
設定の一部を .bashrc から .inputrc に変えました。
$ grep history-search-forward ~/.inputrc ~/.bashrc|sed 's/\/home\/[0-9A-Za-z]*\///'
.inputrc:"\C-n":history-search-forward
.bashrc:        #bind "\C-n":history-search-forward

2010-02-04

phpのオプションでビット演算を使う場合

この記事は php の error_reporting 関数に関する参考です。

関数のオプションの定数をビット演算で複数指定する場合の確認をします。
print "<pre>\n";
printf("%' 30s | %' 6s | %' 13s\n", "constant", "dec", "bin");
foreach (array("E_ALL", "E_NOTICE", "E_ALL^E_NOTICE", "E_ALL&~E_NOTICE", "LOCK_SH", "LOCK_SH|LOCK_NB", "LOCK_EX", "LOCK_EX|LOCK_NB") as $value)
{
    eval("\$value1 = $value;");  // 良い書き方ではないです。
    printf("%' 30s | %'06d | %'013s\n", $value, $value1, decbin($value1));
}
print "</pre>\n";

例えば、下記の設定は E_ALL に E_STRICT が含まれるかどうかで変わります。
error_reporting(E_ALL &~ E_STRICT);
error_reporting(E_ALL ^ E_STRICT);

例えば E_ALL ^ E_NOTICE は E_ALL に E_NOTICE が含まれるので E_ALL から E_NOTICE を引いた値(E_ALL &~ E_NOTICE と同じ)になり E_ALL ^ E_STRICT は E_ALL に E_STRICT が含まれないので E_ALL | E_STRICT と同じ値になります。

php6 から E_ALL が E_STRICT を含むらしいので注意が必要です。
よって error_reporting に排他的論理和を使うのをやめることをお勧めします。

排他的論理和の例
print (0^0) . "=0\n";
print (0^1) . "=1\n";
print (1^0) . "=1\n";
print (1^1) . "=0\n";

例えば E_XXX &~ E_NOTICE は E_NOTICE のビットを0にしたいことが明白で
E_XXX ^ E_NOTICE は E_XXX の E_NOTICE のビットが、0の時1にして、1の時0にします。

(例) pear を使うので E_STRICT をOFFにする。
error_reporting(E_ALL &~ E_STRICT);
//set_error_handler("exception_error_handler", E_ALL &~ E_STRICT);

また .htaccess にエラーレベルを指定する場合には、番号になるので auto_prepend_file などに php のコード(error_reporting(XXX);)として書くほうが良いです。

2010-02-02

speedfan の設定 (SpeedFan Part4 の引用)

この記事は speedfan に関する参考です。

SpeedFan Part4 の引用
SpeedFan Part4: "7 :名無しさん@お腹いっぱい。[sage]:2007/02/16(金) 19:54:14 ID:NaOnMsdl0
Divisorの設定についても、テンプレに追加した方が良くない?
…と、言いだしっぺが案を…。

Q. Fanの回転数がZeroのままです。
A. Configure→Advancedでマザーのチップセットを選んだ後、
FanN divisorの設定を2,4,8等に増やしてください。
これは、Fan回転検知の「細かさ」の指定で、値を上げると回転検知に
敏感になります。上げすぎると回転数の振れ幅が大きくなります。"

speedfanの回転数が取れません。
状態としては everest のセンサーを選んだ後に speedfan を見ると回転数が 0 => 0 以外になります。

設定します。
記録するかどうかのチェックボックスをチェックしないと再起動で元に戻ります。
変更する数字の量は使用しているマザーボードの種類によって異なります。この例は PX915G の場合です。
設定 => 詳細設定 => Winbord ... ISA =>
FAN1 divisor => 2から8
FAN2 divisor => 2から4
FAN3 divisor => 2から8

表示されるようになりました。
sexe というソフトが簡単に speedfan をサービスに登録できます。
sexe でデスクトップに関する設定をONにするとシャットダウン時に speedfan が初期化できないとエラーを出します。
ログイン前に起動して欲しい場合か、止まったら再実行して欲しい場合か、タスクバーにアイコンが出て欲しくない場合に有用と思われます。

xAPで外部からデータを取得します。
設定 => xAP => Enable

temp1~7, fan1~3 が取得できます。
取得間隔や、電圧の設定は発見できませんでした。

取得する例
http://php.net/manual/ja/function.socket-recvfrom.php
<?php
date_default_timezone_set("Asia/Tokyo");
error_reporting(E_ALL | E_STRICT);
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$ret = socket_bind($socket, '127.0.0.1', 3639);
if (!$ret)
{
    trigger_error(E_USER_ERROR, "socket_bind error.\n");
}
while (true)
{
    $from = "";
    $port = 0;
    $ret = socket_recvfrom($socket, $buf, 8192, 0, $from, $port);
    if ($ret > 0)
    {
        print str_repeat("=", 60) . "\n";
        print "\$from = " . $port . "\n";
        print "\$port = " . $port . "\n";
        print "\$buf = \n" . $buf . "\n";
    }
    else
    {
        trigger_error(E_USER_WARNING, "socket_recvfrom error\n");
    }
    print date("Y-m-d H:i:s\n");
}
?>

munin-node の fan の設定は無いようです。
munin-nodewin32/svnroot/munin-node/src/plugins/speedfan/SpeedFanNodePlugin.cpp

確認するコマンド
echo "config speedfan" | nc 192.168.0.90 4949 -q10
echo "fetch speedfan" | nc 192.168.0.90 4949 -q10