fcshDaemon.php 日本語対応
"以前の記事" で作成した fcshDaemon.php を日本語に対応させました。
課題
コーディングの相違を吸収する必要があった。cygwin のコードは ShiftJIS(コードページ932)、flex+fcsh もShiftJIS。php は UTF-8 なので、日本語を使うとなると変換が必要になる。具体的には、preg_match が動作しないということ。環境は、windowsXP+cygwin+meadow+ant+flex4+AIR2.0 などなど。
対処
- fcshDaemon.php を UTF-8 で作成する。
- mb_internal_encoding("UTF-8"); をコールする。
- $result=mb_convert_encoding( $result, "UTF-8", "SJIS" ); でコードをShiftJISからUTF-8に変更する。
- jvm.config (flex_sdk/bin/jvm.config) をNON-LOCALEにする。
- my.php.ini に extension=php_mbstring.dll を加える。
jvm.config 該当部分
#java.args=-Xmx384m -Dsun.io.useCanonCaches=false -Duser.language=en -Duser.region=US #java.args=-Xmx384m -Dsun.io.useCanonCaches=false -Duser.language=ja -Duser.region=JP java.args=-Xmx384m -Dsun.io.useCanonCaches=false
my.php.ini
これはタグ含めて4行で全部。このiniファイルを使うことで、php.exe が速やかな動作をする。
[PHP] extension_dir = "C:\xampp\php\ext\" extension=php_sockets.dll extension=php_mbstring.dll
fcshDaemon.php
#! php -q <?php // $Revision: 206 $ error_reporting(E_ALL); set_time_limit(0); ob_implicit_flush(); /* * 日本語を使うからこれが大事 * ...と言いながら、このファイルは UTF-8 で * 作成しているので無くても構わない。 */ mb_internal_encoding('UTF-8'); /* * IP address and port number of daemon */ $daemon_address ='127.0.0.1'; $daemon_port =10000; /* * process ID of fcsh */ $fcsh_process =null; /* * prompt string of fcsh */ $fcsh_prompt ="(fcsh) "; //最後の空白は要ります /* * a compile command list and a compile target list * * $command_list ... $command_list["instruction"][0] ="instruction"; * $command_list["instruction"][1] ="replaced instruction" * $target_list ... $target_list["taget number"] ="instruction" * * $command_list is storage of a replaced instruction. * $target_list is storage of compile target. */ $command_list =array(); $target_list =array(); /**************************************** * プログラム本体 */ echo "eggtoothcroc's private fcsh wrapper ".'($Revision: 206 $)'."\n"; echo "Copyleft (c) 2009 eggtoothcroc. All lefts reserved.\n"; echo "\n"; echo " ... waiting a connection request thru socket.\n\n"; /* * create a daemon socket */ if( ($daemon_sock = @socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false ){ echo __FILE__ . "(" . __LINE__ ."): Error: ".socket_strerror(socket_last_error()); exit(-1); } /* * put a daemon socket into net */ if( @socket_bind($daemon_sock, $daemon_address, $daemon_port) === false ){ echo __FILE__ . "(" . __LINE__ ."): Error: " .socket_strerror(socket_last_error($daemon_sock)); socket_close($daemon_sock); exit(-1); } do{ // wait one client if( @socket_listen($daemon_sock, 1) === false ){ echo __FILE__ . "(" . __LINE__ ."): Error: " .socket_strerror(socket_last_error($daemon_sock)); socket_close($daemon_sock); exit(-1); } // accept a client if( ($client_sock = @socket_accept($daemon_sock)) === false ){ echo __FILE__ . "(" . __LINE__ ."): Error: " .socket_strerror(socket_last_error($daemon_sock)); socket_close($daemon_sock); exit(-1); } if( !is_resource($fcsh_process) ){ // at the first acceptance a fcsh will be executed list($fcsh_process, $fcsh_to, $fcsh_from, $fcsh_error) =fcsh_open(); if( !is_resource($fcsh_process) ){ $mssg = __FILE__ . "(" . __LINE__ ."): Error: cannot execute fcsh.exe"; reply($client_sock, $mssg); echo $mssg; socket_shutdown($client_sock); socket_close($client_sock); socket_close($daemon_sock); exit(-1); } // read a message from fcsh and echo fcsh_read($fcsh_from,$client_sock); }else{ /* * send a "(fcsh) " to the client */ reply($client_sock, $fcsh_prompt); } /* * read a instruction from the client */ $read =array( $client_sock ); $write =NULL; $except =NULL; $num_changed =socket_select($read,$write,$except,5); if( $num_changed == 0 ){ /* * we don't need to wait for 5 seconds, it's enough in 1 second. * The time between a prompt and a reply to/from the client is * only dozens of milliseconds. */ echo __FILE__ . "(" . __LINE__ ."): Error: Nobody makes me happy...bye"; break; } $command =socket_read($client_sock,1000); // if clear purge( &$command_list, &$target_list, $command ); // if replace ( mxmlc => compile (id) ) $command =reget( &$command_list, $command ); // send a instruction to fcsh fcsh_write( $fcsh_to, $command ); // if quit if( quit( $client_sock, $command ) ) break; // read a result of compilation and echo $result =fcsh_read( $fcsh_from, $client_sock ); // replace an instruction ( mxmlc => compc (id) ) remake( &$command_list, &$target_list, $command, $result ); }while(true); /* * the end of program */ fclose( $fcsh_to ); fclose( $fcsh_from ); fclose( $fcsh_error ); proc_close($fcsh_process); socket_shutdown($client_sock); socket_close($client_sock); socket_close($daemon_sock); 1; /********************************************************** * functions */ /* * fcsh_read * */ function fcsh_read( $pipe, $client_sock ) { global $fcsh_prompt; $rdbuf =""; $rdline =""; do{ $c =fread($pipe,1); $rdline .=$c; if( $c=="\n" ){ echo $rdline; reply($client_sock, $rdline); $rdbuf .=$rdline; $rdline =""; }else if( $c==" " && strpos($rdline,$fcsh_prompt)!==false ){ echo $rdline; reply($client_sock, $rdline); $rdbuf .=$rdline; break; } }while(true); return $rdbuf; } /* * fcsh_write * */ function fcsh_write( $pipe, $command ) { echo $command; fwrite($pipe,$command); } /* * fcsh_open * * execute fcsh, and join stderr and stdout */ function fcsh_open() { $descriptorspec =array( 0 => array("pipe", "r"), // stdin 1 => array("pipe", "w"), // stdout 2 => array("pipe", "w") // stderr ); $process =proc_open( 'fcsh.exe 2>&1', $descriptorspec, $pipes ); return array( $process, $pipes[0], $pipes[1], $pipes[2] ); } /* * reget * * replace a command ( mxmlc => compile (id) ) */ function reget( $command_list, $command ) { if( !array_key_exists($command,$command_list) ){ $command_list[$command] =array( $command, $command ); } return $command_list[$command][1]; } /* * remake * * replace a command if new assignment is appeared * */ function remake( $command_list, $target_list, $command, $result ) { //日本語($result)がSHIFTJISでやってくる $result =mb_convert_encoding( $result, "UTF-8", "SJIS" ); if( preg_match( "/fcsh: Assigned (\d+) as the compile target id/", $result, $chunks ) || preg_match( "/fcsh : コンパイルターゲット ID として (\d+) を割り当てました/", $result, $chunks ) ){ // コンパイル命令の割り当てが見つかった $command_list[$command][1] ="compile ".$chunks[1]."\n"; $target_list[$chunks[1]] =$command; } } /* * purge (clear) * * clear the target */ function purge( $command_list, $target_list, $command ) { if( preg_match( "/clear *(\d*)/", $command, $chunks ) ){ if( $chunks[1]==NULL ){ /* * if no target id specified, clear all */ $command_list =array(); $target_list =array(); }else{ /* * clear a specified target if exists */ if( !array_key_exists($chunks[1],$target_list) ) return; $clear_target =$target_list[$chunks[1]]; unset( $command_list[$clear_target] ); unset( $target_list[$chunks[1]] ); } } } /* * quit */ function quit( $client_sock, $command ) { global $fcsh_prompt; if( preg_match( "/quit */", $command ) ){ reply($client_sock, $fcsh_prompt); return true; } return false; } /* * reply * * reply to a client */ function reply( $client_sock, $command ) { $read =NULL; $write =array( $client_sock ); $except =NULL; $num_changed =socket_select($read,$write,$except,5); if( $num_changed == 0 ){ echo __FILE__ . "(" . __LINE__ ."): Error: write is disabled."; return false; } socket_write($client_sock,$command,strlen($command)); return true; } ?>