diff -urp global-6.3.2/libparser/parser.c global-6.3-2/libparser/parser.c --- global-6.3.2/libparser/parser.c 2014-09-04 15:46:14 +1000 +++ global-6.3-2/libparser/parser.c 2014-11-08 23:07:46 +1000 @@ -31,6 +31,11 @@ #include #endif #include +#if defined(_WIN32) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN +#include +#undef SLIST_ENTRY +#endif #include "parser.h" #include "internal.h" @@ -171,6 +176,11 @@ load_plugin_parser(const char *pluginspe if (p != NULL) *p++ = '\0'; q = strchr(lt_dl_name, ':'); +#ifdef _WIN32 + /* Assume a single-character name is a drive letter. */ + if (q == lt_dl_name + 1) + q = strchr(q + 1, ':'); +#endif if (q == NULL) { parser_name = "parser"; } else { @@ -179,11 +189,38 @@ load_plugin_parser(const char *pluginspe die_with_code(2, "syntax error in pluginspec '%s'.", pluginspec); parser_name = q; } +#if defined(_WIN32) && !defined(__CYGWIN__) + /* Bypass libtool and load the DLL directly, relative to us. */ + pent->handle = (lt_dlhandle)LoadLibrary(lt_dl_name); + if (pent->handle == NULL) { + q = strrchr(lt_dl_name, '/'); + if (q == NULL) + q = strrchr(lt_dl_name, '\\'); + if (q != NULL) + lt_dl_name = q + 1; + q = strrchr(lt_dl_name, '.'); + if (q != NULL && strcmp(q, ".la") == 0) + *q = '\0'; + pent->handle = (lt_dlhandle)LoadLibrary(lt_dl_name); + if (pent->handle == NULL) { + char dll[MAX_PATH*2]; + GetModuleFileName(NULL, dll, MAX_PATH); + q = strrchr(dll, '\\'); + sprintf(q+1, "..\\lib\\gtags\\%s", lt_dl_name); + pent->handle = (lt_dlhandle)LoadLibrary(dll); + } + } + if (pent->handle == NULL) + die_with_code(2, "cannot open shared object '%s'.", lt_dl_name); + pent->entry.lt_dl_name = lt_dl_name; + pent->entry.parser = (PVOID)GetProcAddress((HINSTANCE)pent->handle, parser_name); +#else pent->handle = lt_dlopen(lt_dl_name); if (pent->handle == NULL) die_with_code(2, "cannot open shared object '%s'.", lt_dl_name); pent->entry.lt_dl_name = lt_dl_name; pent->entry.parser = lt_dlsym(pent->handle, parser_name); +#endif if (pent->entry.parser == NULL) die_with_code(2, "cannot find symbol '%s' in '%s'.", parser_name, lt_dl_name); pent->entry.parser_name = parser_name; @@ -205,7 +242,11 @@ unload_plugin_parser(void) return; while (!STAILQ_EMPTY(&plugin_list)) { pent = STAILQ_FIRST(&plugin_list); +#if defined(_WIN32) && !defined(__CYGWIN__) + FreeLibrary((HMODULE)pent->handle); +#else lt_dlclose(pent->handle); +#endif STAILQ_REMOVE_HEAD(&plugin_list, next); free(pent); } diff -urp global-6.3.2/libutil/conf.c global-6.3-2/libutil/conf.c --- global-6.3.2/libutil/conf.c 2014-09-04 15:46:14 +1000 +++ global-6.3-2/libutil/conf.c 2014-11-08 13:02:39 +1000 @@ -32,6 +32,10 @@ #else #include #endif +#if defined(_WIN32) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN +#include +#endif #include "gparam.h" #include "char.h" @@ -398,10 +402,11 @@ getconfs(const char *name, STRBUF *sb) if (test("d", DATADIR)) strbuf_puts(sb, DATADIR); else { - const char *name = strrchr(_pgmptr, '\\'); - if (name) - strbuf_nputs(sb, _pgmptr, name+1 - _pgmptr); - strbuf_puts(sb, "..\\share"); + char path[MAX_PATH], *name; + GetModuleFileName(NULL, path, MAX_PATH); + name = strrchr(path, '\\'); + strcpy(name+1, "..\\share"); + strbuf_puts(sb, path); } #else strbuf_puts(sb, DATADIR); diff -urp global-6.3.2/libutil/dbop.c global-6.3-2/libutil/dbop.c --- global-6.3.2/libutil/dbop.c 2014-09-04 15:46:14 +1000 +++ global-6.3-2/libutil/dbop.c 2014-11-08 22:10:17 +1000 @@ -78,11 +78,12 @@ static void start_sort_process(DBOP *); static void terminate_sort_process(DBOP *); static char *sortnotfound = "POSIX sort program not found. If available, the program will be speed up.\nPlease see ./configure --help."; /* - * 1. DJGPP + * 1. DJGPP/Windows */ -#if defined(__DJGPP__) +#if defined(__DJGPP__) || defined(_WIN32) /* - * Just ignored. DJGPP version doesn't use sorted writing. + * Just ignored. DJGPP version doesn't use sorted writing; Windows (including + * Cygwin) is slightly quicker without it. */ static void start_sort_process(DBOP *dbop) { @@ -93,78 +94,7 @@ terminate_sort_process(DBOP *dbop) { return; } /* - * 2. WIN32 - */ -#elif defined(_WIN32) && !defined(__CYGWIN__) -#define WIN32_LEAN_AND_MEAN -#include -/* - * sort is included with the binary distribution - */ -static char argv[] = "sort -k 1,1"; -static void -start_sort_process(DBOP *dbop) { - HANDLE opipe[2], ipipe[2]; - SECURITY_ATTRIBUTES sa; - STARTUPINFO si; - PROCESS_INFORMATION pi; - const char* lc_all; - char sort[MAX_PATH]; - char* path; - static int informed; - - if (!strcmp(POSIX_SORT, "no")) - return; - if (informed) - return; - /* - * force using sort in the same directory as the program, to avoid - * using the Windows one - */ - path = strrchr(_pgmptr, '\\'); - sprintf(sort, "%.*s\\sort.exe", path - _pgmptr, _pgmptr); - if (!test("fx", sort)) { - warning(sortnotfound); - informed = 1; - return; - } - - sa.nLength = sizeof(sa); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = NULL; - if (!CreatePipe(&opipe[0], &opipe[1], &sa, 0) || - !CreatePipe(&ipipe[0], &ipipe[1], &sa, 0)) - die("CreatePipe failed."); - SetHandleInformation(opipe[1], HANDLE_FLAG_INHERIT, 0); - SetHandleInformation(ipipe[0], HANDLE_FLAG_INHERIT, 0); - ZeroMemory(&si, sizeof(si)); - si.cb = sizeof(si); - si.hStdInput = opipe[0]; - si.hStdOutput = ipipe[1]; - si.hStdError = GetStdHandle(STD_ERROR_HANDLE); - si.dwFlags = STARTF_USESTDHANDLES; - lc_all = getenv("LC_ALL"); - if (lc_all == NULL) - lc_all = ""; - set_env("LC_ALL", "C"); - CreateProcess(sort, argv, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); - set_env("LC_ALL", lc_all); - CloseHandle(opipe[0]); - CloseHandle(ipipe[1]); - CloseHandle(pi.hThread); - dbop->pid = pi.hProcess; - dbop->sortout = fdopen(_open_osfhandle((long)opipe[1], _O_WRONLY), "w"); - dbop->sortin = fdopen(_open_osfhandle((long)ipipe[0], _O_RDONLY), "r"); - if (dbop->sortout == NULL || dbop->sortin == NULL) - die("fdopen failed."); -} -static void -terminate_sort_process(DBOP *dbop) { - WaitForSingleObject(dbop->pid, INFINITE); - CloseHandle(dbop->pid); -} -/* - * 3. UNIX and CYGWIN + * 2. UNIX */ #else #include diff -urp global-6.3.2/plugin-factory/exuberant-ctags.c global-6.3-2/plugin-factory/exuberant-ctags.c --- global-6.3.2/plugin-factory/exuberant-ctags.c 2014-09-04 15:46:15 +1000 +++ global-6.3-2/plugin-factory/exuberant-ctags.c 2014-11-08 18:12:14 +1000 @@ -22,9 +22,6 @@ #include #endif #include -#if !defined(_WIN32) || defined(__CYGWIN__) -#include -#endif #include #include #include @@ -51,24 +48,15 @@ #define LANGMAP_OPTION "--langmap=" #define INITIAL_BUFSIZE 1024 -static char *argv[] = { - EXUBERANT_CTAGS, - NULL, -#ifdef USE_TYPE_STRING - "--gtags", -#endif - "-xu", - "--filter", - "--filter-terminator=" TERMINATOR "\n", - "--format=1", - NULL -}; -static pid_t pid; static FILE *ip, *op; static char *linebuf; static size_t bufsize; static char *ctagsnotfound = "Exuberant Ctags not found. Please see ./configure --help."; +#ifdef __GNUC__ +static void terminate_ctags(void) __attribute__((destructor)); +#endif + static void copy_langmap_converting_cpp(char *dst, const char *src) { @@ -89,6 +77,84 @@ copy_langmap_converting_cpp(char *dst, c strcpy(dst, src); } +#if defined(_WIN32) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN +#include +#include +static HANDLE pid; +static char argv[] = "ctags " + "--gtags " + "-xu --filter --filter-terminator=" TERMINATOR "\n " + "--format=1 " LANGMAP_OPTION; +static void +start_ctags(const struct parser_param *param) +{ + HANDLE opipe[2], ipipe[2]; + SECURITY_ATTRIBUTES sa; + STARTUPINFO si; + PROCESS_INFORMATION pi; + char* arg; + + arg = malloc(sizeof(argv) + strlen(param->langmap)); + if (arg == NULL) + param->die("short of memory."); + strcpy(arg, argv); + copy_langmap_converting_cpp(arg + sizeof(argv) - 1, param->langmap); + + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + if (!CreatePipe(&opipe[0], &opipe[1], &sa, 0) || + !CreatePipe(&ipipe[0], &ipipe[1], &sa, 0)) + param->die("CreatePipe failed."); + SetHandleInformation(opipe[1], HANDLE_FLAG_INHERIT, 0); + SetHandleInformation(ipipe[0], HANDLE_FLAG_INHERIT, 0); + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.hStdInput = opipe[0]; + si.hStdOutput = ipipe[1]; + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + si.dwFlags = STARTF_USESTDHANDLES; + CreateProcess(NULL, arg, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); + CloseHandle(opipe[0]); + CloseHandle(ipipe[1]); + CloseHandle(pi.hThread); + pid = pi.hProcess; + op = fdopen(_open_osfhandle((long)opipe[1], _O_WRONLY), "w"); + ip = fdopen(_open_osfhandle((long)ipipe[0], _O_RDONLY), "r"); + if (ip == NULL || op == NULL) + param->die("fdopen failed."); + + bufsize = INITIAL_BUFSIZE; + linebuf = malloc(bufsize); + if (linebuf == NULL) + param->die("short of memory."); +} +static void +terminate_ctags(void) { + if (op == NULL) + return; + free(linebuf); + fclose(op); + fclose(ip); + WaitForSingleObject(pid, INFINITE); + CloseHandle(pid); +} +#else +#include +static pid_t pid; +static char *argv[] = { + EXUBERANT_CTAGS, + NULL, +#ifdef USE_TYPE_STRING + "--gtags", +#endif + "-xu", + "--filter", + "--filter-terminator=" TERMINATOR "\n", + "--format=1", + NULL +}; static void start_ctags(const struct parser_param *param) { @@ -134,10 +200,6 @@ start_ctags(const struct parser_param *p param->die("short of memory."); } -#ifdef __GNUC__ -static void terminate_ctags(void) __attribute__((destructor)); -#endif - static void terminate_ctags(void) { @@ -149,6 +211,7 @@ terminate_ctags(void) while (waitpid(pid, NULL, 0) < 0 && errno == EINTR) ; } +#endif static char * get_line(const struct parser_param *param) diff -urp global-6.3.2/plugin-factory/pygments-parser.c global-6.3-2/plugin-factory/pygments-parser.c --- global-6.3.2/plugin-factory/pygments-parser.c 2014-09-04 15:46:15 +1000 +++ global-6.3-2/plugin-factory/pygments-parser.c 2014-11-10 21:26:24 +1000 @@ -22,9 +22,6 @@ #include #endif #include -#if !defined(_WIN32) || defined(__CYGWIN__) -#include -#endif #include #include #include @@ -43,7 +40,12 @@ #include "parser.h" +#if defined(_WIN32) && !defined(__CYGWIN__) +#define PYTHON "python" +#define PYGMENTS_PARSER "../share/gtags/script/pygments_parser.py" +#else #define PYGMENTS_PARSER (DATADIR "/gtags/script/pygments_parser.py") +#endif /* * Function layer plugin parser sample @@ -53,16 +55,14 @@ #define LANGMAP_OPTION "--langmap=" #define INITIAL_BUFSIZE 1024 -static char *argv[] = { - PYGMENTS_PARSER, - NULL, - NULL -}; -static pid_t pid; static FILE *ip, *op; static char *linebuf; static size_t bufsize; +#ifdef __GNUC__ +static void terminate_process(void) __attribute__((destructor)); +#endif + static void copy_langmap_converting_cpp(char *dst, const char *src) { @@ -83,6 +83,80 @@ copy_langmap_converting_cpp(char *dst, c strcpy(dst, src); } +#if defined(_WIN32) && !defined(__CYGWIN__) +#define WIN32_LEAN_AND_MEAN +#include +#include +static HANDLE pid; +static void +start_process(const struct parser_param *param) +{ + HANDLE opipe[2], ipipe[2]; + SECURITY_ATTRIBUTES sa; + STARTUPINFO si; + PROCESS_INFORMATION pi; + char* arg; + char parser[MAX_PATH*2]; + size_t len; + + GetModuleFileName(NULL, parser, MAX_PATH); + arg = strrchr(parser, '\\'); + strcpy(arg+1, PYGMENTS_PARSER); + arg = malloc(sizeof(PYTHON) + strlen(parser) + sizeof(LANGMAP_OPTION) + strlen(param->langmap) + 1); + if (arg == NULL) + param->die("short of memory."); + len = sprintf(arg, "%s %s %s", PYTHON, parser, LANGMAP_OPTION); + copy_langmap_converting_cpp(arg + len, param->langmap); + + sa.nLength = sizeof(sa); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = NULL; + if (!CreatePipe(&opipe[0], &opipe[1], &sa, 0) || + !CreatePipe(&ipipe[0], &ipipe[1], &sa, 0)) + param->die("CreatePipe failed."); + SetHandleInformation(opipe[1], HANDLE_FLAG_INHERIT, 0); + SetHandleInformation(ipipe[0], HANDLE_FLAG_INHERIT, 0); + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + si.hStdInput = opipe[0]; + si.hStdOutput = ipipe[1]; + si.hStdError = GetStdHandle(STD_ERROR_HANDLE); + si.dwFlags = STARTF_USESTDHANDLES; + if (!CreateProcess(NULL, arg, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) + param->die("no python"); + CloseHandle(opipe[0]); + CloseHandle(ipipe[1]); + CloseHandle(pi.hThread); + pid = pi.hProcess; + op = fdopen(_open_osfhandle((long)opipe[1], _O_WRONLY), "w"); + ip = fdopen(_open_osfhandle((long)ipipe[0], _O_RDONLY), "r"); + if (ip == NULL || op == NULL) + param->die("fdopen failed."); + + bufsize = INITIAL_BUFSIZE; + linebuf = malloc(bufsize); + if (linebuf == NULL) + param->die("short of memory."); +} +static void +terminate_process(void) { + if (op == NULL) + return; + free(linebuf); + fclose(op); + fclose(ip); + WaitForSingleObject(pid, INFINITE); + CloseHandle(pid); +} +#else +#include +static char *argv[] = { + PYGMENTS_PARSER, + NULL, + NULL +}; +static pid_t pid; + static void start_process(const struct parser_param *param) { @@ -126,10 +200,6 @@ start_process(const struct parser_param param->die("short of memory."); } -#ifdef __GNUC__ -static void terminate_process(void) __attribute__((destructor)); -#endif - static void terminate_process(void) { @@ -141,6 +211,7 @@ terminate_process(void) while (waitpid(pid, NULL, 0) < 0 && errno == EINTR) ; } +#endif static char * get_line(const struct parser_param *param) diff -urp global-6.3.2/plugin-factory/pygments_parser.py.in global-6.3-2/plugin-factory/pygments_parser.py.in --- global-6.3.2/plugin-factory/pygments_parser.py.in 2014-09-04 15:46:15 +1000 +++ global-6.3-2/plugin-factory/pygments_parser.py.in 2014-11-11 12:30:07 +1000 @@ -16,6 +16,8 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see . +from __future__ import print_function +import io import os import subprocess import sys @@ -39,7 +41,12 @@ LANGUAGE_ALIASES = { # All punctuation characters except some characters which are valid # identifier characters in some languages -PUNCTUATION_CHARACTERS = string.punctuation.translate(None, '-_.') +if sys.version_info < (3,): + PUNCTUATION_CHARACTERS = string.punctuation.translate(None, '-_.') +else: + PUNCTUATION_CHARACTERS = string.punctuation.translate(str.maketrans('', '', '-_.')) + +CLOSEFDS = sys.platform != 'win32'; TERMINATOR = '###terminator###\n' @@ -115,23 +122,33 @@ class PygmentsParser: def read_file(self, path): try: - with open(path, 'r') as f: - text = f.read() - return text + if sys.version_info < (3,): + with open(path, 'r') as f: + text = f.read() + return text + else: + with open(path, 'r', encoding='latin1') as f: + text = f.read() + return text except Exception as e: - print >> sys.stderr, e + print(e, file=sys.stderr) return None class CtagsParser: def __init__(self, ctags_command, options): self.process = subprocess.Popen([ctags_command, '-xu', '--filter', '--filter-terminator=' + TERMINATOR, '--format=1'], bufsize=-1, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True) - self.child_stdout = self.process.stdout + stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=CLOSEFDS, + universal_newlines=True) + if sys.version_info < (3,): + self.child_stdout = self.process.stdout + else: + self.child_stdout = io.TextIOWrapper(self.process.stdout.buffer, encoding='latin1') + sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='latin1') self.child_stdin = self.process.stdin self.options = options def parse(self, path): - print >> self.child_stdin, path + print(path, file=self.child_stdin) self.child_stdin.flush() result = {} while True: @@ -173,6 +190,9 @@ def parse_langmap(string): for ext in exts.split('.'): if ext: langmap['.' + ext] = lang + if sys.platform == 'win32': + langmap['.' + ext.upper()] = lang + langmap['.' + ext.lower()] = lang return langmap def handle_requests(langmap, options): @@ -188,13 +208,13 @@ def handle_requests(langmap, options): break path = path.rstrip() tags = parser.parse(path) - for (isdef, tag, lnum),image in tags.iteritems(): + for (isdef, tag, lnum),image in tags.items(): if isdef: typ = 'D' else: typ = 'R' - print typ, tag, lnum, path, image - print TERMINATOR, + print(typ, tag, lnum, path, image) + print(TERMINATOR, end='') sys.stdout.flush() def get_parser_options_from_env(parser_options):