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