From 86e3cd0c5ac9d6e8e80306f9f5fdcce4a4c38dc5 Mon Sep 17 00:00:00 2001 From: YX Hao Date: Wed, 15 Feb 2017 21:58:35 +0800 Subject: [PATCH] Add support for Unicode entries 'wmain' and 'wWinMain' on Windows '-run' suported. argvs are converted. But don't use compliled Unicode CLI exe-file to get inputs interactively in other codepage! Please add other compliling supports than 'build-tcc.bat' (Who is good at them). --- tccpe.c | 28 +++++++++++++++------ win32/build-tcc.bat | 6 ++++- win32/lib/crt1.c | 49 +++++++++++++++++++++++++++++++------ win32/lib/wincrt1.c | 59 +++++++++++++++++++++++++++++++++------------ 4 files changed, 111 insertions(+), 31 deletions(-) diff --git a/tccpe.c b/tccpe.c index 8d29070..8bb3d85 100644 --- a/tccpe.c +++ b/tccpe.c @@ -1759,34 +1759,46 @@ 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; + 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")) + unicode_entry = PE_EXE; + } start_symbol = TCC_OUTPUT_MEMORY == s1->output_type - ? PE_GUI == pe_type ? "__runwinmain" : "_main" + ? PE_GUI == pe_type ? (unicode_entry ? "__runwwinmain" : "__runwinmain") + : (unicode_entry ? "__runwmain" : "__runmain") : 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, '@')) ++start_symbol; /* grab the startup code from libtcc1 */ - if (TCC_OUTPUT_MEMORY != s1->output_type || PE_GUI == pe_type) - set_elf_sym(symtab_section, - 0, 0, - ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, - SHN_UNDEF, start_symbol); + /* only (PE_Dll == pe_type) doesn't need it, + (TCC_OUTPUT_MEMORY == s1->output_type && PE_Dll == pe_type) is illegal */ + set_elf_sym(symtab_section, + 0, 0, + ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0, + SHN_UNDEF, start_symbol); tcc_add_pragma_libs(s1); diff --git a/win32/build-tcc.bat b/win32/build-tcc.bat index 09117b4..8da1404 100644 --- a/win32/build-tcc.bat +++ b/win32/build-tcc.bat @@ -137,10 +137,12 @@ copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe %CC% -o tiny_libmaker-m%TX%.exe tools\tiny_libmaker.c %DX% :libtcc1.a -@set O1=libtcc1.o crt1.o wincrt1.o dllcrt1.o dllmain.o chkstk.o bcheck.o +@set O1=libtcc1.o crt1.o wincrt1.o crt1_w.o wincrt1_w.o dllcrt1.o dllmain.o chkstk.o bcheck.o .\tcc -m32 %D32% -c ../lib/libtcc1.c .\tcc -m32 %D32% -c lib/crt1.c +.\tcc -m32 %D32% -c lib/crt1.c -D_UNICODE -DUNICODE -o crt1_w.o .\tcc -m32 %D32% -c lib/wincrt1.c +.\tcc -m32 %D32% -c lib/wincrt1.c -D_UNICODE -DUNICODE -o wincrt1_w.o .\tcc -m32 %D32% -c lib/dllcrt1.c .\tcc -m32 %D32% -c lib/dllmain.c .\tcc -m32 %D32% -c lib/chkstk.S @@ -151,7 +153,9 @@ tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o @if errorlevel 1 goto :the_end .\tcc -m64 %D64% -c ../lib/libtcc1.c .\tcc -m64 %D64% -c lib/crt1.c +.\tcc -m64 %D64% -c lib/crt1.c -D_UNICODE -DUNICODE -o crt1_w.o .\tcc -m64 %D64% -c lib/wincrt1.c +.\tcc -m64 %D64% -c lib/wincrt1.c -D_UNICODE -DUNICODE -o wincrt1_w.o .\tcc -m64 %D64% -c lib/dllcrt1.c .\tcc -m64 %D64% -c lib/dllmain.c .\tcc -m64 %D64% -c lib/chkstk.S diff --git a/win32/lib/crt1.c b/win32/lib/crt1.c index 7a2d765..1e2bd17 100644 --- a/win32/lib/crt1.c +++ b/win32/lib/crt1.c @@ -1,6 +1,9 @@ // ============================================= // crt1.c +// _UNICODE for tchar.h, UNICODE for API +#include + #include #include @@ -18,20 +21,32 @@ typedef struct int newmode; } _startupinfo; -int __cdecl __getmainargs(int *pargc, char ***pargv, char ***penv, int globb, _startupinfo*); +#ifdef _UNICODE +#define __tgetmainargs __wgetmainargs +#define _tstart _wstart +#define _tmain wmain +#define _runtmain _runwmain +#else +#define __tgetmainargs __getmainargs +#define _tstart _start +#define _tmain main +#define _runtmain _runmain +#endif + +int __cdecl __tgetmainargs(int *pargc, _TCHAR ***pargv, _TCHAR ***penv, int globb, _startupinfo*); void __cdecl __set_app_type(int apptype); unsigned int __cdecl _controlfp(unsigned int new_value, unsigned int mask); -int main(int argc, char * argv[], char * env[]); +extern int _tmain(int argc, _TCHAR * argv[], _TCHAR * env[]); /* Allow command-line globbing with "int _dowildcard = 1;" in the user source */ int _dowildcard; -void _start(void) +void _tstart(void) { __TRY__ int argc, ret; - char **argv; - char **env; + _TCHAR **argv; + _TCHAR **env; _startupinfo start_info; // Sets the current application type @@ -45,8 +60,28 @@ void _start(void) #endif start_info.newmode = 0; - __getmainargs( &argc, &argv, &env, _dowildcard, &start_info); - ret = main(argc, argv, env); + __tgetmainargs( &argc, &argv, &env, _dowildcard, &start_info); + ret = _tmain(argc, argv, env); + exit(ret); +} + +void _runtmain(int argc0, /* as tcc passed in */ char **argv0) +{ + __TRY__ + int argc, ret; + _TCHAR **argv; + _TCHAR **env; + _startupinfo start_info; + + __set_app_type(_CONSOLE_APP); + +#ifdef __i386 + _controlfp(_PC_53, _MCW_PC); +#endif + + start_info.newmode = 0; + __tgetmainargs( &argc, &argv, &env, _dowildcard, &start_info); + ret = _tmain(argc0, argv + argc - argc0, env); exit(ret); } diff --git a/win32/lib/wincrt1.c b/win32/lib/wincrt1.c index 663fd33..06f42f0 100644 --- a/win32/lib/wincrt1.c +++ b/win32/lib/wincrt1.c @@ -1,5 +1,8 @@ //+--------------------------------------------------------------------------- +// _UNICODE for tchar.h, UNICODE for API +#include + #include #include @@ -9,10 +12,28 @@ void __set_app_type(int); void _controlfp(unsigned a, unsigned b); -int _winstart(void) +#ifdef _UNICODE +#define __tgetmainargs __wgetmainargs +#define _twinstart _wwinstart +#define _runtwinmain _runwwinmain +int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int); +#else +#define __tgetmainargs __getmainargs +#define _twinstart _winstart +#define _runtwinmain _runwinmain +#endif + +typedef struct +{ + int newmode; +} _startupinfo; // CLI Vs GUI + +int __cdecl __tgetmainargs(int *pargc, _TCHAR ***pargv, _TCHAR ***penv, int globb, _startupinfo*); + +int _twinstart(void) { __TRY__ - char *szCmd; + _TCHAR *szCmd; STARTUPINFO startinfo; int fShow; int ret; @@ -22,19 +43,19 @@ int _winstart(void) szCmd = GetCommandLine(); if (szCmd) { - while (' ' == *szCmd) + while (__T(' ') == *szCmd) szCmd++; - if ('\"' == *szCmd) { + if (__T('\"') == *szCmd) { while (*++szCmd) - if ('\"' == *szCmd) { + if (__T('\"') == *szCmd) { szCmd++; break; } } else { - while (*szCmd && ' ' != *szCmd) + while (*szCmd && __T(' ') != *szCmd) szCmd++; } - while (' ' == *szCmd) + while (__T(' ') == *szCmd) szCmd++; } @@ -43,22 +64,30 @@ 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 _runtwinmain(int argc0, /* as tcc passed in */ char **argv0) { - char *szCmd, *p; + _TCHAR *szCmd, *p; + + int argc; + _TCHAR **argv; + _TCHAR **env; + _startupinfo start_info; + + start_info.newmode = 0; + __tgetmainargs(&argc, &argv, &env, 0, &start_info); p = GetCommandLine(); szCmd = NULL; - if (argc > 1) - szCmd = strstr(p, argv[1]); + if (argc0 > 1) + szCmd = _tcsstr(p, argv[argc - argc0 + 1]); if (NULL == szCmd) - szCmd = ""; - else if (szCmd > p && szCmd[-1] == '\"') + szCmd = __T(""); + else if (szCmd > p && szCmd[-1] == __T('\"')) --szCmd; _controlfp(0x10000, 0x30000); - return WinMain(GetModuleHandle(NULL), NULL, szCmd, SW_SHOWDEFAULT); + return _tWinMain(GetModuleHandle(NULL), NULL, szCmd, SW_SHOWDEFAULT); }