xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/file-prefix-map.c (revision 4c3eb207d36f67d31994830c0a694161fc1ca39b)
1cef8759bSmrg /* Implementation of file prefix remapping support (-f*-prefix-map options).
2*4c3eb207Smrg    Copyright (C) 2017-2020 Free Software Foundation, Inc.
3cef8759bSmrg 
4cef8759bSmrg    This program is free software; you can redistribute it and/or modify it
5cef8759bSmrg    under the terms of the GNU General Public License as published by the
6cef8759bSmrg    Free Software Foundation; either version 3, or (at your option) any
7cef8759bSmrg    later version.
8cef8759bSmrg 
9cef8759bSmrg    This program is distributed in the hope that it will be useful,
10cef8759bSmrg    but WITHOUT ANY WARRANTY; without even the implied warranty of
11cef8759bSmrg    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12cef8759bSmrg    GNU General Public License for more details.
13cef8759bSmrg 
14cef8759bSmrg    You should have received a copy of the GNU General Public License
15cef8759bSmrg    along with this program; see the file COPYING3.  If not see
16cef8759bSmrg    <http://www.gnu.org/licenses/>.  */
17cef8759bSmrg 
18cef8759bSmrg #include "config.h"
19cef8759bSmrg #include "system.h"
20cef8759bSmrg #include "coretypes.h"
21cef8759bSmrg #include "diagnostic.h"
22cef8759bSmrg #include "file-prefix-map.h"
23cef8759bSmrg 
24cef8759bSmrg /* Structure recording the mapping from source file and directory names at
25cef8759bSmrg    compile time to those to be embedded in the compilation result (debug
26cef8759bSmrg    information, the __FILE__ macro expansion, etc).  */
27cef8759bSmrg struct file_prefix_map
28cef8759bSmrg {
29cef8759bSmrg   const char *old_prefix;
30cef8759bSmrg   const char *new_prefix;
31cef8759bSmrg   size_t old_len;
32cef8759bSmrg   size_t new_len;
33cef8759bSmrg   struct file_prefix_map *next;
34cef8759bSmrg };
35cef8759bSmrg 
36cef8759bSmrg /* Record a file prefix mapping in the specified map.  ARG is the argument to
37cef8759bSmrg    -f*-prefix-map and must be of the form OLD=NEW.  OPT is the option name
38cef8759bSmrg    for diagnostics.  */
39cef8759bSmrg static void
add_prefix_map(file_prefix_map * & maps,const char * arg,const char * opt)40cef8759bSmrg add_prefix_map (file_prefix_map *&maps, const char *arg, const char *opt)
41cef8759bSmrg {
42cef8759bSmrg   file_prefix_map *map;
43627f7eb2Smrg   const char *p, *old;
44627f7eb2Smrg   size_t oldlen;
45cef8759bSmrg 
46cef8759bSmrg   /* Note: looking for the last '='. The thinking is we can control the paths
47cef8759bSmrg      inside our projects but not where the users build them.  */
48cef8759bSmrg   p = strrchr (arg, '=');
49cef8759bSmrg   if (!p)
50cef8759bSmrg     {
51cef8759bSmrg       error ("invalid argument %qs to %qs", arg, opt);
52cef8759bSmrg       return;
53cef8759bSmrg     }
54627f7eb2Smrg   if (*arg == '$')
55627f7eb2Smrg     {
56627f7eb2Smrg       char *env = xstrndup (arg + 1, p - (arg + 1));
57627f7eb2Smrg       old = getenv(env);
58627f7eb2Smrg       if (!old)
59627f7eb2Smrg 	{
60627f7eb2Smrg 	  warning (0, "environment variable %qs not set in argument to "
61627f7eb2Smrg 		   "%s", env, opt);
62627f7eb2Smrg 	  free(env);
63627f7eb2Smrg 	  return;
64627f7eb2Smrg 	}
65627f7eb2Smrg       oldlen = strlen(old);
66627f7eb2Smrg       free(env);
67627f7eb2Smrg     }
68627f7eb2Smrg   else
69627f7eb2Smrg     {
70627f7eb2Smrg       old = xstrndup (arg, p - arg);
71627f7eb2Smrg       oldlen = p - arg;
72627f7eb2Smrg     }
73cef8759bSmrg   map = XNEW (file_prefix_map);
74627f7eb2Smrg   map->old_prefix = old;
75627f7eb2Smrg   map->old_len = oldlen;
76cef8759bSmrg   p++;
77cef8759bSmrg   map->new_prefix = xstrdup (p);
78cef8759bSmrg   map->new_len = strlen (p);
79cef8759bSmrg   map->next = maps;
80cef8759bSmrg   maps = map;
81cef8759bSmrg }
82cef8759bSmrg 
83cef8759bSmrg /* Perform user-specified mapping of filename prefixes.  Return the
84cef8759bSmrg    GC-allocated new name corresponding to FILENAME or FILENAME if no
85cef8759bSmrg    remapping was performed.  */
86cef8759bSmrg 
87cef8759bSmrg static const char *
remap_filename(file_prefix_map * maps,const char * filename)88cef8759bSmrg remap_filename (file_prefix_map *maps, const char *filename)
89cef8759bSmrg {
90cef8759bSmrg   file_prefix_map *map;
91cef8759bSmrg   char *s;
92cef8759bSmrg   const char *name;
93cef8759bSmrg   size_t name_len;
94cef8759bSmrg 
95cef8759bSmrg   for (map = maps; map; map = map->next)
96cef8759bSmrg     if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
97cef8759bSmrg       break;
98cef8759bSmrg   if (!map)
99cef8759bSmrg     return filename;
100cef8759bSmrg   name = filename + map->old_len;
101cef8759bSmrg   name_len = strlen (name) + 1;
102cef8759bSmrg 
103cef8759bSmrg   s = (char *) ggc_alloc_atomic (name_len + map->new_len);
104cef8759bSmrg   memcpy (s, map->new_prefix, map->new_len);
105cef8759bSmrg   memcpy (s + map->new_len, name, name_len);
106cef8759bSmrg   return s;
107cef8759bSmrg }
108cef8759bSmrg 
109cef8759bSmrg /* NOTE: if adding another -f*-prefix-map option then don't forget to
110cef8759bSmrg    ignore it in DW_AT_producer (dwarf2out.c).  */
111cef8759bSmrg 
112cef8759bSmrg /* Linked lists of file_prefix_map structures.  */
113cef8759bSmrg static file_prefix_map *macro_prefix_maps; /* -fmacro-prefix-map  */
114cef8759bSmrg static file_prefix_map *debug_prefix_maps; /* -fdebug-prefix-map  */
115cef8759bSmrg 
116cef8759bSmrg /* Record a file prefix mapping for -fmacro-prefix-map.  */
117cef8759bSmrg void
add_macro_prefix_map(const char * arg)118cef8759bSmrg add_macro_prefix_map (const char *arg)
119cef8759bSmrg {
120cef8759bSmrg   add_prefix_map (macro_prefix_maps, arg, "-fmacro-prefix-map");
121cef8759bSmrg }
122cef8759bSmrg 
123cef8759bSmrg /* Record a file prefix mapping for -fdebug-prefix-map.  */
124cef8759bSmrg void
add_debug_prefix_map(const char * arg)125cef8759bSmrg add_debug_prefix_map (const char *arg)
126cef8759bSmrg {
127cef8759bSmrg   add_prefix_map (debug_prefix_maps, arg, "-fdebug-prefix-map");
128cef8759bSmrg }
129cef8759bSmrg 
130cef8759bSmrg /* Record a file prefix mapping for all -f*-prefix-map.  */
131cef8759bSmrg void
add_file_prefix_map(const char * arg)132cef8759bSmrg add_file_prefix_map (const char *arg)
133cef8759bSmrg {
134cef8759bSmrg   add_prefix_map (macro_prefix_maps, arg, "-ffile-prefix-map");
135cef8759bSmrg   add_prefix_map (debug_prefix_maps, arg, "-ffile-prefix-map");
136cef8759bSmrg }
137cef8759bSmrg 
138cef8759bSmrg /* Remap using -fmacro-prefix-map.  Return the GC-allocated new name
139cef8759bSmrg    corresponding to FILENAME or FILENAME if no remapping was performed.  */
140cef8759bSmrg const char *
remap_macro_filename(const char * filename)141cef8759bSmrg remap_macro_filename (const char *filename)
142cef8759bSmrg {
143cef8759bSmrg   return remap_filename (macro_prefix_maps, filename);
144cef8759bSmrg }
145cef8759bSmrg 
146cef8759bSmrg /* Original GCC version disabled. The NetBSD version handles regex */
147cef8759bSmrg #if 0
148cef8759bSmrg /* Remap using -fdebug-prefix-map.  Return the GC-allocated new name
149cef8759bSmrg    corresponding to FILENAME or FILENAME if no remapping was performed.  */
150cef8759bSmrg const char *
151cef8759bSmrg remap_debug_filename (const char *filename)
152cef8759bSmrg {
153cef8759bSmrg   return remap_filename (debug_prefix_maps, filename);
154cef8759bSmrg }
155cef8759bSmrg #endif
156cef8759bSmrg 
157cef8759bSmrg /*****
158cef8759bSmrg  ***** The following code is a NetBSD extension that allows regex and
159cef8759bSmrg  ***** \[0-9] substitutition arguments.
160cef8759bSmrg  *****/
161cef8759bSmrg 
162cef8759bSmrg /* Perform user-specified mapping of debug filename prefixes.  Return
163cef8759bSmrg    the new name corresponding to FILENAME.  */
164cef8759bSmrg 
165cef8759bSmrg static const char *
remap_debug_prefix_filename(const char * filename)166cef8759bSmrg remap_debug_prefix_filename (const char *filename)
167cef8759bSmrg {
168cef8759bSmrg   file_prefix_map *map;
169cef8759bSmrg   char *s;
170cef8759bSmrg   const char *name;
171cef8759bSmrg   size_t name_len;
172cef8759bSmrg 
173cef8759bSmrg   for (map = debug_prefix_maps; map; map = map->next)
174cef8759bSmrg     if (filename_ncmp (filename, map->old_prefix, map->old_len) == 0)
175cef8759bSmrg       break;
176cef8759bSmrg   if (!map)
177cef8759bSmrg     return filename;
178cef8759bSmrg   name = filename + map->old_len;
179cef8759bSmrg   name_len = strlen (name) + 1;
180cef8759bSmrg   s = (char *) alloca (name_len + map->new_len);
181cef8759bSmrg   memcpy (s, map->new_prefix, map->new_len);
182cef8759bSmrg   memcpy (s + map->new_len, name, name_len);
183cef8759bSmrg   return ggc_strdup (s);
184cef8759bSmrg }
185cef8759bSmrg 
186cef8759bSmrg #include <regex.h>
187cef8759bSmrg 
188cef8759bSmrg typedef struct debug_regex_map
189cef8759bSmrg {
190cef8759bSmrg   regex_t re;
191cef8759bSmrg   const char *sub;
192cef8759bSmrg   struct debug_regex_map *next;
193cef8759bSmrg } debug_regex_map;
194cef8759bSmrg 
195cef8759bSmrg /* Linked list of such structures.  */
196cef8759bSmrg debug_regex_map *debug_regex_maps;
197cef8759bSmrg 
198cef8759bSmrg 
199cef8759bSmrg /* Record a debug file regex mapping.  ARG is the argument to
200cef8759bSmrg    -fdebug-regex-map and must be of the form OLD=NEW.  */
201cef8759bSmrg 
202cef8759bSmrg void
add_debug_regex_map(const char * arg)203cef8759bSmrg add_debug_regex_map (const char *arg)
204cef8759bSmrg {
205cef8759bSmrg   debug_regex_map *map;
206cef8759bSmrg   const char *p;
207cef8759bSmrg   char *old;
208cef8759bSmrg   char buf[1024];
209cef8759bSmrg   regex_t re;
210cef8759bSmrg   int e;
211cef8759bSmrg 
212cef8759bSmrg   p = strchr (arg, '=');
213cef8759bSmrg   if (!p)
214cef8759bSmrg     {
215cef8759bSmrg       error ("invalid argument %qs to -fdebug-regex-map", arg);
216cef8759bSmrg       return;
217cef8759bSmrg     }
218cef8759bSmrg 
219cef8759bSmrg   old = xstrndup (arg, p - arg);
220cef8759bSmrg   if ((e = regcomp(&re, old, REG_EXTENDED)) != 0)
221cef8759bSmrg     {
222cef8759bSmrg       regerror(e, &re, buf, sizeof(buf));
223cef8759bSmrg       warning (0, "regular expression compilation for %qs in argument to "
224cef8759bSmrg 	       "-fdebug-regex-map failed: %qs", old, buf);
225cef8759bSmrg       free(old);
226cef8759bSmrg       return;
227cef8759bSmrg     }
228cef8759bSmrg   free(old);
229cef8759bSmrg 
230cef8759bSmrg   map = XNEW (debug_regex_map);
231cef8759bSmrg   map->re = re;
232cef8759bSmrg   p++;
233cef8759bSmrg   map->sub = xstrdup (p);
234cef8759bSmrg   map->next = debug_regex_maps;
235cef8759bSmrg   debug_regex_maps = map;
236cef8759bSmrg }
237cef8759bSmrg 
238cef8759bSmrg extern "C" ssize_t regasub(char **, const char *,
239cef8759bSmrg   const regmatch_t *rm, const char *);
240cef8759bSmrg 
241cef8759bSmrg /* Perform user-specified mapping of debug filename regular expressions.  Return
242cef8759bSmrg    the new name corresponding to FILENAME.  */
243cef8759bSmrg 
244cef8759bSmrg static const char *
remap_debug_regex_filename(const char * filename)245cef8759bSmrg remap_debug_regex_filename (const char *filename)
246cef8759bSmrg {
247cef8759bSmrg   debug_regex_map *map;
248cef8759bSmrg   char *s;
249cef8759bSmrg   regmatch_t rm[10];
250cef8759bSmrg 
251cef8759bSmrg   for (map = debug_regex_maps; map; map = map->next)
252cef8759bSmrg     if (regexec (&map->re, filename, 10, rm, 0) == 0
253cef8759bSmrg        && regasub (&s, map->sub, rm, filename) >= 0)
254cef8759bSmrg       {
255cef8759bSmrg 	 const char *name = ggc_strdup(s);
256cef8759bSmrg 	 free(s);
257cef8759bSmrg 	 return name;
258cef8759bSmrg       }
259cef8759bSmrg   return filename;
260cef8759bSmrg }
261cef8759bSmrg 
262cef8759bSmrg const char *
remap_debug_filename(const char * filename)263cef8759bSmrg remap_debug_filename (const char *filename)
264cef8759bSmrg {
265cef8759bSmrg    return remap_debug_regex_filename (remap_debug_prefix_filename (filename));
266cef8759bSmrg }
267