Created
June 13, 2011 00:01
-
-
Save thekid/1022149 to your computer and use it in GitHub Desktop.
XP Framework: Unicode revamp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/unix/src/exec.in b/unix/src/exec.in | |
index 05efad0..d97a586 100644 | |
--- a/unix/src/exec.in | |
+++ b/unix/src/exec.in | |
@@ -50,6 +50,12 @@ if [ ! -d /proc/1 ] ; then | |
export XP_CMDLINE | |
fi | |
#endif | |
+LC_CONSOLE=${LANG#*\.} | |
+LC_CONSOLE="${LC_CONSOLE} ${LC_CONSOLE} ${LC_CONSOLE} " | |
+if [ -t 0 ] ; then LC_CONSOLE=${LC_CONSOLE}0 ; else LC_CONSOLE=${LC_CONSOLE}1; fi | |
+if [ -t 1 ] ; then LC_CONSOLE=${LC_CONSOLE}0 ; else LC_CONSOLE=${LC_CONSOLE}1; fi | |
+if [ -t 2 ] ; then LC_CONSOLE=${LC_CONSOLE}0 ; else LC_CONSOLE=${LC_CONSOLE}1; fi | |
export XP_RT | |
+export LC_CONSOLE | |
IFS="|" | |
${XP_RT}${ifs}${args}${ifs}$tool ${ARGS} "$@" | |
diff --git a/windows/src/CompositeConfigSource.cs b/windows/src/CompositeConfigSource.cs | |
index f204daa..68657b5 100644 | |
--- a/windows/src/CompositeConfigSource.cs | |
+++ b/windows/src/CompositeConfigSource.cs | |
@@ -42,6 +42,19 @@ namespace Net.XpFramework.Runner | |
} | |
/// <summary> | |
+ /// Returns whether the PHP runtime supports wmain() | |
+ /// </summary> | |
+ public bool? GetWMain() | |
+ { | |
+ foreach (XpConfigSource source in this.sources) | |
+ { | |
+ bool? wmain = source.GetWMain(); | |
+ if (wmain != null) return wmain; | |
+ } | |
+ return null; | |
+ } | |
+ | |
+ /// <summary> | |
/// Returns the PHP runtime arguments to be used from this config source | |
/// </summary> | |
public Dictionary<string, IEnumerable<string>> GetArgs() | |
diff --git a/windows/src/EnvironmentConfigSource.cs b/windows/src/EnvironmentConfigSource.cs | |
index 56e8b24..cf9d96c 100644 | |
--- a/windows/src/EnvironmentConfigSource.cs | |
+++ b/windows/src/EnvironmentConfigSource.cs | |
@@ -28,6 +28,14 @@ namespace Net.XpFramework.Runner | |
} | |
/// <summary> | |
+ /// Returns whether the PHP runtime supports wmain() | |
+ /// </summary> | |
+ public bool? GetWMain() | |
+ { | |
+ return null; | |
+ } | |
+ | |
+ /// <summary> | |
/// Returns the PHP runtime arguments to be used from this config source | |
/// </summary> | |
public Dictionary<string, IEnumerable<string>> GetArgs() | |
diff --git a/windows/src/Executor.cs b/windows/src/Executor.cs | |
index 4126ed1..6322e98 100755 | |
--- a/windows/src/Executor.cs | |
+++ b/windows/src/Executor.cs | |
@@ -3,14 +3,43 @@ using System.Collections.Generic; | |
using System.Text; | |
using System.IO; | |
using System.Diagnostics; | |
+using System.Runtime.InteropServices; | |
+ | |
namespace Net.XpFramework.Runner | |
{ | |
+ delegate string ArgProcessor(string arg); | |
+ | |
class Executor | |
{ | |
private static string PATH_SEPARATOR = new string(new char[] { Path.PathSeparator}); | |
private static List<string> EMPTY_LIST = new List<string>(); | |
+ [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] | |
+ internal static extern IntPtr GetStdHandle(int nStdHandle); | |
+ | |
+ [DllImport("kernel32.dll", SetLastError = true)] | |
+ internal static extern bool GetConsoleMode(IntPtr hConsoleHandle, out int mode); | |
+ | |
+ internal enum StandardHandles | |
+ { | |
+ IN = -10, | |
+ OUT = -11, | |
+ ERR = -12 | |
+ } | |
+ | |
+ public static bool IsRedirect(StandardHandles id) | |
+ { | |
+ int mode; | |
+ | |
+ if (!GetConsoleMode(GetStdHandle((int)id), out mode)) | |
+ { | |
+ throw new IOException("GetConsoleMode(" + id + ") failed"); | |
+ } | |
+ | |
+ return 0 == mode; | |
+ } | |
+ | |
/// <summary> | |
/// | |
/// </summary> | |
@@ -33,6 +62,7 @@ namespace Net.XpFramework.Runner | |
); | |
IEnumerable<string> use_xp = configs.GetUse(); | |
string executor = configs.GetRuntime() ?? "php"; | |
+ bool wmain = configs.GetWMain() ?? false; | |
if (null == use_xp) { | |
throw new EntryPointNotFoundException("Cannot determine use_xp setting from " + configs); | |
@@ -54,19 +84,33 @@ namespace Net.XpFramework.Runner | |
String.Join(PATH_SEPARATOR, includes) | |
); | |
- // If input or output encoding are not equal to default, also pass their | |
- // names inside an LC_CONSOLE environment variable. Only do this inside | |
- // real Windows console windows! | |
+ // Pass input,output,default encodings and whether stdin,out and err are redirects | |
+ // or not via LC_CONSOLE. Only do this inside real Windows console windows, for | |
+ // Cygwin, this works quite differently! | |
// | |
// See http://msdn.microsoft.com/en-us/library/system.text.encoding.headername.aspx | |
// and http://msdn.microsoft.com/en-us/library/system.text.encoding.aspx | |
if (null == Environment.GetEnvironmentVariable("TERM")) | |
{ | |
Encoding defaultEncoding = Encoding.Default; | |
- if (!defaultEncoding.Equals(Console.InputEncoding) || !defaultEncoding.Equals(Console.OutputEncoding)) | |
- { | |
- Environment.SetEnvironmentVariable("LC_CONSOLE", Console.InputEncoding.HeaderName + "," + Console.OutputEncoding.HeaderName); | |
- } | |
+ Environment.SetEnvironmentVariable("LC_CONSOLE", String.Format( | |
+ "{0} {1} {2} {3}{4}{5}", | |
+ Console.InputEncoding.HeaderName, | |
+ Console.OutputEncoding.HeaderName, | |
+ wmain ? "utf-16" : "utf-8", | |
+ IsRedirect(StandardHandles.IN) ? 1 : 0, | |
+ IsRedirect(StandardHandles.OUT) ? 1 : 0, | |
+ IsRedirect(StandardHandles.ERR) ? 1 : 0 | |
+ )); | |
+ } | |
+ else | |
+ { | |
+ string lang = Environment.GetEnvironmentVariable("LANG"); | |
+ Environment.SetEnvironmentVariable("LC_CONSOLE", String.Format( | |
+ "{0} {0} {1} 000", | |
+ null == lang ? Encoding.Default.HeaderName : lang.Split('.')[1], | |
+ wmain ? "utf-16" : "utf-8" | |
+ )); | |
} | |
// Look for PHP configuration | |
@@ -77,7 +121,6 @@ namespace Net.XpFramework.Runner | |
argv += " -d" + kv.Key + "=\"" + value + "\""; | |
} | |
} | |
- | |
// Spawn runtime | |
var proc = new Process(); | |
@@ -85,8 +128,35 @@ namespace Net.XpFramework.Runner | |
proc.StartInfo.Arguments = argv + " \"" + new List<string>(Paths.Locate(use_xp, "tools\\" + runner + ".php", true))[0] + "\" " + tool; | |
if (args.Length > 0) | |
{ | |
- foreach (string arg in args) { | |
- proc.StartInfo.Arguments += " \"" + arg.Replace("\"", "\"\"\"") + "\""; | |
+ ArgProcessor process; | |
+ | |
+ // Workaround problem that php itself doesn't have a wmain() method, so the OS | |
+ // converts the strings passed as argument to OS default encoding (CP1252, on | |
+ // a German Windows installation). Works fine until someone enters Japanese | |
+ // characters). Convert to single byte character set before passing. | |
+ // | |
+ // This workaround can be disabled by setting runtime.wmain to true once PHP | |
+ // declares that. See http://msdn.microsoft.com/en-us/library/88w63h9k.aspx | |
+ if (wmain) | |
+ { | |
+ process = delegate(string arg) | |
+ { | |
+ return arg; | |
+ }; | |
+ } | |
+ else | |
+ { | |
+ process = delegate(string arg) | |
+ { | |
+ var mb = Encoding.UTF8; | |
+ var sb = Encoding.GetEncoding(1252); | |
+ | |
+ return sb.GetString(mb.GetBytes(arg)); | |
+ }; | |
+ } | |
+ foreach (string arg in args) | |
+ { | |
+ proc.StartInfo.Arguments += " \"" + process(arg.Replace("\"", "\"\"\"")) + "\""; | |
} | |
} | |
diff --git a/windows/src/IniConfigSource.cs b/windows/src/IniConfigSource.cs | |
index 7561aa9..cd7f065 100644 | |
--- a/windows/src/IniConfigSource.cs | |
+++ b/windows/src/IniConfigSource.cs | |
@@ -39,6 +39,22 @@ namespace Net.XpFramework.Runner | |
} | |
/// <summary> | |
+ /// Returns whether the PHP runtime supports wmain() | |
+ /// </summary> | |
+ public bool? GetWMain() | |
+ { | |
+ var wmain = this.ini.Get("runtime", "wmain"); | |
+ | |
+ if (null == wmain) | |
+ { | |
+ return null; | |
+ } | |
+ | |
+ wmain = wmain.ToLower(); | |
+ return wmain.Equals("yes") || wmain.Equals("true") || wmain.Equals("1") || wmain.Equals("on"); | |
+ } | |
+ | |
+ /// <summary> | |
/// Returns the PHP runtime arguments to be used from this config source | |
/// </summary> | |
public Dictionary<string, IEnumerable<string>> GetArgs() | |
@@ -47,7 +63,7 @@ namespace Net.XpFramework.Runner | |
List<string> empty= new List<string>(); | |
foreach (string key in this.ini.Keys("runtime", empty)) | |
{ | |
- if (!"default".Equals(key)) | |
+ if (!"default".Equals(key) && !"wmain".Equals(key)) | |
{ | |
args[key]= this.ini.GetAll("runtime", key, empty); | |
} | |
diff --git a/windows/src/XpConfigSource.cs b/windows/src/XpConfigSource.cs | |
index d0ba28a..60744e9 100644 | |
--- a/windows/src/XpConfigSource.cs | |
+++ b/windows/src/XpConfigSource.cs | |
@@ -19,6 +19,12 @@ namespace Net.XpFramework.Runner | |
string GetRuntime(); | |
/// <summary> | |
+ /// Returns whether the PHP runtime supports wmain() | |
+ /// See http://stackoverflow.com/questions/2627891/does-process-startinfo-arguments-support-a-utf-8-string | |
+ /// </summary> | |
+ bool? GetWMain(); | |
+ | |
+ /// <summary> | |
/// Returns the PHP runtime arguments to be used from this config source | |
/// </summary> | |
Dictionary<string, IEnumerable<string>> GetArgs(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The unittest output is that of
unittest src/resources/unittest/*.ini
...