PHPコマンドラインオプションの挙動を変えてみる
hnwさんのトコで「ワンライナーのためのPHPコマンドラインオプション」が詳しく解説されています。
これは便利です!ありがとうございます。<(_ _)>
普段からPHPでワンライナーを駆使していないのがバレバレなのですが、これをキッカケに色々と試してみたトコロ、確かにhnwさんが指摘しているように行末の改行コードが勝手にネグられるのは切ない感じです。
いつもなら、ここでショボーンとなって自然消滅するのですが、夢の中でhnwさんから真剣な表情で「一緒にやっていきましょう」と言われたので、ちょっとは頑張らないと申し訳が立たないなぁ。。。と勝手に思いつつ、中身を覗いてみたらシンプルな実装だったので(やっつけですが)改造も簡単にできました。ワーイ。
後、moriyoshiさんの突っ込みもあったのですが、必ずセミコロンで終わらないといけないのは確かに切ない感じです。
個人的にも「php -r '';」みたいな感じで、よく打ち損じているのですが、自動的に補完してくれると嬉しいなぁ。。。と前から思っていて、改行コードを保持する改造のノリで「だったら強制的にセミコロンを末尾に付与すれば良くね?」という結論に至り、こちらの方もシンプルな実装だったので(同様にやっつけですが)改造も簡単にできました。バンザーイ。いつもと違って今日は手が動きます。(w
以下のパッチ対象は5.3.0RC4ですが、5.2系統の実装も大差は無かったので、参考にできるかと思います。
--- php-5.3.0RC4,orig/sapi/cli/php_cli.c 2009-06-06 03:50:32.000000000 +0900 +++ php-5.3.0RC4/sapi/cli/php_cli.c 2009-06-22 18:58:52.000000000 +0900 @@ -1224,9 +1224,14 @@ #endif case PHP_MODE_CLI_DIRECT: cli_register_file_handles(TSRMLS_C); - if (zend_eval_string_ex(exec_direct, NULL, "Command line code", 1 TSRMLS_CC) == FAILURE) { + int new_size = strlen(exec_direct); + char *new_exec_direct = estrndup(exec_direct, (new_size + 2)); + new_exec_direct[new_size] = ';'; + new_exec_direct[(new_size+1)] = '\0'; + if (zend_eval_string_ex(new_exec_direct, NULL, "Command line code", 1 TSRMLS_CC) == FAILURE) { exit_status=254; } + efree(new_exec_direct); break; case PHP_MODE_PROCESS_STDIN: @@ -1247,9 +1252,15 @@ zend_hash_update(&EG(symbol_table), "argi", sizeof("argi"), &argi, sizeof(zval *), NULL); while (exit_status == SUCCESS && (input=php_stream_gets(s_in_process, NULL, 0)) != NULL) { len = strlen(input); - while (len-- && (input[len]=='\n' || input[len]=='\r')) { - input[len] = '\0'; - } + while (len--) { + if (input[len]=='\r' && input[(len+1)]=='\n' ) { + input[(len+2)] = '\0'; + len--; + } else if (input[len]=='\n' || input[len]=='\r') { + input[(len+1)] = '\0'; + } + } + len = strlen(input); ALLOC_ZVAL(argn); Z_TYPE_P(argn) = IS_STRING; Z_STRLEN_P(argn) = ++len; @@ -1258,9 +1269,14 @@ zend_hash_update(&EG(symbol_table), "argn", sizeof("argn"), &argn, sizeof(zval *), NULL); Z_LVAL_P(argi) = ++index; if (exec_run) { - if (zend_eval_string_ex(exec_run, NULL, "Command line run code", 1 TSRMLS_CC) == FAILURE) { + int new_size = strlen(exec_run); + char *new_exec_run = estrndup(exec_run, (new_size + 2)); + new_exec_run[new_size] = ';'; + new_exec_run[(new_size+1)] = '\0'; + if (zend_eval_string_ex(new_exec_run, NULL, "Command line run code", 1 TSRMLS_CC) == FAILURE) { exit_status=254; } + efree(new_exec_run); } else { if (script_file) { if (cli_seek_file_begin(&file_handle, script_file, &lineno TSRMLS_CC) != SUCCESS) {
gist.githubにも登録しておきました。度々指摘していただき感謝です。<(_ _)>
これで、もう忘れないぞっと。