Hi.

I'm sending V2, where I changed:

- removed expansion of '%w', it's handled in: 
https://gcc.gnu.org/ml/gcc-patches/2018-05/msg00729.html
- simplified concatenation in replace_filename_variables
- documentation for the expansion is added

Ready for trunk?

Martin
>From ac35fffa250685ec9f5fd04c1076558769848f38 Mon Sep 17 00:00:00 2001
From: marxin <mli...@suse.cz>
Date: Fri, 18 May 2018 13:12:06 +0200
Subject: [PATCH] Support variables in expansion of -fprofile-generate option
 (PR gcov-profile/47618).

gcc/ChangeLog:

2018-05-29  Martin Liska  <mli...@suse.cz>

	PR gcov-profile/47618
	* doc/invoke.texi: Document how -fprofile-dir format
        is extended.

libgcc/ChangeLog:

2018-05-29  Martin Liska  <mli...@suse.cz>

	PR gcov-profile/47618
	* libgcov-driver-system.c (replace_filename_variables): New
        function.
	(gcov_exit_open_gcda_file): Use it.
---
 gcc/doc/invoke.texi            | 14 +++++++
 libgcc/libgcov-driver-system.c | 70 ++++++++++++++++++++++++++++++++++
 2 files changed, 84 insertions(+)

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 65f32d67640..42ab7e9211a 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -11294,6 +11294,20 @@ and its related options.  Both absolute and relative paths can be used.
 By default, GCC uses the current directory as @var{path}, thus the
 profile data file appears in the same directory as the object file.
 
+When an executable is run in a massive parallel environment, it is recommended
+to save profile to different folders.  That can be done with variables
+in @var{path} that are exported during run-time:
+
+@table @gcctabopt
+
+@item %p
+process ID.
+
+@item %q@{VAR@}
+value of environment variable @var{VAR}
+
+@end table
+
 @item -fprofile-generate
 @itemx -fprofile-generate=@var{path}
 @opindex fprofile-generate
diff --git a/libgcc/libgcov-driver-system.c b/libgcc/libgcov-driver-system.c
index 0df44239363..1216edb1a50 100644
--- a/libgcc/libgcov-driver-system.c
+++ b/libgcc/libgcov-driver-system.c
@@ -128,6 +128,74 @@ create_file_directory (char *filename)
 #endif
 }
 
+/* Replace filename variables in FILENAME.  We currently support expansion:
+
+   %p - process ID
+   %q{ENV} - value of environment variable ENV
+   */
+
+static char *
+replace_filename_variables (char *filename)
+{
+  char buffer[16];
+  char empty[] = "";
+  for (char *p = filename; *p != '\0'; p++)
+    {
+      unsigned length = strlen (filename);
+      if (*p == '%' && *(p + 1) != '\0')
+	{
+	  unsigned start = p - filename;
+	  p++;
+	  char *replacement = NULL;
+	  switch (*p)
+	    {
+	    case 'p':
+	      sprintf (buffer, "%d", getpid ());
+	      replacement = buffer;
+	      p++;
+	      break;
+	    case 'q':
+	      if (*(p + 1) == '{')
+		{
+		  p += 2;
+		  char *e = strchr (p, '}');
+		  if (e)
+		    {
+		      *e = '\0';
+		      replacement = getenv (p);
+		      if (replacement == NULL)
+			replacement = empty;
+		      p = e + 1;
+		    }
+		  else
+		    return filename;
+		}
+	      break;
+	    default:
+	      return filename;
+	    }
+
+	  /* Concat beginning of the path, replacement and
+	     ending of the path.  */
+	  unsigned end = length - (p - filename);
+	  unsigned repl_length = strlen (replacement);
+
+	  char *buffer = (char *)xmalloc (start + end + repl_length + 1);
+	  char *buffer_ptr = buffer;
+	  buffer_ptr = (char *)mempcpy (buffer_ptr, filename, start);
+	  buffer_ptr = (char *)mempcpy (buffer_ptr, replacement, repl_length);
+	  buffer_ptr = (char *)mempcpy (buffer_ptr, p, end);
+	  *buffer_ptr = '\0';
+
+	  free (filename);
+	  filename = buffer;
+	  p = buffer + start + repl_length;
+	}
+    }
+
+  return filename;
+}
+
 static void
 allocate_filename_struct (struct gcov_filename *gf)
 {
@@ -216,6 +284,8 @@ gcov_exit_open_gcda_file (struct gcov_info *gi_ptr,
     }
   strcpy (dst, fname);
 
+  gf->filename = replace_filename_variables (gf->filename);
+
   if (!gcov_open (gf->filename))
     {
       /* Open failed likely due to missed directory.
-- 
2.17.0

Reply via email to