Mercurial > gub
view patches/ghostscript-9.15-windows-dxmain.patch @ 6512:ccc20ae889ca default tip guix
mingw::guile-2.0.7 builds.
author | Jan Nieuwenhuizen <janneke@gnu.org> |
---|---|
date | Thu, 24 Mar 2016 08:03:39 +0100 |
parents | a0073109b692 |
children |
line wrap: on
line source
--- a/psi/dxmainc.c 2014-09-22 19:17:33.000000000 +0900 +++ b/psi/dxmainc.c 2015-03-19 22:41:31.286769200 +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__ @@ -40,22 +42,22 @@ const char start_string[] = "systemdict /start get exec\n"; -static int gsdll_stdin(void *instance, char *buf, int len); -static int gsdll_stdout(void *instance, const char *str, int len); -static int gsdll_stdout(void *instance, const char *str, int len); +static int GSDLLCALL gsdll_stdin(void *instance, char *buf, int len); +static int GSDLLCALL gsdll_stdout(void *instance, const char *str, int len); +static int GSDLLCALL gsdll_stdout(void *instance, const char *str, int len); /*********************************************************************/ /* stdio functions */ /* callback for reading stdin */ /* Use async input */ -static int +static int GSDLLCALL gsdll_stdin(void *instance, char *buf, int len) { - return read(fileno(stdin), buf, len); + return _read(fileno(stdin), buf, len); } -static int +static int GSDLLCALL gsdll_stdout(void *instance, const char *str, int len) { fwrite(str, 1, len, stdout); @@ -63,7 +65,7 @@ return len; } -static int +static int GSDLLCALL gsdll_stderr(void *instance, const char *str, int len) { fwrite(str, 1, len, stderr); @@ -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 GSDLLCALL +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 GSDLLCALL +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 GSDLLCALL +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