Subject: bug#76322: Make ctags a thin wrapper around etags

From: Eli Zaretskii <[email-masked]>
Date: Thu, 06 Mar 2025 15:31:11 +0200

> Date: Tue, 4 Mar 2025 10:37:05 -0800
> Cc: [email-masked]
> From: Paul Eggert <[email-masked]>
> 
> Thanks for the review. Revised patch attached, which I think addresses 
> all the comments.

Thanks.  This mostly worked, but I needed a few minor changes (below).
We should use _spawnvp, not _execvp, since the latter doesn't return,
so we cannot return the exit status of etags to the caller.  More
importantly, the counting of bytes to allocate missed the PROGRAM part
of --ctags=PROGRAM, so ctags would crash in weird ways.  Finally, I
need to include stdio.h to get the declaration of perror.  Here's the
patch:

diff --git a/lib-src/ctags.c b/lib-src/ctags.c
index 82324f5..2a2a7d2 100644
--- a/lib-src/ctags.c
+++ b/lib-src/ctags.c
@@ -23,13 +23,14 @@ #define DEFER_MS_W32_H
 #include <filename.h>
 
 #include <malloc.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
 /* Declare _execvp by hand, since MS-Windows <process.h> collides with
    ../src/process.h.  */
 #include <stdint.h> /* for intptr_t */
-extern intptr_t _execvp (char const *, char const *const *);
+extern intptr_t _spawnvp (int, char const *, char const *const *);
 
 #ifdef WINDOWSNT
 /* Store into D[I] through D[I + N - 1] the byte C, and return I + N.
@@ -100,7 +101,10 @@ main (int argc, char **argv)
   for (int i = 0; i < argc; i++)
     nargbytes += w32_execvp_arg_repr (argv[i], NULL);
   nargbytes -= progname_baselen;
-  nargbytes += sizeof etags_basename - 1 + sizeof option_prefix - 1;
+  nargbytes += sizeof etags_basename - 1;
+  nargbytes += w32_execvp_arg_repr (option_prefix, NULL);
+  nargbytes += w32_execvp_arg_repr (argv[0], NULL)
+	       - progname_baselen + sizeof etags_basename - 1;
 
   char const **etags_argv = malloc ((argc + 2) * sizeof *argv + nargbytes);
   if (etags_argv)
@@ -122,7 +126,7 @@ main (int argc, char **argv)
 
       etags_argv[argc + 1] = NULL;
       progname = etags_argv[0];
-      _execvp (progname, etags_argv);
+      return _spawnvp (0, progname, etags_argv);
     }
 
   perror (progname);