]> gcc.gnu.org Git - gcc.git/blame - gcc/java/jcf-path.c
Make --CLASSPATH by a synonym for --classpath and -classpath.
[gcc.git] / gcc / java / jcf-path.c
CommitLineData
8603f9c5
TT
1/* Handle CLASSPATH, -classpath, and path searching.
2
2a85660d 3 Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc.
8603f9c5
TT
4
5This program is free software; you can redistribute it and/or modify
6it under the terms of the GNU General Public License as published by
7the Free Software Foundation; either version 2, or (at your option)
8any later version.
9
10This program is distributed in the hope that it will be useful,
11but WITHOUT ANY WARRANTY; without even the implied warranty of
12MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13GNU General Public License for more details.
14
15You should have received a copy of the GNU General Public License
16along with GNU CC; see the file COPYING. If not, write to
17the Free Software Foundation, 59 Temple Place - Suite 330,
18Boston, MA 02111-1307, USA.
19
20Java and all Java-based marks are trademarks or registered trademarks
21of Sun Microsystems, Inc. in the United States and other countries.
22The Free Software Foundation is independent of Sun Microsystems, Inc. */
23
24/* Written by Tom Tromey <tromey@cygnus.com>, October 1998. */
25
4504ead1 26#include "config.h"
8603f9c5
TT
27#include "system.h"
28
29#include "jcf.h"
30
31/* Some boilerplate that really belongs in a header. */
32
33#ifndef GET_ENV_PATH_LIST
34#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
35#endif
36
c2952b01
APB
37/* By default, colon separates directories in a path. */
38#ifndef PATH_SEPARATOR
39#define PATH_SEPARATOR ':'
40#endif
41
42#ifndef DIR_SEPARATOR
43#define DIR_SEPARATOR '/'
44#endif
45
71651d6c
TT
46#ifndef DIR_UP
47#define DIR_UP ".."
48#endif
49
8603f9c5
TT
50\f
51
52/* Possible flag values. */
53#define FLAG_SYSTEM 1
54#define FLAG_ZIP 2
55
56/* We keep linked lists of directory names. A ``directory'' can be
57 either an ordinary directory or a .zip file. */
58struct entry
59{
60 char *name;
61 int flags;
62 struct entry *next;
63};
64
df32d2ce
KG
65static void free_entry PARAMS ((struct entry **));
66static void append_entry PARAMS ((struct entry **, struct entry *));
67static void add_entry PARAMS ((struct entry **, const char *, int));
68static void add_path PARAMS ((struct entry **, const char *, int));
c8e7d2e6 69
8603f9c5
TT
70/* We support several different ways to set the class path.
71
f34ff6d6 72 built-in system directory (only libgcj.jar)
8603f9c5 73 CLASSPATH environment variable
db444fbe 74 -classpath option overrides $CLASSPATH
2a85660d
PB
75 -CLASSPATH option is a synonym for -classpath (for compatibility)
76 -bootclasspath overrides built-in
8603f9c5
TT
77 -I prepends path to list
78
79 We implement this by keeping several path lists, and then simply
80 ignoring the ones which are not relevant. */
81
82/* This holds all the -I directories. */
83static struct entry *include_dirs;
84
85/* This holds the CLASSPATH environment variable. */
86static struct entry *classpath_env;
87
db444fbe 88/* This holds the -classpath command-line option. */
2a85660d 89static struct entry *classpath_user;
8603f9c5
TT
90
91/* This holds the default directories. Some of these will have the
92 "system" flag set. */
93static struct entry *sys_dirs;
94
95/* This is the sealed list. It is just a combination of other lists. */
96static struct entry *sealed;
97
98/* We keep track of the longest path we've seen. */
99static int longest_path = 0;
100
101\f
102
103static void
104free_entry (entp)
105 struct entry **entp;
106{
107 struct entry *e, *n;
108
109 for (e = *entp; e; e = n)
110 {
111 n = e->next;
112 free (e->name);
113 free (e);
114 }
115 *entp = NULL;
116}
117
118static void
119append_entry (entp, ent)
120 struct entry **entp;
121 struct entry *ent;
122{
123 /* It doesn't matter if this is slow, since it is run only at
124 startup, and then infrequently. */
125 struct entry *e;
126
127 /* Find end of list. */
128 for (e = *entp; e && e->next; e = e->next)
129 ;
130
131 if (e)
132 e->next = ent;
133 else
134 *entp = ent;
135}
136
137static void
138add_entry (entp, filename, is_system)
139 struct entry **entp;
c8e7d2e6 140 const char *filename;
8603f9c5
TT
141 int is_system;
142{
143 int len;
144 struct entry *n;
145
146 n = (struct entry *) ALLOC (sizeof (struct entry));
147 n->flags = is_system ? FLAG_SYSTEM : 0;
148 n->next = NULL;
149
150 len = strlen (filename);
66af84e4
PB
151 if (len > 4 && (strcmp (filename + len - 4, ".zip") == 0
152 || strcmp (filename + len - 4, ".jar") == 0))
8603f9c5
TT
153 {
154 n->flags |= FLAG_ZIP;
155 /* If the user uses -classpath then he'll have to include
f34ff6d6 156 libgcj.jar in the value. We check for this in a simplistic
8603f9c5
TT
157 way. Symlinks will fool this test. This is only used for
158 -MM and -MMD, so it probably isn't terribly important. */
00368bdd 159 if (! strcmp (filename, LIBGCJ_ZIP_FILE))
8603f9c5
TT
160 n->flags |= FLAG_SYSTEM;
161 }
162
733b3a87
TT
163 /* Note that we add a trailing separator to `.zip' names as well.
164 This is a little hack that lets the searching code in jcf-io.c
165 work more easily. Eww. */
166 if (filename[len - 1] != '/' && filename[len - 1] != DIR_SEPARATOR)
8603f9c5 167 {
ecef190c 168 char *f2 = (char *) alloca (len + 2);
8603f9c5
TT
169 strcpy (f2, filename);
170 f2[len] = DIR_SEPARATOR;
171 f2[len + 1] = '\0';
c2e3db92 172 n->name = xstrdup (f2);
8603f9c5
TT
173 ++len;
174 }
175 else
c2e3db92 176 n->name = xstrdup (filename);
8603f9c5
TT
177
178 if (len > longest_path)
179 longest_path = len;
180
181 append_entry (entp, n);
182}
183
184static void
185add_path (entp, cp, is_system)
186 struct entry **entp;
c8e7d2e6 187 const char *cp;
8603f9c5
TT
188 int is_system;
189{
c8e7d2e6 190 const char *startp, *endp;
8603f9c5
TT
191
192 if (cp)
193 {
194 char *buf = (char *) alloca (strlen (cp) + 3);
195 startp = endp = cp;
196 while (1)
197 {
198 if (! *endp || *endp == PATH_SEPARATOR)
199 {
8603f9c5
TT
200 if (endp == startp)
201 {
202 buf[0] = '.';
203 buf[1] = DIR_SEPARATOR;
204 buf[2] = '\0';
205 }
71f6a8e2 206 else
8603f9c5 207 {
71f6a8e2
TT
208 strncpy (buf, startp, endp - startp);
209 buf[endp - startp] = '\0';
8603f9c5 210 }
8603f9c5
TT
211 add_entry (entp, buf, is_system);
212 if (! *endp)
213 break;
214 ++endp;
215 startp = endp;
216 }
217 else
218 ++endp;
219 }
220 }
221}
222
2a85660d
PB
223static int init_done = 0;
224
8603f9c5
TT
225/* Initialize the path module. */
226void
227jcf_path_init ()
228{
229 char *cp;
71651d6c
TT
230 char *try, sep[2];
231 struct stat stat_b;
232 int found = 0, len;
8603f9c5 233
2a85660d
PB
234 if (init_done)
235 return;
236 init_done = 1;
71651d6c
TT
237
238 sep[0] = DIR_SEPARATOR;
239 sep[1] = '\0';
240
241 GET_ENV_PATH_LIST (cp, "GCC_EXEC_PREFIX");
242 if (cp)
243 {
244 try = alloca (strlen (cp) + 50);
245 /* The exec prefix can be something like
246 /usr/local/bin/../lib/gcc-lib/. We want to change this
247 into a pointer to the share directory. We support two
248 configurations: one where prefix and exec-prefix are the
249 same, and one where exec-prefix is `prefix/SOMETHING'. */
250 strcpy (try, cp);
251 strcat (try, DIR_UP);
252 strcat (try, sep);
253 strcat (try, DIR_UP);
254 strcat (try, sep);
255 len = strlen (try);
256
257 strcpy (try + len, "share");
258 strcat (try, sep);
f34ff6d6 259 strcat (try, "libgcj.jar");
71651d6c
TT
260 if (! stat (try, &stat_b))
261 {
262 add_entry (&sys_dirs, try, 1);
263 found = 1;
264 }
265 else
266 {
267 strcpy (try + len, DIR_UP);
268 strcat (try, sep);
269 strcat (try, "share");
270 strcat (try, sep);
f34ff6d6 271 strcat (try, "libgcj.jar");
71651d6c
TT
272 if (! stat (try, &stat_b))
273 {
274 add_entry (&sys_dirs, try, 1);
275 found = 1;
276 }
277 }
278 }
279 if (! found)
280 {
281 /* Desperation: use the installed one. */
282 add_entry (&sys_dirs, LIBGCJ_ZIP_FILE, 1);
283 }
8603f9c5
TT
284
285 GET_ENV_PATH_LIST (cp, "CLASSPATH");
286 add_path (&classpath_env, cp, 0);
287}
288
2a85660d
PB
289/* Call this when -classpath is seen on the command line.
290 This overrides only the $CLASSPATH environment variable.
db444fbe 291 */
8603f9c5 292void
2a85660d 293jcf_path_classpath_arg (path)
c8e7d2e6 294 const char *path;
8603f9c5 295{
2a85660d
PB
296 free_entry (&classpath_user);
297 add_path (&classpath_user, path, 0);
8603f9c5
TT
298}
299
2a85660d 300/* Call this when -bootclasspath is seen on the command line.
db444fbe 301 */
8603f9c5 302void
2a85660d 303jcf_path_bootclasspath_arg (path)
c8e7d2e6 304 const char *path;
8603f9c5 305{
2a85660d
PB
306 free_entry (&sys_dirs);
307 add_path (&sys_dirs, path, 1);
8603f9c5
TT
308}
309
310/* Call this when -I is seen on the command line. */
311void
312jcf_path_include_arg (path)
c8e7d2e6 313 const char *path;
8603f9c5
TT
314{
315 add_entry (&include_dirs, path, 0);
316}
317
318/* We `seal' the path by linking everything into one big list. Then
4266d0b2
TT
319 we provide a way to iterate through the sealed list. If PRINT is
320 true then we print the final class path to stderr. */
8603f9c5 321void
4266d0b2
TT
322jcf_path_seal (print)
323 int print;
8603f9c5 324{
8603f9c5
TT
325 struct entry *secondary;
326
327 sealed = include_dirs;
328 include_dirs = NULL;
329
2a85660d 330 if (classpath_user)
8603f9c5 331 {
2a85660d
PB
332 secondary = classpath_user;
333 classpath_user = NULL;
8603f9c5
TT
334 }
335 else
336 {
2a85660d
PB
337 if (! classpath_env)
338 add_entry (&classpath_env, ".", 0);
339
8603f9c5
TT
340 secondary = classpath_env;
341 classpath_env = NULL;
342 }
343
2a85660d
PB
344
345 free_entry (&classpath_user);
8603f9c5
TT
346 free_entry (&classpath_env);
347
348 append_entry (&sealed, secondary);
2a85660d
PB
349 append_entry (&sealed, sys_dirs);
350 sys_dirs = NULL;
4266d0b2
TT
351
352 if (print)
353 {
354 struct entry *ent;
355 fprintf (stderr, "Class path starts here:\n");
356 for (ent = sealed; ent; ent = ent->next)
357 {
358 fprintf (stderr, " %s", ent->name);
359 if ((ent->flags & FLAG_SYSTEM))
360 fprintf (stderr, " (system)");
361 if ((ent->flags & FLAG_ZIP))
362 fprintf (stderr, " (zip)");
363 fprintf (stderr, "\n");
364 }
365 }
8603f9c5
TT
366}
367
368void *
369jcf_path_start ()
370{
371 return (void *) sealed;
372}
373
374void *
375jcf_path_next (x)
376 void *x;
377{
378 struct entry *ent = (struct entry *) x;
379 return (void *) ent->next;
380}
381
382/* We guarantee that the return path will either be a zip file, or it
383 will end with a directory separator. */
384char *
385jcf_path_name (x)
386 void *x;
387{
388 struct entry *ent = (struct entry *) x;
389 return ent->name;
390}
391
392int
393jcf_path_is_zipfile (x)
394 void *x;
395{
396 struct entry *ent = (struct entry *) x;
397 return (ent->flags & FLAG_ZIP);
398}
399
400int
401jcf_path_is_system (x)
402 void *x;
403{
404 struct entry *ent = (struct entry *) x;
405 return (ent->flags & FLAG_SYSTEM);
406}
407
408int
409jcf_path_max_len ()
410{
411 return longest_path;
412}
This page took 0.808257 seconds and 5 git commands to generate.