commit 48e2407e169882af3d750754f6d0c908b919a832
Author: YX Hao <lifenjoiner@163.com>
Date:   Tue Aug 12 22:44:08 2014 +0800

    Win: Add Unicode support for _tmain and _tWinMain

diff --git a/libtcc.c b/libtcc.c
index b0ac2c7..7bfb51a 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -1046,6 +1046,9 @@ LIBTCCAPI TCCState *tcc_new(void)
 #ifdef TCC_IS_NATIVE
     s->runtime_main = "main";
 #endif
+#ifdef TCC_TARGET_PE
+    s->unicode_entry = 0;
+#endif
     return s;
 }
 
diff --git a/tcc.h b/tcc.h
index c93cedf..ff5d6ab 100644
--- a/tcc.h
+++ b/tcc.h
@@ -705,6 +705,7 @@ struct TCCState {
     int uw_sym;
     unsigned uw_offs;
 # endif
+    int unicode_entry; /* _tmain, _tWinMain */
 #endif
 
 #ifdef TCC_IS_NATIVE
diff --git a/tccgen.c b/tccgen.c
index 5fd127f..02a0967 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -5824,7 +5824,11 @@ static void gen_function(Sym *sym)
     gfunc_prolog(&sym->type);
 #ifdef CONFIG_TCC_BCHECK
     if (tcc_state->do_bounds_check
-        && !strcmp(get_tok_str(sym->v, NULL), "main")) {
+        && (!strcmp(get_tok_str(sym->v, NULL),
+#ifdef TCC_TARGET_PE
+        tcc_state->unicode_entry == 3 /*PE_EXE*/ ? "wmain" :
+#endif
+        "main"))) {
         int i;
 
         sym = local_stack;
diff --git a/tccpe.c b/tccpe.c
index e392f40..209cf7f 100644
--- a/tccpe.c
+++ b/tccpe.c
@@ -1738,23 +1738,34 @@ static void pe_add_runtime(TCCState *s1, struct pe_info *pe)
 {
     const char *start_symbol;
     int pe_type = 0;
+    int unicode_entry = 0;
 
     if (find_elf_sym(symtab_section, PE_STDSYM("WinMain","@16")))
         pe_type = PE_GUI;
     else
+    if (find_elf_sym(symtab_section, PE_STDSYM("wWinMain","@16"))) {
+        pe_type = PE_GUI;
+        s1->unicode_entry = PE_GUI;
+    } else
     if (TCC_OUTPUT_DLL == s1->output_type) {
         pe_type = PE_DLL;
         /* need this for 'tccelf.c:relocate_section()' */
         s1->output_type = TCC_OUTPUT_EXE;
     }
-    else
+    else {
         pe_type = PE_EXE;
+        if (find_elf_sym(symtab_section, "wmain"))
+            s1->unicode_entry = PE_EXE;
+    }
 
+    unicode_entry = s1->unicode_entry;
     start_symbol =
         TCC_OUTPUT_MEMORY == s1->output_type
-        ? PE_GUI == pe_type ? "__runwinmain" : "_main"
+        ? PE_GUI == pe_type ? (unicode_entry ? "__wrunwinmain" : "__runwinmain")
+            : (unicode_entry ? "_wmain" : "_main")
         : PE_DLL == pe_type ? PE_STDSYM("__dllstart","@12")
-        : PE_GUI == pe_type ? "__winstart" : "__start"
+            : PE_GUI == pe_type ? (unicode_entry ? "__wwinstart": "__winstart")
+                : (unicode_entry ? "__wstart" : "__start")
         ;
 
     if (!s1->leading_underscore || strchr(start_symbol, '@'))
diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat
index f5c414a..5a2a85f 100644
--- a/win32/build-tcc.bat
+++ b/win32/build-tcc.bat
@@ -39,7 +39,9 @@ copy ..\include\*.h include
 :libtcc1.a
 .\tcc %target% -c ../lib/libtcc1.c
 .\tcc %target% -c lib/crt1.c
+.\tcc %target% -c lib/crt1.c -D_UNICODE -o crt1_w.o
 .\tcc %target% -c lib/wincrt1.c
+.\tcc %target% -c lib/wincrt1.c -D_UNICODE -o wincrt1_w.o
 .\tcc %target% -c lib/dllcrt1.c
 .\tcc %target% -c lib/dllmain.c
 .\tcc %target% -c lib/chkstk.S
@@ -49,12 +51,12 @@ goto lib%P%
 .\tcc %target% -c ../lib/alloca86.S
 .\tcc %target% -c ../lib/alloca86-bt.S
 .\tcc %target% -c ../lib/bcheck.c
-tiny_libmaker lib/libtcc1.a libtcc1.o alloca86.o alloca86-bt.o crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o bcheck.o
+tiny_libmaker lib/libtcc1.a libtcc1.o alloca86.o alloca86-bt.o crt1.o crt1_w.o wincrt1.o wincrt1_w.o dllcrt1.o dllmain.o chkstk.o bcheck.o
 @goto the_end
 
 :lib64
 .\tcc %target% -c ../lib/alloca86_64.S
-tiny_libmaker lib/libtcc1.a libtcc1.o alloca86_64.o crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o
+tiny_libmaker lib/libtcc1.a libtcc1.o alloca86_64.o crt1.o crt1_w.o wincrt1.o wincrt1_w.o dllcrt1.o dllmain.o chkstk.o
 
 :the_end
 del *.o
diff --git a/win32/lib/crt1.c b/win32/lib/crt1.c
index 5e80bd3..ad7572a 100644
--- a/win32/lib/crt1.c
+++ b/win32/lib/crt1.c
@@ -2,6 +2,11 @@
 // crt1.c
 
 #include <stdlib.h>
+#include <tchar.h>
+#ifdef _UNICODE
+#define UNICODE /* for API */
+#endif
+#include <windows.h>
 
 #define __UNKNOWN_APP    0
 #define __CONSOLE_APP    1
@@ -14,19 +19,28 @@ typedef struct
     int newmode;
 } _startupinfo;
 
+#ifdef _UNICODE
+int __wgetmainargs(int *pargc, wchar_t ***pargv, wchar_t ***penv, int globb, _startupinfo*);
+#define _tstart _wstart
+#define _tmain wmain
+#define __tgetmainargs __wgetmainargs
+#else
 int __getmainargs(int *pargc, char ***pargv, char ***penv, int globb, _startupinfo*);
-int main(int argc, char **argv, char **env);
+#define _tstart _start
+#define _tmain main
+#define __tgetmainargs __getmainargs
+#endif
 
-int _start(void)
+int _tstart(void)
 {
     __TRY__
-    int argc; char **argv; char **env;
+    int argc; _TCHAR **argv; _TCHAR **env;
     _startupinfo start_info = {0};
 
     _controlfp(0x10000, 0x30000);
     __set_app_type(__CONSOLE_APP);
 
-    if (! __getmainargs(&argc, &argv, &env, 0, &start_info))
+    if (! __twgetmainargs(&argc, &argv, &env, 0, &start_info))
     {
         int ret;
 
diff --git a/win32/lib/wincrt1.c b/win32/lib/wincrt1.c
index 663fd33..ee79be0 100644
--- a/win32/lib/wincrt1.c
+++ b/win32/lib/wincrt1.c
@@ -1,6 +1,10 @@
 //+---------------------------------------------------------------------------
 
+#ifdef _UNICODE
+#define UNICODE /* for API */
+#endif
 #include <windows.h>
+#include <tchar.h>
 #include <stdlib.h>
 
 #define __UNKNOWN_APP    0
@@ -9,10 +13,19 @@
 void __set_app_type(int);
 void _controlfp(unsigned a, unsigned b);
 
-int _winstart(void)
+#ifdef _UNICODE
+int APIENTRY wWinMain(HINSTANCE,HINSTANCE,LPWSTR,int);
+#define _twinstart _wwinstart
+#define _trunwinmain _wrunwinmain
+#else
+#define _twinstart _winstart
+#define _trunwinmain _runwinmain
+#endif
+
+int _twinstart(void)
 {
     __TRY__
-    char *szCmd;
+    _TCHAR *szCmd;
     STARTUPINFO startinfo;
     int fShow;
     int ret;
@@ -43,22 +56,22 @@ int _winstart(void)
     if (0 == (startinfo.dwFlags & STARTF_USESHOWWINDOW))
         fShow = SW_SHOWDEFAULT;
 
-    ret = WinMain(GetModuleHandle(NULL), NULL, szCmd, fShow);
+    ret = _tWinMain(GetModuleHandle(NULL), NULL, szCmd, fShow);
     exit(ret);
 }
 
-int _runwinmain(int argc, char **argv)
+int _trunwinmain(int argc, _TCHAR **argv)
 {
-    char *szCmd, *p;
+    _TCHAR *szCmd, *p;
 
     p = GetCommandLine();
     szCmd = NULL;
     if (argc > 1)
-        szCmd = strstr(p, argv[1]);
+        szCmd = _tcsstr(p, argv[1]);
     if (NULL == szCmd)
-        szCmd = "";
+        szCmd = __T("");
     else if (szCmd > p && szCmd[-1] == '\"')
         --szCmd;
     _controlfp(0x10000, 0x30000);
-    return WinMain(GetModuleHandle(NULL), NULL, szCmd, SW_SHOWDEFAULT);
+    return _tWinMain(GetModuleHandle(NULL), NULL, szCmd, SW_SHOWDEFAULT);
 }
