Hello,
I've redone the patch because I had moved the whole arg building into the child
process (on non-Windows) which is both inefficient and obfuscates the diff.
Regards.
--
Olivier Certner
--- gtags.conf.in.~1.55.~ 2017-12-12 15:05:24.000000000 +0100
+++ gtags.conf.in 2023-04-07 14:39:50.709124000 +0200
@@ -181,6 +181,7 @@
universal-ctags|setting to use Universal Ctags plug-in parser:\
:tc=common:\
:ctagscom=@UNIVERSAL_CTAGS@:\
+ :ctagsoptfile=:\
:ctagslib=$libdir/gtags/universal-ctags.la:\
:langmap=Ada\:.adb.ads.Ada:\
:langmap=Ant\:(build.xml)(*.build.xml).ant.xml:\
--- plugin-factory/Makefile.am.~1.13.~ 2023-04-06 21:28:23.170662000 +0200
+++ plugin-factory/Makefile.am 2023-04-07 12:02:21.191300000 +0200
@@ -22,7 +22,7 @@
exuberant_ctags_la_LDFLAGS = -module -avoid-version -no-undefined
# Univercal Ctags parser
universal_ctags_la_SOURCES = exuberant-ctags.c
-universal_ctags_la_CFLAGS = -DUSE_EXTRA_FIELDS
+universal_ctags_la_CFLAGS = -DUNIVERSAL_CTAGS_FLAVOR
universal_ctags_la_LDFLAGS = -module -avoid-version -no-undefined
# Pygments parser
--- plugin-factory/exuberant-ctags.c.~1.15.~ 2021-10-26 01:00:31.000000000 +0200
+++ plugin-factory/exuberant-ctags.c 2023-04-07 14:37:28.053247000 +0200
@@ -49,6 +49,9 @@
#define TERMINATOR "###terminator###"
#define LANGMAP_OPTION "--langmap="
+#if defined(UNIVERSAL_CTAGS_FLAVOR)
+#define OPTIONS_OPTION "--options="
+#endif
#define INITIAL_BUFSIZE 1024
static FILE *ip, *op;
@@ -60,13 +63,14 @@
* In execution phase, plug-in parser get the value from the configuration file
* (gtags.conf, $HOME/.globalrc) if it is defined.
*/
-#if defined(USE_EXTRA_FIELDS)
+#if defined(UNIVERSAL_CTAGS_FLAVOR)
static char *ctagscom = UNIVERSAL_CTAGS;
-static const char *ctagsnotfound = "Universal Ctags not found. Please see ./configure --help.";
+static const char *ctagsnotfound = "No Universal Ctags executable specified."
#else
static char *ctagscom = EXUBERANT_CTAGS;
-static const char *ctagsnotfound = "Exuberant Ctags not found. Please see ./configure --help.";
+static const char *ctagsnotfound = "No Exuberant Ctags executable specified."
#endif
+" Specify through ./configure or the 'ctagscom' configuration variable.";
#ifdef __GNUC__
static void terminate_ctags(void) __attribute__((destructor));
@@ -98,7 +102,8 @@
#include <fcntl.h>
static HANDLE pid;
static char argv[] = "\" "
-#if defined(USE_EXTRA_FIELDS)
+#if defined(UNIVERSAL_CTAGS_FLAVOR)
+ "--quiet --options=NONE "
"\"--_xformat=%R %-16N %4n %-16F %C\" "
"--extras=+r "
"--fields=+r "
@@ -116,21 +121,58 @@
SECURITY_ATTRIBUTES sa;
STARTUPINFO si;
PROCESS_INFORMATION pi;
- char* arg;
+ char* org_arg, arg;
char *path = param->getconf("ctagscom");
+ size_t ctagscom_len;
+ size_t const langmap_len = strlen(param->langmap);
+#ifdef UNIVERSAL_CTAGS_FLAVOR
+ char const * options_file = param->getconf("ctagsoptfile");
+ size_t full_options_file_len;
- if (path && strlen(path) > 0 && strcmp(path, "no") != 0)
+ if (options_file != NULL &&
+ (!options_file[0] || !strcmp(options_file, "no"))) {
+ free(options_file);
+ options_file = NULL;
+ }
+
+ full_options_file_len = options_file == NULL ? 0 :
+ strlen(options_file) + sizeof(OPTIONS_OPTION) - 1 + 1 /*SPACE*/;
+#endif
+
+ if (path && path[0] && strcmp(path, "no") != 0)
ctagscom = path;
- if (!ctagscom || !strlen(ctagscom) || !strcmp(ctagscom, "no"))
+ if (!ctagscom || !(ctagscom_len = strlen(ctagscom)) ||
+ !strcmp(ctagscom, "no"))
param->die(ctagsnotfound);
- arg = malloc(1 + strlen(ctagscom) + sizeof(argv) + strlen(param->langmap));
- if (arg == NULL)
+ org_arg = arg =
+ malloc(1 /*NUL*/ + 1 /*First double-quote*/ +
+ ctagscom_len + sizeof(argv) - 1 + langmap_len
+#ifdef UNIVERSAL_CTAGS_FLAVOR
+ + full_options_file_len
+#endif
+ );
+ if (org_arg == NULL)
param->die("short of memory.");
- *arg = '"';
- strcpy(arg+1, ctagscom);
- strcat(arg, argv);
- copy_langmap_converting_cpp(arg + strlen(arg), param->langmap);
+ *arg++ = '"';
+ memcpy(arg, ctagscom, ctagscom_len);
+ arg += ctagscom_len;
+ free(path);
+ ctagscom = NULL; // Prevent inadvertent use-after-free
+ memcpy(arg, argv, sizeof(argv) - 1);
+ arg += sizeof(argv) - 1;
+ copy_langmap_converting_cpp(arg, param->langmap);
+ // Previous call preserves length (and inserts NUL)
+ arg += langmap_len;
+#ifdef UNIVERSAL_CTAGS_FLAVOR
+ if (options_file != NULL) {
+ *arg++ = ' ';
+ memcpy(arg, OPTIONS_OPTION, sizeof(OPTIONS_OPTION) - 1);
+ arg += sizeof(OPTIONS_OPTION) - 1;
+ strcpy(arg, options_file);
+ free(options_file);
+ }
+#endif
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
@@ -146,8 +188,11 @@
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(ctagsnotfound);
+ if (!CreateProcess(NULL, org_arg, NULL, NULL,
+ TRUE, 0, NULL, NULL, &si, &pi))
+ param->die("cannot execute '%s'. (CreateProcess() failed)",
+ org_arg);
+ free(org_arg);
CloseHandle(opipe[0]);
CloseHandle(ipipe[1]);
CloseHandle(pi.hThread);
@@ -176,9 +221,10 @@
#include <sys/wait.h>
static pid_t pid;
static char *argv[] = {
- "ctags",
- NULL,
-#if defined(USE_EXTRA_FIELDS)
+ NULL, // Slot for program name
+#ifdef UNIVERSAL_CTAGS_FLAVOR
+ "--quiet",
+ "--options=NONE",
"--_xformat=%R %-16N %4n %-16F %C",
"--extras=+r",
"--fields=+r",
@@ -188,45 +234,98 @@
"-xu",
"--filter",
"--filter-terminator=" TERMINATOR "\n",
- NULL
+ NULL, // Slot for LANGMAP_OPTION
+#ifdef UNIVERSAL_CTAGS_FLAVOR
+ NULL, // Slot for OPTIONS_FILE
+#endif
+ NULL // Sentinel
};
static void
start_ctags(const struct parser_param *param)
{
int opipe[2], ipipe[2];
char *path = param->getconf("ctagscom");
+ char ** const argv_last = argv +
+ (sizeof(argv) / sizeof(*argv) - 2);
+#ifdef UNIVERSAL_CTAGS_FLAVOR
+ char const * options_file = param->getconf("ctagsoptfile");
+ char ** const langmap_slot = argv_last - 1;
+ char ** const options_file_slot = argv_last;
+#else
+ char ** const langmap_slot = argv_last;
+#endif
- if (path && strlen(path) > 0 && strcmp(path, "no") != 0)
+ if (path && path[0] && strcmp(path, "no") != 0)
ctagscom = path;
- if (!ctagscom || !strlen(ctagscom) || !strcmp(ctagscom, "no"))
+ if (!ctagscom || !ctagscom[0] || !strcmp(ctagscom, "no"))
param->die(ctagsnotfound);
argv[0] = ctagscom;
- argv[1] = malloc(sizeof(LANGMAP_OPTION) + strlen(param->langmap));
- if (argv[1] == NULL)
+ *langmap_slot = malloc(1 + sizeof(LANGMAP_OPTION) - 1 +
+ strlen(param->langmap));
+ if (*langmap_slot == NULL)
param->die("short of memory.");
- memcpy(argv[1], LANGMAP_OPTION, sizeof(LANGMAP_OPTION) - 1);
- copy_langmap_converting_cpp(argv[1] + sizeof(LANGMAP_OPTION) - 1, param->langmap);
+ memcpy(*langmap_slot, LANGMAP_OPTION,
+ sizeof(LANGMAP_OPTION) - 1);
+ copy_langmap_converting_cpp
+ (*langmap_slot + sizeof(LANGMAP_OPTION) - 1,
+ param->langmap);
+#ifdef UNIVERSAL_CTAGS_FLAVOR
+ if (options_file != NULL &&
+ (!options_file[0] || !strcmp(options_file, "no"))) {
+ free(options_file);
+ options_file = NULL;
+ *options_file_slot = NULL;
+ }
+
+ if (options_file != NULL) {
+ size_t options_file_len = strlen(options_file);
+
+ *options_file_slot = malloc
+ (1 + sizeof(OPTIONS_OPTION) - 1 + options_file_len);
+ if (*options_file_slot == NULL)
+ param->die("short of memory.");
+ memcpy(*options_file_slot,
+ OPTIONS_OPTION, sizeof(OPTIONS_OPTION) - 1);
+ memcpy(*options_file_slot + sizeof(OPTIONS_OPTION) - 1,
+ options_file, options_file_len);
+ (*options_file_slot)
+ [sizeof(OPTIONS_OPTION) - 1 + options_file_len] = 0;
+
+ free(options_file);
+ }
+#endif
+
if (pipe(opipe) < 0 || pipe(ipipe) < 0)
param->die("cannot create pipe.");
+
pid = fork();
+
if (pid == 0) {
/* child process */
close(opipe[1]);
close(ipipe[0]);
if (dup2(opipe[0], STDIN_FILENO) < 0
- || dup2(ipipe[1], STDOUT_FILENO) < 0)
+ || dup2(ipipe[1], STDOUT_FILENO) < 0)
param->die("dup2 failed.");
close(opipe[0]);
close(ipipe[1]);
+
execvp(ctagscom, argv);
- param->die("cannot execute '%s'. (execvp failed)", ctagscom);
+
+ param->die("cannot execute '%s'. (execvp() failed)", ctagscom);
}
+
/* parent process */
if (pid < 0)
param->die("fork failed.");
+
free(path);
- free(argv[1]);
+ free(*langmap_slot);
+#ifdef UNIVERSAL_CTAGS_FLAVOR
+ free(*options_file_slot);
+#endif
+
close(opipe[0]);
close(ipipe[1]);
ip = fdopen(ipipe[0], "r");
@@ -286,7 +385,7 @@
int type = PARSER_DEF;
char *p, *tagname, *filename;
-#if defined(USE_EXTRA_FIELDS)
+#if defined(UNIVERSAL_CTAGS_FLAVOR)
/*
* Output of ctags:
* ctags -x ...