Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(452)

Side by Side Diff: bison/src/bison/2.4.1/bison-2.4.1/patches/bison-2.4.1-src/lib/relocatable.c

Issue 10807020: Add native Windows binary for bison. (Closed) Base URL: svn://chrome-svn/chrome/trunk/deps/third_party/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
Property Changes:
Added: svn:eol-style
+ LF
OLDNEW
(Empty)
1 /* Provide relocatable packages.
2 Copyright (C) 2003-2006, 2008 Free Software Foundation, Inc.
3 Written by Bruno Haible <bruno@clisp.org>, 2003.
4
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU Library General Public License as published
7 by the Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18 USA. */
19
20
21 /* Tell glibc's <stdio.h> to provide a prototype for getline().
22 This must come before <config.h> because <config.h> may include
23 <features.h>, and once <features.h> has been included, it's too late. */
24 #ifndef _GNU_SOURCE
25 # define _GNU_SOURCE 1
26 #endif
27
28 #include <config.h>
29
30 /* Specification. */
31 #include "relocatable.h"
32
33 #if ENABLE_RELOCATABLE
34
35 #include <stddef.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39
40 #ifdef NO_XMALLOC
41 # define xmalloc malloc
42 #else
43 # include "xalloc.h"
44 #endif
45
46 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
47 # define WIN32_LEAN_AND_MEAN
48 # include <windows.h>
49 #endif
50
51 #if DEPENDS_ON_LIBCHARSET
52 # include <libcharset.h>
53 #endif
54 #if DEPENDS_ON_LIBICONV && HAVE_ICONV
55 # include <iconv.h>
56 #endif
57 #if DEPENDS_ON_LIBINTL && ENABLE_NLS
58 # include <libintl.h>
59 #endif
60
61 /* Faked cheap 'bool'. */
62 #undef bool
63 #undef false
64 #undef true
65 #define bool int
66 #define false 0
67 #define true 1
68
69 /* Pathname support.
70 ISSLASH(C) tests whether C is a directory separator character.
71 IS_PATH_WITH_DIR(P) tests whether P contains a directory specification.
72 */
73 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
74 /* Win32, Cygwin, OS/2, DOS */
75 # define ISSLASH(C) ((C) == '/' || (C) == '\\')
76 # define HAS_DEVICE(P) \
77 ((((P)[0] >= 'A' && (P)[0] <= 'Z') || ((P)[0] >= 'a' && (P)[0] <= 'z')) \
78 && (P)[1] == ':')
79 # define IS_PATH_WITH_DIR(P) \
80 (strchr (P, '/') != NULL || strchr (P, '\\') != NULL || HAS_DEVICE (P))
81 # define FILE_SYSTEM_PREFIX_LEN(P) (HAS_DEVICE (P) ? 2 : 0)
82 #else
83 /* Unix */
84 # define ISSLASH(C) ((C) == '/')
85 # define IS_PATH_WITH_DIR(P) (strchr (P, '/') != NULL)
86 # define FILE_SYSTEM_PREFIX_LEN(P) 0
87 #endif
88
89 /* Original installation prefix. */
90 static char *orig_prefix;
91 static size_t orig_prefix_len;
92 /* Current installation prefix. */
93 static char *curr_prefix;
94 static size_t curr_prefix_len;
95 /* These prefixes do not end in a slash. Anything that will be concatenated
96 to them must start with a slash. */
97
98 /* Sets the original and the current installation prefix of this module.
99 Relocation simply replaces a pathname starting with the original prefix
100 by the corresponding pathname with the current prefix instead. Both
101 prefixes should be directory names without trailing slash (i.e. use ""
102 instead of "/"). */
103 static void
104 set_this_relocation_prefix (const char *orig_prefix_arg,
105 const char *curr_prefix_arg)
106 {
107 if (orig_prefix_arg != NULL && curr_prefix_arg != NULL
108 /* Optimization: if orig_prefix and curr_prefix are equal, the
109 relocation is a nop. */
110 && strcmp (orig_prefix_arg, curr_prefix_arg) != 0)
111 {
112 /* Duplicate the argument strings. */
113 char *memory;
114
115 orig_prefix_len = strlen (orig_prefix_arg);
116 curr_prefix_len = strlen (curr_prefix_arg);
117 memory = (char *) xmalloc (orig_prefix_len + 1 + curr_prefix_len + 1);
118 #ifdef NO_XMALLOC
119 if (memory != NULL)
120 #endif
121 {
122 memcpy (memory, orig_prefix_arg, orig_prefix_len + 1);
123 orig_prefix = memory;
124 memory += orig_prefix_len + 1;
125 memcpy (memory, curr_prefix_arg, curr_prefix_len + 1);
126 curr_prefix = memory;
127 return;
128 }
129 }
130 orig_prefix = NULL;
131 curr_prefix = NULL;
132 /* Don't worry about wasted memory here - this function is usually only
133 called once. */
134 }
135
136 /* Sets the original and the current installation prefix of the package.
137 Relocation simply replaces a pathname starting with the original prefix
138 by the corresponding pathname with the current prefix instead. Both
139 prefixes should be directory names without trailing slash (i.e. use ""
140 instead of "/"). */
141 void
142 set_relocation_prefix (const char *orig_prefix_arg, const char *curr_prefix_arg)
143 {
144 set_this_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
145
146 /* Now notify all dependent libraries. */
147 #if DEPENDS_ON_LIBCHARSET
148 libcharset_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
149 #endif
150 #if DEPENDS_ON_LIBICONV && HAVE_ICONV && _LIBICONV_VERSION >= 0x0109
151 libiconv_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
152 #endif
153 #if DEPENDS_ON_LIBINTL && ENABLE_NLS && defined libintl_set_relocation_prefix
154 libintl_set_relocation_prefix (orig_prefix_arg, curr_prefix_arg);
155 #endif
156 }
157
158 #if !defined IN_LIBRARY || (defined PIC && defined INSTALLDIR)
159
160 /* Convenience function:
161 Computes the current installation prefix, based on the original
162 installation prefix, the original installation directory of a particular
163 file, and the current pathname of this file.
164 Returns it, freshly allocated. Returns NULL upon failure. */
165 #ifdef IN_LIBRARY
166 #define compute_curr_prefix local_compute_curr_prefix
167 static
168 #endif
169 char *
170 compute_curr_prefix (const char *orig_installprefix,
171 const char *orig_installdir,
172 const char *curr_pathname)
173 {
174 char *curr_installdir;
175 const char *rel_installdir;
176
177 if (curr_pathname == NULL)
178 return NULL;
179
180 /* Determine the relative installation directory, relative to the prefix.
181 This is simply the difference between orig_installprefix and
182 orig_installdir. */
183 if (strncmp (orig_installprefix, orig_installdir, strlen (orig_installprefix))
184 != 0)
185 /* Shouldn't happen - nothing should be installed outside $(prefix). */
186 return NULL;
187 rel_installdir = orig_installdir + strlen (orig_installprefix);
188
189 /* Determine the current installation directory. */
190 {
191 const char *p_base = curr_pathname + FILE_SYSTEM_PREFIX_LEN (curr_pathname);
192 const char *p = curr_pathname + strlen (curr_pathname);
193 char *q;
194
195 while (p > p_base)
196 {
197 p--;
198 if (ISSLASH (*p))
199 break;
200 }
201
202 q = (char *) xmalloc (p - curr_pathname + 1);
203 #ifdef NO_XMALLOC
204 if (q == NULL)
205 return NULL;
206 #endif
207 memcpy (q, curr_pathname, p - curr_pathname);
208 q[p - curr_pathname] = '\0';
209 curr_installdir = q;
210 }
211
212 /* Compute the current installation prefix by removing the trailing
213 rel_installdir from it. */
214 {
215 const char *rp = rel_installdir + strlen (rel_installdir);
216 const char *cp = curr_installdir + strlen (curr_installdir);
217 const char *cp_base =
218 curr_installdir + FILE_SYSTEM_PREFIX_LEN (curr_installdir);
219
220 while (rp > rel_installdir && cp > cp_base)
221 {
222 bool same = false;
223 const char *rpi = rp;
224 const char *cpi = cp;
225
226 while (rpi > rel_installdir && cpi > cp_base)
227 {
228 rpi--;
229 cpi--;
230 if (ISSLASH (*rpi) || ISSLASH (*cpi))
231 {
232 if (ISSLASH (*rpi) && ISSLASH (*cpi))
233 same = true;
234 break;
235 }
236 /* Do case-insensitive comparison if the filesystem is always or
237 often case-insensitive. It's better to accept the comparison
238 if the difference is only in case, rather than to fail. */
239 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__ || defined __EMX__ || defined __DJGPP__
240 /* Win32, Cygwin, OS/2, DOS - case insignificant filesystem */
241 if ((*rpi >= 'a' && *rpi <= 'z' ? *rpi - 'a' + 'A' : *rpi)
242 != (*cpi >= 'a' && *cpi <= 'z' ? *cpi - 'a' + 'A' : *cpi))
243 break;
244 #else
245 if (*rpi != *cpi)
246 break;
247 #endif
248 }
249 if (!same)
250 break;
251 /* The last pathname component was the same. opi and cpi now point
252 to the slash before it. */
253 rp = rpi;
254 cp = cpi;
255 }
256
257 if (rp > rel_installdir)
258 {
259 /* Unexpected: The curr_installdir does not end with rel_installdir. */
260 free (curr_installdir);
261 return NULL;
262 }
263
264 {
265 size_t curr_prefix_len = cp - curr_installdir;
266 char *curr_prefix;
267
268 curr_prefix = (char *) xmalloc (curr_prefix_len + 1);
269 #ifdef NO_XMALLOC
270 if (curr_prefix == NULL)
271 {
272 free (curr_installdir);
273 return NULL;
274 }
275 #endif
276 memcpy (curr_prefix, curr_installdir, curr_prefix_len);
277 curr_prefix[curr_prefix_len] = '\0';
278
279 free (curr_installdir);
280
281 return curr_prefix;
282 }
283 }
284 }
285
286 #endif /* !IN_LIBRARY || PIC */
287
288 #if defined PIC && defined INSTALLDIR
289
290 /* Full pathname of shared library, or NULL. */
291 static char *shared_library_fullname;
292
293 #if defined _WIN32 || defined __WIN32__ || defined __CYGWIN__
294
295 /* Determine the full pathname of the shared library when it is loaded. */
296
297 BOOL WINAPI
298 DllMain (HINSTANCE module_handle, DWORD event, LPVOID reserved)
299 {
300 (void) reserved;
301
302 if (event == DLL_PROCESS_ATTACH)
303 {
304 /* The DLL is being loaded into an application's address range. */
305 static char location[MAX_PATH];
306
307 if (!GetModuleFileName (module_handle, location, sizeof (location)))
308 /* Shouldn't happen. */
309 return FALSE;
310
311 if (!IS_PATH_WITH_DIR (location))
312 /* Shouldn't happen. */
313 return FALSE;
314
315 {
316 #if defined __CYGWIN__
317 /* On Cygwin, we need to convert paths coming from Win32 system calls
318 to the Unix-like slashified notation. */
319 static char location_as_posix_path[2 * MAX_PATH];
320 /* There's no error return defined for cygwin_conv_to_posix_path.
321 See cygwin-api/func-cygwin-conv-to-posix-path.html.
322 Does it overflow the buffer of expected size MAX_PATH or does it
323 truncate the path? I don't know. Let's catch both. */
324 cygwin_conv_to_posix_path (location, location_as_posix_path);
325 location_as_posix_path[MAX_PATH - 1] = '\0';
326 if (strlen (location_as_posix_path) >= MAX_PATH - 1)
327 /* A sign of buffer overflow or path truncation. */
328 return FALSE;
329 shared_library_fullname = strdup (location_as_posix_path);
330 #else
331 shared_library_fullname = strdup (location);
332 #endif
333 }
334 }
335
336 return TRUE;
337 }
338
339 #else /* Unix except Cygwin */
340
341 static void
342 find_shared_library_fullname ()
343 {
344 #if defined __linux__ && __GLIBC__ >= 2
345 /* Linux has /proc/self/maps. glibc 2 has the getline() function. */
346 FILE *fp;
347
348 /* Open the current process' maps file. It describes one VMA per line. */
349 fp = fopen ("/proc/self/maps", "r");
350 if (fp)
351 {
352 unsigned long address = (unsigned long) &find_shared_library_fullname;
353 for (;;)
354 {
355 unsigned long start, end;
356 int c;
357
358 if (fscanf (fp, "%lx-%lx", &start, &end) != 2)
359 break;
360 if (address >= start && address <= end - 1)
361 {
362 /* Found it. Now see if this line contains a filename. */
363 while (c = getc (fp), c != EOF && c != '\n' && c != '/')
364 continue;
365 if (c == '/')
366 {
367 size_t size;
368 int len;
369
370 ungetc (c, fp);
371 shared_library_fullname = NULL; size = 0;
372 len = getline (&shared_library_fullname, &size, fp);
373 if (len >= 0)
374 {
375 /* Success: filled shared_library_fullname. */
376 if (len > 0 && shared_library_fullname[len - 1] == '\n')
377 shared_library_fullname[len - 1] = '\0';
378 }
379 }
380 break;
381 }
382 while (c = getc (fp), c != EOF && c != '\n')
383 continue;
384 }
385 fclose (fp);
386 }
387 #endif
388 }
389
390 #endif /* (WIN32 or Cygwin) / (Unix except Cygwin) */
391
392 /* Return the full pathname of the current shared library.
393 Return NULL if unknown.
394 Guaranteed to work only on Linux, Cygwin and Woe32. */
395 static char *
396 get_shared_library_fullname ()
397 {
398 #if !(defined _WIN32 || defined __WIN32__ || defined __CYGWIN__)
399 static bool tried_find_shared_library_fullname;
400 if (!tried_find_shared_library_fullname)
401 {
402 find_shared_library_fullname ();
403 tried_find_shared_library_fullname = true;
404 }
405 #endif
406 return shared_library_fullname;
407 }
408
409 #endif /* PIC */
410
411 /* Returns the pathname, relocated according to the current installation
412 directory.
413 The returned string is either PATHNAME unmodified or a freshly allocated
414 string that you can free with free() after casting it to 'char *'. */
415 const char *
416 relocate (const char *pathname)
417 {
418 #if defined PIC && defined INSTALLDIR
419 static int initialized;
420
421 /* Initialization code for a shared library. */
422 if (!initialized)
423 {
424 /* At this point, orig_prefix and curr_prefix likely have already been
425 set through the main program's set_program_name_and_installdir
426 function. This is sufficient in the case that the library has
427 initially been installed in the same orig_prefix. But we can do
428 better, to also cover the cases that 1. it has been installed
429 in a different prefix before being moved to orig_prefix and (later)
430 to curr_prefix, 2. unlike the program, it has not moved away from
431 orig_prefix. */
432 const char *orig_installprefix = INSTALLPREFIX;
433 const char *orig_installdir = INSTALLDIR;
434 char *curr_prefix_better;
435
436 curr_prefix_better =
437 compute_curr_prefix (orig_installprefix, orig_installdir,
438 get_shared_library_fullname ());
439
440 set_relocation_prefix (orig_installprefix,
441 curr_prefix_better != NULL
442 ? curr_prefix_better
443 : curr_prefix);
444
445 if (curr_prefix_better != NULL)
446 free (curr_prefix_better);
447
448 initialized = 1;
449 }
450 #endif
451
452 /* Note: It is not necessary to perform case insensitive comparison here,
453 even for DOS-like filesystems, because the pathname argument was
454 typically created from the same Makefile variable as orig_prefix came
455 from. */
456 if (orig_prefix != NULL && curr_prefix != NULL
457 && strncmp (pathname, orig_prefix, orig_prefix_len) == 0)
458 {
459 if (pathname[orig_prefix_len] == '\0')
460 {
461 /* pathname equals orig_prefix. */
462 char *result = (char *) xmalloc (strlen (curr_prefix) + 1);
463
464 #ifdef NO_XMALLOC
465 if (result != NULL)
466 #endif
467 {
468 strcpy (result, curr_prefix);
469 return result;
470 }
471 }
472 else if (ISSLASH (pathname[orig_prefix_len]))
473 {
474 /* pathname starts with orig_prefix. */
475 const char *pathname_tail = &pathname[orig_prefix_len];
476 char *result =
477 (char *) xmalloc (curr_prefix_len + strlen (pathname_tail) + 1);
478
479 #ifdef NO_XMALLOC
480 if (result != NULL)
481 #endif
482 {
483 memcpy (result, curr_prefix, curr_prefix_len);
484 strcpy (result + curr_prefix_len, pathname_tail);
485 return result;
486 }
487 }
488 }
489 /* Nothing to relocate. */
490 return pathname;
491 }
492
493 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698