1 /* Handle CLASSPATH, -classpath, and path searching.
3 Copyright (C) 1998, 1999 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)
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. */
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)
37 /* By default, colon separates directories in a path. */
38 #ifndef PATH_SEPARATOR
39 #define PATH_SEPARATOR ':'
43 #define DIR_SEPARATOR '/'
48 /* Possible flag values. */
52 /* We keep linked lists of directory names. A ``directory'' can be
53 either an ordinary directory or a .zip file. */
61 static void free_entry
PROTO ((struct entry
**));
62 static void append_entry
PROTO ((struct entry
**, struct entry
*));
63 static void add_entry
PROTO ((struct entry
**, const char *, int));
64 static void add_path
PROTO ((struct entry
**, const char *, int));
66 /* We support several different ways to set the class path.
68 built-in system directory (only libgcj.zip)
69 CLASSPATH environment variable
70 -CLASSPATH overrides CLASSPATH
71 -classpath option - overrides CLASSPATH, -CLASSPATH, and built-in
72 -I prepends path to list
74 We implement this by keeping several path lists, and then simply
75 ignoring the ones which are not relevant. */
77 /* This holds all the -I directories. */
78 static struct entry
*include_dirs
;
80 /* This holds the CLASSPATH environment variable. */
81 static struct entry
*classpath_env
;
83 /* This holds the -CLASSPATH command-line option. */
84 static struct entry
*classpath_u
;
86 /* This holds the -classpath command-line option. */
87 static struct entry
*classpath_l
;
89 /* This holds the default directories. Some of these will have the
91 static struct entry
*sys_dirs
;
93 /* This is the sealed list. It is just a combination of other lists. */
94 static struct entry
*sealed
;
96 /* We keep track of the longest path we've seen. */
97 static int longest_path
= 0;
107 for (e
= *entp
; e
; e
= n
)
117 append_entry (entp
, ent
)
121 /* It doesn't matter if this is slow, since it is run only at
122 startup, and then infrequently. */
125 /* Find end of list. */
126 for (e
= *entp
; e
&& e
->next
; e
= e
->next
)
136 add_entry (entp
, filename
, is_system
)
138 const char *filename
;
144 n
= (struct entry
*) ALLOC (sizeof (struct entry
));
145 n
->flags
= is_system
? FLAG_SYSTEM
: 0;
148 len
= strlen (filename
);
149 if (len
> 4 && (strcmp (filename
+ len
- 4, ".zip") == 0
150 || strcmp (filename
+ len
- 4, ".jar") == 0))
152 n
->flags
|= FLAG_ZIP
;
153 /* If the user uses -classpath then he'll have to include
154 libgcj.zip in the value. We check for this in a simplistic
155 way. Symlinks will fool this test. This is only used for
156 -MM and -MMD, so it probably isn't terribly important. */
157 if (! strcmp (filename
, LIBGCJ_ZIP_FILE
))
158 n
->flags
|= FLAG_SYSTEM
;
161 /* Note that we add a trailing separator to `.zip' names as well.
162 This is a little hack that lets the searching code in jcf-io.c
163 work more easily. Eww. */
164 if (filename
[len
- 1] != '/' && filename
[len
- 1] != DIR_SEPARATOR
)
166 char *f2
= (char *) alloca (len
+ 2);
167 strcpy (f2
, filename
);
168 f2
[len
] = DIR_SEPARATOR
;
170 n
->name
= xstrdup (f2
);
174 n
->name
= xstrdup (filename
);
176 if (len
> longest_path
)
179 append_entry (entp
, n
);
183 add_path (entp
, cp
, is_system
)
188 const char *startp
, *endp
;
192 char *buf
= (char *) alloca (strlen (cp
) + 3);
196 if (! *endp
|| *endp
== PATH_SEPARATOR
)
201 buf
[1] = DIR_SEPARATOR
;
206 strncpy (buf
, startp
, endp
- startp
);
207 buf
[endp
- startp
] = '\0';
209 add_entry (entp
, buf
, is_system
);
221 /* Initialize the path module. */
227 add_entry (&sys_dirs
, ".", 0);
228 add_entry (&sys_dirs
, LIBGCJ_ZIP_FILE
, 1);
230 GET_ENV_PATH_LIST (cp
, "CLASSPATH");
231 add_path (&classpath_env
, cp
, 0);
234 /* Call this when -classpath is seen on the command line. */
236 jcf_path_classpath_arg (path
)
239 free_entry (&classpath_l
);
240 add_path (&classpath_l
, path
, 0);
243 /* Call this when -CLASSPATH is seen on the command line. */
245 jcf_path_CLASSPATH_arg (path
)
248 free_entry (&classpath_u
);
249 add_path (&classpath_u
, path
, 0);
252 /* Call this when -I is seen on the command line. */
254 jcf_path_include_arg (path
)
257 add_entry (&include_dirs
, path
, 0);
260 /* We `seal' the path by linking everything into one big list. Then
261 we provide a way to iterate through the sealed list. */
266 struct entry
*secondary
;
268 sealed
= include_dirs
;
273 secondary
= classpath_l
;
277 else if (classpath_u
)
279 secondary
= classpath_u
;
284 secondary
= classpath_env
;
285 classpath_env
= NULL
;
288 free_entry (&classpath_l
);
289 free_entry (&classpath_u
);
290 free_entry (&classpath_env
);
292 append_entry (&sealed
, secondary
);
296 append_entry (&sealed
, sys_dirs
);
300 free_entry (&sys_dirs
);
306 return (void *) sealed
;
313 struct entry
*ent
= (struct entry
*) x
;
314 return (void *) ent
->next
;
317 /* We guarantee that the return path will either be a zip file, or it
318 will end with a directory separator. */
323 struct entry
*ent
= (struct entry
*) x
;
328 jcf_path_is_zipfile (x
)
331 struct entry
*ent
= (struct entry
*) x
;
332 return (ent
->flags
& FLAG_ZIP
);
336 jcf_path_is_system (x
)
339 struct entry
*ent
= (struct entry
*) x
;
340 return (ent
->flags
& FLAG_SYSTEM
);