Mercurial > gub
changeset 6384:bd27c9462d99
Fix mingw::ghostscript
unicode commandline args
author | Masamichi Hosoda <trueroad@users.noreply.github.com> |
---|---|
date | Sat, 14 Mar 2015 23:14:28 +0900 |
parents | 5b8eb8bbe753 |
children | 7941370171bf |
files | gub/specs/ghostscript.py patches/ghostscript-9.15-windows-dxmain.patch |
diffstat | 2 files changed, 277 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/gub/specs/ghostscript.py Sat Mar 14 11:12:49 2015 +0900 +++ b/gub/specs/ghostscript.py Sat Mar 14 23:14:28 2015 +0900 @@ -234,7 +234,9 @@ class Ghostscript__mingw (Ghostscript): exe = '.exe' - patches = Ghostscript.patches + patches = Ghostscript.patches + [ + 'ghostscript-9.15-windows-dxmain.patch' + ] def __init__ (self, settings, source): Ghostscript.__init__ (self, settings, source) # Configure (compile) without -mwindows for console
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/patches/ghostscript-9.15-windows-dxmain.patch Sat Mar 14 23:14:28 2015 +0900 @@ -0,0 +1,274 @@ +--- a/psi/dxmainc.c 2014-09-22 19:17:33.000000000 +0900 ++++ b/psi/dxmainc.c 2015-03-14 23:03:03.633481800 +0900 +@@ -28,10 +28,12 @@ + * gcc -shared -Wl,-soname,libgs.so.7 -o libgs.so.7.00 file.o -lc + */ + ++#include "windows_.h" + #include <stdio.h> + #include <stdlib.h> + #include <string.h> + #include <unistd.h> ++#include <io.h> + #include <fcntl.h> + #include <errno.h> + #define __PROTOTYPES__ +@@ -52,7 +54,7 @@ + static int + gsdll_stdin(void *instance, char *buf, int len) + { +- return read(fileno(stdin), buf, len); ++ return _read(fileno(stdin), buf, len); + } + + static int +@@ -71,18 +73,196 @@ + return len; + } + ++/* porting from dwmainc.c */ ++#ifndef GS_NO_UTF8 ++/* stdio functions - versions that translate to/from utf-8 */ ++static int ++gsdll_stdin_utf8(void *instance, char *buf, int len) ++{ ++ static WCHAR thiswchar = 0; /* wide character to convert to multiple bytes */ ++ static int nmore = 0; /* number of additional encoding bytes to generate */ ++ UINT consolecp = 0; ++ int nret = 0; /* number of bytes returned to caller */ ++ int i; ++ ++ while (len) { ++ while (len && nmore) { ++ nmore--; ++ *buf++ = 0x80 | ((thiswchar >> (6 * nmore)) & 0x3F), nret++; ++ len--; ++ } ++ while (len) { ++ if (0 >= _read(fileno(stdin), buf, 1)) ++ return nret; ++ nret++, buf++, len--; ++ if (buf[-1] == '\n') ++ /* return at end of line (note: no traslation needed) */ ++ return nret; ++ else if ((unsigned char)buf[-1] <= 0x7F) ++ /* no translation needed for 7-bit ASCII codes */ ++ continue; ++ else { ++ /* extended character, may be double */ ++ BYTE dbcsstr[2]; ++ ++ dbcsstr[0] = buf[-1]; ++ if (!consolecp) ++ consolecp = GetConsoleCP(); ++ thiswchar = L'?'; /* initialize in case the conversion below fails */ ++ if (IsDBCSLeadByteEx(consolecp, dbcsstr[0])) { ++ /* double-byte character code, fetch the trail byte */ ++ _read(fileno(stdin), &dbcsstr[1], 1); ++ MultiByteToWideChar(consolecp, 0, dbcsstr, 2, &thiswchar, 1); ++ } ++ else { ++ MultiByteToWideChar(consolecp, 0, dbcsstr, 1, &thiswchar, 1); ++ } ++ /* convert thiswchar to utf-8 */ ++ if (thiswchar <= 0x007F) { /* encoded as single byte */ ++ buf[-1] = (char)thiswchar; ++ } else if (thiswchar <= 0x07FF) { /* encoded as 2 bytes */ ++ buf[-1] = 0xC0 | ((thiswchar >> 6) & 0x1F); ++ nmore = 1; ++ break; ++ } else if (thiswchar <= 0xFFFF) { /* encoded as 3 bytes */ ++ buf[-1] = 0xE0 | ((thiswchar >> 12) & 0xF); ++ nmore = 2; ++ break; ++ } else ++ /* note: codes outside the BMP not handled */ ++ buf[-1] = '?'; ++ } ++ } ++ } ++ return nret; ++} ++ ++static void ++gsdll_utf8write(FILE *stdwr, const char *str, int len, WCHAR *thiswchar, int *nmore) ++{ ++ UINT consolecp = 0; ++ ++ while (len) { ++ const char *str0; ++ ++ /* write ASCII chars without translation */ ++ for (str0 = str; len && !(*str & 0x80); str++, len--); ++ if (str > str0) { ++ if (*nmore) { ++ /* output previous, incomplete utf-8 sequence as ASCII "?" */ ++ fwrite("?", 1, 1, stdwr); ++ *nmore = 0, *thiswchar = 0; ++ } ++ fwrite(str0, 1, str - str0, stdwr); ++ } ++ /* accumulate lead/trail bytes into *thiswchar */ ++ for (; len; str++, len--) { ++ switch (*str & 0xC0) { ++ case 0x80: /* trail byte */ ++ if (*nmore) { ++ (*nmore)--; ++ *thiswchar |= (WCHAR)(unsigned char)(*str & 0x3F) << (6 * *nmore); ++ } ++ else { ++ /* lead byte missing; output unexpected trail byte as ASCII "?" */ ++ *nmore = 0; ++ *thiswchar = L'?'; ++ } ++ break; ++ case 0xC0: /* lead byte */ ++ if (*nmore) ++ /* output previous, incomplete utf-8 sequence as ASCII "?" */ ++ fwrite("?", 1, 1, stdwr); ++ if (!(*str & 0x20)) ++ *nmore = 1; /* 2-byte encoding */ ++ else if (!(*str & 0x10)) ++ *nmore = 2; /* 3-byte encoding */ ++ else if (!(*str & 0x08)) ++ *nmore = 3; /* 4-byte encoding */ ++ else ++ *nmore = 0; /* restricted (> 4) or invalid encodings */ ++ if (*nmore) ++ *thiswchar = (WCHAR)(unsigned char)(*str & (0x3F >> *nmore)) << (6 * *nmore); ++ else { ++ /* output invalid encoding as ASCII "?" */ ++ *thiswchar = L'?'; ++ } ++ break; ++ default: /* cannot happen because *str has MSB set */ ++ break; ++ } ++ /* output wide character if finished */ ++ if (!*nmore) { ++ char mbstr[8]; ++ int n_mbstr; ++ ++ if (!consolecp) ++ consolecp = GetConsoleOutputCP(); ++ n_mbstr = WideCharToMultiByte(consolecp, 0, thiswchar, 1, mbstr, sizeof mbstr, NULL, NULL); ++ if (n_mbstr <= 0) ++ fwrite("?", 1, 1, stdwr); ++ else ++ fwrite(mbstr, 1, n_mbstr, stdwr); ++ *thiswchar = 0; /* cleanup */ ++ str++, len--; ++ break; ++ } ++ } ++ } ++ fflush(stdwr); ++} ++ ++static int ++gsdll_stdout_utf8(void *instance, const char *utf8str, int bytelen) ++{ ++ static WCHAR thiswchar = 0; /* accumulates the bits from multiple encoding bytes */ ++ static int nmore = 0; /* expected number of additional encoding bytes */ ++ ++ gsdll_utf8write(stdout, utf8str, bytelen, &thiswchar, &nmore); ++ return bytelen; ++} ++ ++static int ++gsdll_stderr_utf8(void *instance, const char *utf8str, int bytelen) ++{ ++ static WCHAR thiswchar = 0; /* accumulates the bits from multiple encoding bytes */ ++ static int nmore = 0; /* expected number of additional encoding bytes */ ++ ++ gsdll_utf8write(stderr, utf8str, bytelen, &thiswchar, &nmore); ++ return bytelen; ++} ++#endif ++ + /*********************************************************************/ + ++#ifdef GS_NO_UTF8 + int main(int argc, char *argv[]) ++#else ++/* porting from dwmainc.c */ ++static int main_utf8(int argc, char *argv[]) ++#endif + { + int exit_status; + int code = 1, code1; + void *instance; + int exit_code; + ++ if (!_isatty(fileno(stdin))) ++ _setmode(fileno(stdin), _O_BINARY); ++ _setmode(fileno(stdout), _O_BINARY); ++ _setmode(fileno(stderr), _O_BINARY); ++ + /* run Ghostscript */ + if ((code = gsapi_new_instance(&instance, NULL)) == 0) { ++#ifdef GS_NO_UTF8 + gsapi_set_stdio(instance, gsdll_stdin, gsdll_stdout, gsdll_stderr); ++#else ++ /* porting from dwmainc.c */ ++ gsapi_set_stdio(instance, ++ _isatty(fileno(stdin)) ? gsdll_stdin_utf8 : gsdll_stdin, ++ _isatty(fileno(stdout)) ? gsdll_stdout_utf8 : gsdll_stdout, ++ _isatty(fileno(stderr)) ? gsdll_stderr_utf8 : gsdll_stderr); ++#endif + code = gsapi_init_with_args(instance, argc, argv); + + if (code == 0) +@@ -111,3 +291,52 @@ + + return exit_status; + } ++ ++/* porting from dwmainc.c */ ++#ifndef GS_NO_UTF8 ++int wmain(int argc, wchar_t *argv[], wchar_t *envp[]) { ++ /* Duplicate args as utf8 */ ++ char **nargv; ++ int i, code; ++ ++ nargv = calloc(argc, sizeof(nargv[0])); ++ if (nargv == NULL) ++ goto err; ++ for (i=0; i < argc; i++) { ++ nargv[i] = malloc(wchar_to_utf8(NULL, argv[i])); ++ if (nargv[i] == NULL) ++ goto err; ++ (void)wchar_to_utf8(nargv[i], argv[i]); ++ } ++ code = main_utf8(argc, nargv); ++ ++ if (0) { ++err: ++ fprintf(stderr, ++ "Ghostscript failed to initialise due to malloc failure\n"); ++ code = -1; ++ } ++ ++ if (nargv) { ++ for (i=0; i<argc; i++) { ++ free(nargv[i]); ++ } ++ free(nargv); ++ } ++ ++ return code; ++} ++#endif ++ ++/* for mingw non-unicode runtime */ ++#ifndef GS_NO_UTF8 ++int __wgetmainargs (int *c, wchar_t ***v, wchar_t ***e, int w, int *s); ++ ++int main(int argc, wchar_t *argv[], wchar_t *envp[]) { ++ int wargc=0, si=0; ++ wchar_t **wargv, **wenvp; ++ ++ __wgetmainargs (&wargc, &wargv, &wenvp, 1, &si); ++ return wmain(wargc, wargv, wenvp); ++} ++#endif