This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] fixincludes: fix fixincludes for MinGW


The fixincl executable uses system function to call applyfix or to
direcly patch a header file, with parameters enclosed in single
quotes. This problem is that MinGW system function just calls cmd.exe,
which doesn't strip quotes from parameters and completely ignores
quotes for embedding spaces in parameters. The MinGW system function
also doesn't allow for newlines in executed command parameters. As a
result fixincludes doesn't wotk at on when trying to build a cross
compiler with mingw as host.

On MinGW host, this patch adds system_with_shell function, which
transforms command passed to system function is following way:
- Enclose entire command in double quotes
- Prepend shell executable name, taken from environment variable SHELL
- Replace each occurence of newline with '$'\n'' sequence which is
understood by bash and ksh (it is assumed that all newlines are
embedded in command parameters enclosed in single quotes)

2016-09-23 Tadek Kijkowski (tkijkowski@gmail.com)

        * fixincl.c: Added system_with_shell for MinGW host.


Index: fixincludes/fixincl.c
===================================================================
--- fixincludes/fixincl.c   (revision 240386)
+++ fixincludes/fixincl.c   (working copy)
@@ -170,7 +170,111 @@
   exit (EXIT_SUCCESS);
 }

+#ifdef __MINGW32__

+/* Count number of \c needle character instances in string */
+static int
+count_chars ( char* str, char needle )
+{
+  int instances = 0;
+
+  while (str)
+    {
+       str = strchr (str, needle);
+       if (str)
+         {
+           ++str;
+           ++instances;
+         }
+    }
+
+  return instances;
+}
+
+/* On Mingw32 system(3) will just start cmd by default.
+   Try using unix style shell passed via SHELL env. variable.
+ */
+
+/* Call system(3) function, but prepend ${SHELL} -c to the command,
+   replace newlines with '$'\n'' and enclose command with double quotes.
+ */
+static int
+system_with_shell ( char* s )
+{
+  static const char z_shell_start_args[] = " -c \"";
+  static const char z_shell_end_args[] = "\"";
+  static const char z_shell_newline[] = "'$'\\n''";
+
+  char* env_shell;
+  char* long_cmd;
+  char* cmd_endp;
+  size_t cmd_size;
+  int sys_result;
+  int newline_cnt;
+  char* nl_scan;
+
+  /* If SHELL variable is not defined just call standard shell function */
+  env_shell = getenv ("SHELL");
+  if (env_shell == NULL)
+    return system (s);
+
+  /* Count number of newlines in command */
+  newline_cnt = count_chars(s, '\n');
+
+  /* Allocate enough memory to fit newly created command string */
+  cmd_size = strlen (env_shell) + (sizeof (z_shell_start_args) - 1)
+           + strlen (s) + newline_cnt * (sizeof(z_shell_newline) - 1 - 1)
+           + (sizeof (z_shell_end_args) - 1) + 1;
+
+  long_cmd = XNEWVEC (char, cmd_size);
+
+  /* Start with ${SHELL} -c " */
+  strcpy (long_cmd, env_shell);
+  strcat (long_cmd, z_shell_start_args);
+
+  /* End pointer for appending pieces of command while replacing newlines */
+  cmd_endp = long_cmd + strlen(long_cmd);
+  nl_scan = s;
+  while (nl_scan != NULL)
+    {
+      char* next_nl = strchr (nl_scan, '\n');
+      if (next_nl)
+        {
+          /* Append part of command between newlines */
+          size_t part_len = next_nl - nl_scan;
+          memcpy(cmd_endp, nl_scan, part_len);
+          cmd_endp += part_len;
+
+          /* Append newline replacement */
+          memcpy(cmd_endp, z_shell_newline, sizeof(z_shell_newline));
+          cmd_endp += sizeof(z_shell_newline) - 1;
+
+          /* Skip newline in src */
+          ++next_nl;
+        }
+      else
+        {
+          /* Last portion */
+          strcpy (cmd_endp, nl_scan);
+        }
+      nl_scan = next_nl;
+    }
+
+  /* Closing quote */
+  strcat (long_cmd, z_shell_end_args);
+
+  sys_result = system (long_cmd);
+
+  free ( (void*) long_cmd);
+
+  return sys_result;
+}
+
+#define system system_with_shell
+
+#endif /* defined(__MINGW32__) */
+
+
 static void
 do_version (void)
 {


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]