Use poly_int tree accessors
[official-gcc.git] / libgcc / libgcov-driver-system.c
blobbf125869dc08c64363156534a74c1b23e81e8f27
1 /* Routines required for instrumenting a program. */
2 /* Compile this one with gcc. */
3 /* Copyright (C) 1989-2018 Free Software Foundation, Inc.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 Under Section 7 of GPL version 3, you are granted additional
18 permissions described in the GCC Runtime Library Exception, version
19 3.1, as published by the Free Software Foundation.
21 You should have received a copy of the GNU General Public License and
22 a copy of the GCC Runtime Library Exception along with this program;
23 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 <http://www.gnu.org/licenses/>. */
26 #if !IN_GCOV_TOOL
27 /* Configured via the GCOV_ERROR_FILE environment variable;
28 it will either be stderr, or a file of the user's choosing.
29 Non-static to prevent multiple gcov-aware shared objects from
30 instantiating their own copies. */
31 FILE *__gcov_error_file = NULL;
32 #endif
34 /* A utility function to populate the __gcov_error_file pointer.
35 This should NOT be called outside of the gcov system driver code. */
37 static FILE *
38 get_gcov_error_file (void)
40 #if IN_GCOV_TOOL
41 return stderr;
42 #else
43 if (!__gcov_error_file)
45 const char *gcov_error_filename = getenv ("GCOV_ERROR_FILE");
47 if (gcov_error_filename)
48 __gcov_error_file = fopen (gcov_error_filename, "a");
49 if (!__gcov_error_file)
50 __gcov_error_file = stderr;
52 return __gcov_error_file;
53 #endif
56 /* A utility function for outputting errors. */
58 static int __attribute__((format(printf, 1, 2)))
59 gcov_error (const char *fmt, ...)
61 int ret;
62 va_list argp;
64 va_start (argp, fmt);
65 FILE *f = get_gcov_error_file ();
66 ret = vfprintf (f, fmt, argp);
67 va_end (argp);
69 if (getenv ("GCOV_EXIT_AT_ERROR"))
71 fprintf (f, "profiling:exiting after an error\n");
72 exit (1);
75 return ret;
78 #if !IN_GCOV_TOOL
79 static void
80 gcov_error_exit (void)
82 if (__gcov_error_file && __gcov_error_file != stderr)
84 fclose (__gcov_error_file);
85 __gcov_error_file = NULL;
88 #endif
90 /* Make sure path component of the given FILENAME exists, create
91 missing directories. FILENAME must be writable.
92 Returns zero on success, or -1 if an error occurred. */
94 static int
95 create_file_directory (char *filename)
97 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32)
98 (void) filename;
99 return -1;
100 #else
101 char *s;
103 s = filename;
105 if (HAS_DRIVE_SPEC(s))
106 s += 2;
107 if (IS_DIR_SEPARATOR(*s))
108 ++s;
109 for (; *s != '\0'; s++)
110 if (IS_DIR_SEPARATOR(*s))
112 char sep = *s;
113 *s = '\0';
115 /* Try to make directory if it doesn't already exist. */
116 if (access (filename, F_OK) == -1
117 #ifdef TARGET_POSIX_IO
118 && mkdir (filename, 0755) == -1
119 #else
120 #ifdef mkdir
121 #undef mkdir
122 #endif
123 && mkdir (filename) == -1
124 #endif
125 /* The directory might have been made by another process. */
126 && errno != EEXIST)
128 gcov_error ("profiling:%s:Cannot create directory\n", filename);
129 *s = sep;
130 return -1;
133 *s = sep;
135 return 0;
136 #endif
139 static void
140 allocate_filename_struct (struct gcov_filename *gf)
142 const char *gcov_prefix;
143 size_t prefix_length;
144 int strip = 0;
147 /* Check if the level of dirs to strip off specified. */
148 char *tmp = getenv("GCOV_PREFIX_STRIP");
149 if (tmp)
151 strip = atoi (tmp);
152 /* Do not consider negative values. */
153 if (strip < 0)
154 strip = 0;
157 gf->strip = strip;
159 /* Get file name relocation prefix. Non-absolute values are ignored. */
160 gcov_prefix = getenv("GCOV_PREFIX");
161 prefix_length = gcov_prefix ? strlen (gcov_prefix) : 0;
163 /* Remove an unnecessary trailing '/' */
164 if (prefix_length && IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
165 prefix_length--;
167 /* If no prefix was specified and a prefix stip, then we assume
168 relative. */
169 if (!prefix_length && gf->strip)
171 gcov_prefix = ".";
172 prefix_length = 1;
174 gf->prefix = prefix_length;
176 /* Allocate and initialize the filename scratch space. */
177 gf->filename = (char *) xmalloc (gf->max_length + prefix_length + 2);
178 if (prefix_length)
179 memcpy (gf->filename, gcov_prefix, prefix_length);
182 /* Open a gcda file specified by GI_FILENAME.
183 Return -1 on error. Return 0 on success. */
185 static int
186 gcov_exit_open_gcda_file (struct gcov_info *gi_ptr,
187 struct gcov_filename *gf)
189 const char *fname = gi_ptr->filename;
190 char *dst = gf->filename + gf->prefix;
192 fname = gi_ptr->filename;
194 /* Build relocated filename, stripping off leading
195 directories from the initial filename if requested. */
196 if (gf->strip > 0)
198 const char *probe = fname;
199 int level;
201 /* Remove a leading separator, without counting it. */
202 if (IS_DIR_SEPARATOR (*probe))
203 probe++;
205 /* Skip selected directory levels. If we fall off the end, we
206 keep the final part. */
207 for (level = gf->strip; *probe && level; probe++)
208 if (IS_DIR_SEPARATOR (*probe))
210 fname = probe;
211 level--;
215 /* Update complete filename with stripped original. */
216 if (gf->prefix)
218 /* Avoid to add multiple drive letters into combined path. */
219 if (HAS_DRIVE_SPEC(fname))
220 fname += 2;
222 if (!IS_DIR_SEPARATOR (*fname))
223 *dst++ = '/';
225 strcpy (dst, fname);
227 if (!gcov_open (gf->filename))
229 /* Open failed likely due to missed directory.
230 Create directory and retry to open file. */
231 if (create_file_directory (gf->filename))
233 fprintf (stderr, "profiling:%s:Skip\n", gf->filename);
234 return -1;
236 if (!gcov_open (gf->filename))
238 fprintf (stderr, "profiling:%s:Cannot open\n", gf->filename);
239 return -1;
243 return 0;