* doc/invoke.texi (i386 Options): Document x86-64 options.
[official-gcc.git] / gcc / java / jcf-path.c
blob079cb365411eed6e725f010be328f4f6bc4f80e9
1 /* Handle CLASSPATH, -classpath, and path searching.
3 Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2, or (at your option)
8 any later version.
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
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with GNU CC; see the file COPYING. If not, write to
17 the Free Software Foundation, 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
20 Java and all Java-based marks are trademarks or registered trademarks
21 of Sun Microsystems, Inc. in the United States and other countries.
22 The Free Software Foundation is independent of Sun Microsystems, Inc. */
24 /* Written by Tom Tromey <tromey@cygnus.com>, October 1998. */
26 #include "config.h"
27 #include "system.h"
29 #include "jcf.h"
31 /* Some boilerplate that really belongs in a header. */
33 #ifndef GET_ENV_PATH_LIST
34 #define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
35 #endif
37 /* By default, colon separates directories in a path. */
38 #ifndef PATH_SEPARATOR
39 #define PATH_SEPARATOR ':'
40 #endif
42 #ifndef DIR_SEPARATOR
43 #define DIR_SEPARATOR '/'
44 #endif
46 #ifndef DIR_UP
47 #define DIR_UP ".."
48 #endif
52 /* Possible flag values. */
53 #define FLAG_SYSTEM 1
54 #define FLAG_ZIP 2
56 /* We keep linked lists of directory names. A ``directory'' can be
57 either an ordinary directory or a .zip file. */
58 struct entry
60 char *name;
61 int flags;
62 struct entry *next;
65 static void free_entry PARAMS ((struct entry **));
66 static void append_entry PARAMS ((struct entry **, struct entry *));
67 static void add_entry PARAMS ((struct entry **, const char *, int));
68 static void add_path PARAMS ((struct entry **, const char *, int));
70 /* We support several different ways to set the class path.
72 built-in system directory (only libgcj.jar)
73 CLASSPATH environment variable
74 -CLASSPATH overrides CLASSPATH
75 -classpath option - overrides CLASSPATH, -CLASSPATH, and built-in
76 -I prepends path to list
78 We implement this by keeping several path lists, and then simply
79 ignoring the ones which are not relevant. */
81 /* This holds all the -I directories. */
82 static struct entry *include_dirs;
84 /* This holds the CLASSPATH environment variable. */
85 static struct entry *classpath_env;
87 /* This holds the -CLASSPATH command-line option. */
88 static struct entry *classpath_u;
90 /* This holds the -classpath command-line option. */
91 static struct entry *classpath_l;
93 /* This holds the default directories. Some of these will have the
94 "system" flag set. */
95 static struct entry *sys_dirs;
97 /* This is the sealed list. It is just a combination of other lists. */
98 static struct entry *sealed;
100 /* We keep track of the longest path we've seen. */
101 static int longest_path = 0;
105 static void
106 free_entry (entp)
107 struct entry **entp;
109 struct entry *e, *n;
111 for (e = *entp; e; e = n)
113 n = e->next;
114 free (e->name);
115 free (e);
117 *entp = NULL;
120 static void
121 append_entry (entp, ent)
122 struct entry **entp;
123 struct entry *ent;
125 /* It doesn't matter if this is slow, since it is run only at
126 startup, and then infrequently. */
127 struct entry *e;
129 /* Find end of list. */
130 for (e = *entp; e && e->next; e = e->next)
133 if (e)
134 e->next = ent;
135 else
136 *entp = ent;
139 static void
140 add_entry (entp, filename, is_system)
141 struct entry **entp;
142 const char *filename;
143 int is_system;
145 int len;
146 struct entry *n;
148 n = (struct entry *) ALLOC (sizeof (struct entry));
149 n->flags = is_system ? FLAG_SYSTEM : 0;
150 n->next = NULL;
152 len = strlen (filename);
153 if (len > 4 && (strcmp (filename + len - 4, ".zip") == 0
154 || strcmp (filename + len - 4, ".jar") == 0))
156 n->flags |= FLAG_ZIP;
157 /* If the user uses -classpath then he'll have to include
158 libgcj.jar in the value. We check for this in a simplistic
159 way. Symlinks will fool this test. This is only used for
160 -MM and -MMD, so it probably isn't terribly important. */
161 if (! strcmp (filename, LIBGCJ_ZIP_FILE))
162 n->flags |= FLAG_SYSTEM;
165 /* Note that we add a trailing separator to `.zip' names as well.
166 This is a little hack that lets the searching code in jcf-io.c
167 work more easily. Eww. */
168 if (filename[len - 1] != '/' && filename[len - 1] != DIR_SEPARATOR)
170 char *f2 = (char *) alloca (len + 2);
171 strcpy (f2, filename);
172 f2[len] = DIR_SEPARATOR;
173 f2[len + 1] = '\0';
174 n->name = xstrdup (f2);
175 ++len;
177 else
178 n->name = xstrdup (filename);
180 if (len > longest_path)
181 longest_path = len;
183 append_entry (entp, n);
186 static void
187 add_path (entp, cp, is_system)
188 struct entry **entp;
189 const char *cp;
190 int is_system;
192 const char *startp, *endp;
194 if (cp)
196 char *buf = (char *) alloca (strlen (cp) + 3);
197 startp = endp = cp;
198 while (1)
200 if (! *endp || *endp == PATH_SEPARATOR)
202 if (endp == startp)
204 buf[0] = '.';
205 buf[1] = DIR_SEPARATOR;
206 buf[2] = '\0';
208 else
210 strncpy (buf, startp, endp - startp);
211 buf[endp - startp] = '\0';
213 add_entry (entp, buf, is_system);
214 if (! *endp)
215 break;
216 ++endp;
217 startp = endp;
219 else
220 ++endp;
225 /* Initialize the path module. */
226 void
227 jcf_path_init ()
229 char *cp;
230 char *try, sep[2];
231 struct stat stat_b;
232 int found = 0, len;
234 add_entry (&sys_dirs, ".", 0);
236 sep[0] = DIR_SEPARATOR;
237 sep[1] = '\0';
239 GET_ENV_PATH_LIST (cp, "GCC_EXEC_PREFIX");
240 if (cp)
242 try = alloca (strlen (cp) + 50);
243 /* The exec prefix can be something like
244 /usr/local/bin/../lib/gcc-lib/. We want to change this
245 into a pointer to the share directory. We support two
246 configurations: one where prefix and exec-prefix are the
247 same, and one where exec-prefix is `prefix/SOMETHING'. */
248 strcpy (try, cp);
249 strcat (try, DIR_UP);
250 strcat (try, sep);
251 strcat (try, DIR_UP);
252 strcat (try, sep);
253 len = strlen (try);
255 strcpy (try + len, "share");
256 strcat (try, sep);
257 strcat (try, "libgcj.jar");
258 if (! stat (try, &stat_b))
260 add_entry (&sys_dirs, try, 1);
261 found = 1;
263 else
265 strcpy (try + len, DIR_UP);
266 strcat (try, sep);
267 strcat (try, "share");
268 strcat (try, sep);
269 strcat (try, "libgcj.jar");
270 if (! stat (try, &stat_b))
272 add_entry (&sys_dirs, try, 1);
273 found = 1;
277 if (! found)
279 /* Desperation: use the installed one. */
280 add_entry (&sys_dirs, LIBGCJ_ZIP_FILE, 1);
283 GET_ENV_PATH_LIST (cp, "CLASSPATH");
284 add_path (&classpath_env, cp, 0);
287 /* Call this when -classpath is seen on the command line. */
288 void
289 jcf_path_classpath_arg (path)
290 const char *path;
292 free_entry (&classpath_l);
293 add_path (&classpath_l, path, 0);
296 /* Call this when -CLASSPATH is seen on the command line. */
297 void
298 jcf_path_CLASSPATH_arg (path)
299 const char *path;
301 free_entry (&classpath_u);
302 add_path (&classpath_u, path, 0);
305 /* Call this when -I is seen on the command line. */
306 void
307 jcf_path_include_arg (path)
308 const char *path;
310 add_entry (&include_dirs, path, 0);
313 /* We `seal' the path by linking everything into one big list. Then
314 we provide a way to iterate through the sealed list. If PRINT is
315 true then we print the final class path to stderr. */
316 void
317 jcf_path_seal (print)
318 int print;
320 int do_system = 1;
321 struct entry *secondary;
323 sealed = include_dirs;
324 include_dirs = NULL;
326 if (classpath_l)
328 secondary = classpath_l;
329 classpath_l = NULL;
330 do_system = 0;
332 else if (classpath_u)
334 secondary = classpath_u;
335 classpath_u = NULL;
337 else
339 secondary = classpath_env;
340 classpath_env = NULL;
343 free_entry (&classpath_l);
344 free_entry (&classpath_u);
345 free_entry (&classpath_env);
347 append_entry (&sealed, secondary);
349 if (do_system)
351 append_entry (&sealed, sys_dirs);
352 sys_dirs = NULL;
354 else
355 free_entry (&sys_dirs);
357 if (print)
359 struct entry *ent;
360 fprintf (stderr, "Class path starts here:\n");
361 for (ent = sealed; ent; ent = ent->next)
363 fprintf (stderr, " %s", ent->name);
364 if ((ent->flags & FLAG_SYSTEM))
365 fprintf (stderr, " (system)");
366 if ((ent->flags & FLAG_ZIP))
367 fprintf (stderr, " (zip)");
368 fprintf (stderr, "\n");
373 void *
374 jcf_path_start ()
376 return (void *) sealed;
379 void *
380 jcf_path_next (x)
381 void *x;
383 struct entry *ent = (struct entry *) x;
384 return (void *) ent->next;
387 /* We guarantee that the return path will either be a zip file, or it
388 will end with a directory separator. */
389 char *
390 jcf_path_name (x)
391 void *x;
393 struct entry *ent = (struct entry *) x;
394 return ent->name;
398 jcf_path_is_zipfile (x)
399 void *x;
401 struct entry *ent = (struct entry *) x;
402 return (ent->flags & FLAG_ZIP);
406 jcf_path_is_system (x)
407 void *x;
409 struct entry *ent = (struct entry *) x;
410 return (ent->flags & FLAG_SYSTEM);
414 jcf_path_max_len ()
416 return longest_path;