comparison mercurial/exewrapper.c @ 40396:973ff03d9bc0

exewrapper: convert to _tcsxxx functions for Unicode compatability This fixes more than 50 tests on py3 on Windows when enabled, mostly hooks and such that invoked `hg` directly. 187 left to go. I skipped doing the abort printing with Unicode because of apparent issues with MinGW [1]. It may be moot though, as MinGW isn't listed as a supported compiler after 3.4 [2]. [1] https://stackoverflow.com/questions/17700797/printf-wprintf-s-s-ls-char-and-wchar-errors-not-announced-by-a-compil [2] https://wiki.python.org/moin/WindowsCompilers
author Matt Harbison <matt_harbison@yahoo.com>
date Fri, 19 Oct 2018 18:32:13 -0400
parents aca727359ec5
children 36ba91e06948
comparison
equal deleted inserted replaced
40395:aca727359ec5 40396:973ff03d9bc0
6 This software may be used and distributed according to the terms of the 6 This software may be used and distributed according to the terms of the
7 GNU General Public License version 2 or any later version. 7 GNU General Public License version 2 or any later version.
8 */ 8 */
9 9
10 #include <stdio.h> 10 #include <stdio.h>
11 #include <tchar.h>
11 #include <windows.h> 12 #include <windows.h>
12 13
13 #include "hgpythonlib.h" 14 #include "hgpythonlib.h"
14 15
15 #ifdef __GNUC__ 16 #ifdef __GNUC__
19 } 20 }
20 int strcpy_s(char *d, size_t n, const char *s) 21 int strcpy_s(char *d, size_t n, const char *s)
21 { 22 {
22 return !strncpy(d, s, n); 23 return !strncpy(d, s, n);
23 } 24 }
25
26 #define _tcscpy_s strcpy_s
27 #define _tcscat_s strcat_s
28 #define _countof(array) (sizeof(array)/sizeof(array[0]))
24 #endif 29 #endif
25 30
26 static char pyscript[MAX_PATH + 10]; 31 static TCHAR pyscript[MAX_PATH + 10];
27 static char pyhome[MAX_PATH + 10]; 32 static TCHAR pyhome[MAX_PATH + 10];
28 static char pydllfile[MAX_PATH + 10]; 33 static TCHAR pydllfile[MAX_PATH + 10];
29 34
30 int main(int argc, char *argv[]) 35 int _tmain(int argc, TCHAR *argv[])
31 { 36 {
32 char *p; 37 TCHAR *p;
33 int ret; 38 int ret;
34 int i; 39 int i;
35 int n; 40 int n;
36 char **pyargv; 41 TCHAR **pyargv;
37 WIN32_FIND_DATA fdata; 42 WIN32_FIND_DATA fdata;
38 HANDLE hfind; 43 HANDLE hfind;
39 const char *err; 44 const char *err;
40 HMODULE pydll; 45 HMODULE pydll;
41 void(__cdecl * Py_SetPythonHome)(char *home); 46 void(__cdecl * Py_SetPythonHome)(TCHAR *home);
42 int(__cdecl * Py_Main)(int argc, char *argv[]); 47 int(__cdecl * Py_Main)(int argc, TCHAR *argv[]);
43 48
44 if (GetModuleFileName(NULL, pyscript, sizeof(pyscript)) == 0) { 49 if (GetModuleFileName(NULL, pyscript, _countof(pyscript)) == 0) {
45 err = "GetModuleFileName failed"; 50 err = "GetModuleFileName failed";
46 goto bail; 51 goto bail;
47 } 52 }
48 53
49 p = strrchr(pyscript, '.'); 54 p = _tcsrchr(pyscript, '.');
50 if (p == NULL) { 55 if (p == NULL) {
51 err = "malformed module filename"; 56 err = "malformed module filename";
52 goto bail; 57 goto bail;
53 } 58 }
54 *p = 0; /* cut trailing ".exe" */ 59 *p = 0; /* cut trailing ".exe" */
55 strcpy_s(pyhome, sizeof(pyhome), pyscript); 60 _tcscpy_s(pyhome, _countof(pyhome), pyscript);
56 61
57 hfind = FindFirstFile(pyscript, &fdata); 62 hfind = FindFirstFile(pyscript, &fdata);
58 if (hfind != INVALID_HANDLE_VALUE) { 63 if (hfind != INVALID_HANDLE_VALUE) {
59 /* pyscript exists, close handle */ 64 /* pyscript exists, close handle */
60 FindClose(hfind); 65 FindClose(hfind);
61 } else { 66 } else {
62 /* file pyscript isn't there, take <pyscript>exe.py */ 67 /* file pyscript isn't there, take <pyscript>exe.py */
63 strcat_s(pyscript, sizeof(pyscript), "exe.py"); 68 _tcscat_s(pyscript, _countof(pyscript), _T("exe.py"));
64 } 69 }
65 70
66 pydll = NULL; 71 pydll = NULL;
67 72
68 p = strrchr(pyhome, '\\'); 73 p = _tcsrchr(pyhome, _T('\\'));
69 if (p == NULL) { 74 if (p == NULL) {
70 err = "can't find backslash in module filename"; 75 err = "can't find backslash in module filename";
71 goto bail; 76 goto bail;
72 } 77 }
73 *p = 0; /* cut at directory */ 78 *p = 0; /* cut at directory */
74 79
75 /* check for private Python of HackableMercurial */ 80 /* check for private Python of HackableMercurial */
76 strcat_s(pyhome, sizeof(pyhome), "\\hg-python"); 81 _tcscat_s(pyhome, _countof(pyhome), _T("\\hg-python"));
77 82
78 hfind = FindFirstFile(pyhome, &fdata); 83 hfind = FindFirstFile(pyhome, &fdata);
79 if (hfind != INVALID_HANDLE_VALUE) { 84 if (hfind != INVALID_HANDLE_VALUE) {
80 /* Path .\hg-python exists. We are probably in HackableMercurial 85 /* Path .\hg-python exists. We are probably in HackableMercurial
81 scenario, so let's load python dll from this dir. */ 86 scenario, so let's load python dll from this dir. */
82 FindClose(hfind); 87 FindClose(hfind);
83 strcpy_s(pydllfile, sizeof(pydllfile), pyhome); 88 _tcscpy_s(pydllfile, _countof(pydllfile), pyhome);
84 strcat_s(pydllfile, sizeof(pydllfile), "\\" HGPYTHONLIB ".dll"); 89 _tcscat_s(pydllfile, _countof(pydllfile), _T("\\") _T(HGPYTHONLIB)
90 _T(".dll"));
85 pydll = LoadLibrary(pydllfile); 91 pydll = LoadLibrary(pydllfile);
86 if (pydll == NULL) { 92 if (pydll == NULL) {
87 err = "failed to load private Python DLL " HGPYTHONLIB 93 err = "failed to load private Python DLL " HGPYTHONLIB ".dll";
88 ".dll";
89 goto bail; 94 goto bail;
90 } 95 }
91 Py_SetPythonHome = 96 Py_SetPythonHome =
92 (void *)GetProcAddress(pydll, "Py_SetPythonHome"); 97 (void *)GetProcAddress(pydll, "Py_SetPythonHome");
93 if (Py_SetPythonHome == NULL) { 98 if (Py_SetPythonHome == NULL) {
96 } 101 }
97 Py_SetPythonHome(pyhome); 102 Py_SetPythonHome(pyhome);
98 } 103 }
99 104
100 if (pydll == NULL) { 105 if (pydll == NULL) {
101 pydll = LoadLibrary(HGPYTHONLIB ".dll"); 106 pydll = LoadLibrary(_T(HGPYTHONLIB) _T(".dll"));
102 if (pydll == NULL) { 107 if (pydll == NULL) {
103 err = "failed to load Python DLL " HGPYTHONLIB ".dll"; 108 err = "failed to load Python DLL " HGPYTHONLIB ".dll";
104 goto bail; 109 goto bail;
105 } 110 }
106 } 111 }
116 already be there, if the script spawned a child process of itself, in 121 already be there, if the script spawned a child process of itself, in
117 the same way as it got called, that is, with the pyscript already in 122 the same way as it got called, that is, with the pyscript already in
118 place. So we optionally accept the pyscript as the first argument 123 place. So we optionally accept the pyscript as the first argument
119 (argv[1]), letting our exe taking the role of the python interpreter. 124 (argv[1]), letting our exe taking the role of the python interpreter.
120 */ 125 */
121 if (argc >= 2 && strcmp(argv[1], pyscript) == 0) { 126 if (argc >= 2 && _tcscmp(argv[1], pyscript) == 0) {
122 /* 127 /*
123 pyscript is already in the args, so there is no need to copy 128 pyscript is already in the args, so there is no need to copy
124 the args and we can directly call the python interpreter with 129 the args and we can directly call the python interpreter with
125 the original args. 130 the original args.
126 */ 131 */
130 /* 135 /*
131 Start assembling the args for the Python interpreter call. We put the 136 Start assembling the args for the Python interpreter call. We put the
132 name of our exe (argv[0]) in the position where the python.exe 137 name of our exe (argv[0]) in the position where the python.exe
133 canonically is, and insert the pyscript next. 138 canonically is, and insert the pyscript next.
134 */ 139 */
135 pyargv = malloc((argc + 5) * sizeof(char *)); 140 pyargv = malloc((argc + 5) * sizeof(TCHAR *));
136 if (pyargv == NULL) { 141 if (pyargv == NULL) {
137 err = "not enough memory"; 142 err = "not enough memory";
138 goto bail; 143 goto bail;
139 } 144 }
140 n = 0; 145 n = 0;