/* Handle CLASSPATH, -classpath, and path searching.
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
+ Free Software Foundation, Inc.
- Copyright (C) 1998 Free Software Foundation, Inc.
+This file is part of GCC.
-This program is free software; you can redistribute it and/or modify
+GCC is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
-This program is distributed in the hope that it will be useful,
+GCC is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING. If not, write to
+along with GCC; see the file COPYING. If not, write to
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
/* Written by Tom Tromey <tromey@cygnus.com>, October 1998. */
-#include <config.h>
+#include "config.h"
#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
-#include "jcf.h"
-
-/* Some boilerplate that really belongs in a header. */
+#include <dirent.h>
-#ifndef GET_ENV_PATH_LIST
-#define GET_ENV_PATH_LIST(VAR,NAME) do { (VAR) = getenv (NAME); } while (0)
-#endif
+#include "jcf.h"
/* By default, colon separates directories in a path. */
#ifndef PATH_SEPARATOR
#define DIR_SEPARATOR '/'
#endif
+#ifndef DIR_UP
+#define DIR_UP ".."
+#endif
+
\f
/* Possible flag values. */
struct entry *next;
};
+static void free_entry PARAMS ((struct entry **));
+static void append_entry PARAMS ((struct entry **, struct entry *));
+static void add_entry PARAMS ((struct entry **, const char *, int));
+static void add_path PARAMS ((struct entry **, const char *, int));
+
/* We support several different ways to set the class path.
- built-in system directory (only libjava.zip)
+ built-in system directory (only libgcj.jar)
CLASSPATH environment variable
- -CLASSPATH overrides CLASSPATH
- -classpath option - overrides CLASSPATH, -CLASSPATH, and built-in
+ -classpath option overrides $CLASSPATH
+ -CLASSPATH option is a synonym for -classpath (for compatibility)
+ -bootclasspath overrides built-in
+ -extdirs sets the extensions directory path (overrides built-in)
-I prepends path to list
We implement this by keeping several path lists, and then simply
/* This holds the CLASSPATH environment variable. */
static struct entry *classpath_env;
-/* This holds the -CLASSPATH command-line option. */
-static struct entry *classpath_u;
-
/* This holds the -classpath command-line option. */
-static struct entry *classpath_l;
+static struct entry *classpath_user;
/* This holds the default directories. Some of these will have the
"system" flag set. */
static struct entry *sys_dirs;
+/* This holds the extensions path entries. */
+static struct entry *extensions;
+
/* This is the sealed list. It is just a combination of other lists. */
static struct entry *sealed;
static void
add_entry (entp, filename, is_system)
struct entry **entp;
- char *filename;
+ const char *filename;
int is_system;
{
int len;
struct entry *n;
- n = (struct entry *) ALLOC (sizeof (struct entry));
+ n = ALLOC (sizeof (struct entry));
n->flags = is_system ? FLAG_SYSTEM : 0;
n->next = NULL;
len = strlen (filename);
- if (len > 4 && ! strcmp (filename - 4, ".zip"))
+ if (len > 4 && (strcmp (filename + len - 4, ".zip") == 0
+ || strcmp (filename + len - 4, ".jar") == 0))
{
n->flags |= FLAG_ZIP;
/* If the user uses -classpath then he'll have to include
- libjava.zip in the value. We check for this in a simplistic
+ libgcj.jar in the value. We check for this in a simplistic
way. Symlinks will fool this test. This is only used for
-MM and -MMD, so it probably isn't terribly important. */
- if (! strcmp (filename, LIBJAVA_ZIP_FILE))
+ if (! strcmp (filename, LIBGCJ_ZIP_FILE))
n->flags |= FLAG_SYSTEM;
}
- if (! (n->flags & FLAG_ZIP)
- && filename[len - 1] != '/'
- && filename[len - 1] != DIR_SEPARATOR)
+ /* Note that we add a trailing separator to `.zip' names as well.
+ This is a little hack that lets the searching code in jcf-io.c
+ work more easily. Eww. */
+ if (filename[len - 1] != '/' && filename[len - 1] != DIR_SEPARATOR)
{
- char *f2 = (char *) alloca (len + 1);
+ char *f2 = alloca (len + 2);
strcpy (f2, filename);
f2[len] = DIR_SEPARATOR;
f2[len + 1] = '\0';
- n->name = strdup (f2);
+ n->name = xstrdup (f2);
++len;
}
else
- n->name = strdup (filename);
+ n->name = xstrdup (filename);
if (len > longest_path)
longest_path = len;
static void
add_path (entp, cp, is_system)
struct entry **entp;
- char *cp;
+ const char *cp;
int is_system;
{
- char *startp, *endp;
+ const char *startp, *endp;
if (cp)
{
- char *buf = (char *) alloca (strlen (cp) + 3);
+ char *buf = alloca (strlen (cp) + 3);
startp = endp = cp;
while (1)
{
}
}
+static int init_done = 0;
+
/* Initialize the path module. */
void
jcf_path_init ()
{
char *cp;
+ char *try, sep[2];
+ struct stat stat_b;
+ int found = 0, len;
+
+ if (init_done)
+ return;
+ init_done = 1;
- add_entry (&sys_dirs, ".", 0);
- add_entry (&sys_dirs, LIBJAVA_ZIP_FILE, 1);
+ sep[0] = DIR_SEPARATOR;
+ sep[1] = '\0';
- GET_ENV_PATH_LIST (cp, "CLASSPATH");
+ GET_ENVIRONMENT (cp, "GCC_EXEC_PREFIX");
+ if (cp)
+ {
+ try = alloca (strlen (cp) + 50);
+ /* The exec prefix can be something like
+ /usr/local/bin/../lib/gcc-lib/. We want to change this
+ into a pointer to the share/java directory. We support two
+ configurations: one where prefix and exec-prefix are the
+ same, and one where exec-prefix is `prefix/SOMETHING'. */
+ strcpy (try, cp);
+ strcat (try, DIR_UP);
+ strcat (try, sep);
+ strcat (try, DIR_UP);
+ strcat (try, sep);
+ len = strlen (try);
+
+ strcpy (try + len, "share");
+ strcat (try, sep);
+ strcat (try, "java");
+ strcat (try, sep);
+ strcat (try, "libgcj-" DEFAULT_TARGET_VERSION ".jar");
+ if (! stat (try, &stat_b))
+ {
+ add_entry (&sys_dirs, try, 1);
+ found = 1;
+ strcpy (&try[strlen (try)
+ - strlen ("libgcj-" DEFAULT_TARGET_VERSION ".jar")],
+ sep);
+ strcat (try, "ext");
+ strcat (try, sep);
+ if (! stat (try, &stat_b))
+ jcf_path_extdirs_arg (try);
+ }
+ else
+ {
+ strcpy (try + len, DIR_UP);
+ strcat (try, sep);
+ strcat (try, "share");
+ strcat (try, sep);
+ strcat (try, "java");
+ strcat (try, sep);
+ strcat (try, "libgcj-" DEFAULT_TARGET_VERSION ".jar");
+ if (! stat (try, &stat_b))
+ {
+ add_entry (&sys_dirs, try, 1);
+ found = 1;
+ strcpy (&try[strlen (try)
+ - strlen ("libgcj-" DEFAULT_TARGET_VERSION ".jar")],
+ sep);
+ strcat (try, "ext");
+ strcat (try, sep);
+ if (! stat (try, &stat_b))
+ jcf_path_extdirs_arg (try);
+ }
+ }
+ }
+ if (! found)
+ {
+ /* Desperation: use the installed one. */
+ char *extdirs;
+ add_entry (&sys_dirs, LIBGCJ_ZIP_FILE, 1);
+ extdirs = alloca (strlen (LIBGCJ_ZIP_FILE) + 1);
+ strcpy (extdirs, LIBGCJ_ZIP_FILE);
+ strcpy (&extdirs[strlen (LIBGCJ_ZIP_FILE)
+ - strlen ("libgcj-" DEFAULT_TARGET_VERSION ".jar")],
+ "ext");
+ strcat (extdirs, sep);
+ if (! stat (extdirs, &stat_b))
+ jcf_path_extdirs_arg (extdirs);
+ }
+
+ GET_ENVIRONMENT (cp, "CLASSPATH");
add_path (&classpath_env, cp, 0);
}
-/* Call this when -classpath is seen on the command line. */
+/* Call this when -classpath is seen on the command line.
+ This overrides only the $CLASSPATH environment variable.
+ */
void
jcf_path_classpath_arg (path)
- char *path;
+ const char *path;
+{
+ free_entry (&classpath_user);
+ add_path (&classpath_user, path, 0);
+}
+
+/* Call this when -bootclasspath is seen on the command line.
+ */
+void
+jcf_path_bootclasspath_arg (path)
+ const char *path;
{
- free_entry (&classpath_l);
- add_path (&classpath_l, path, 0);
+ free_entry (&sys_dirs);
+ add_path (&sys_dirs, path, 1);
}
-/* Call this when -CLASSPATH is seen on the command line. */
+/* Call this when -extdirs is seen on the command line.
+ */
void
-jcf_path_CLASSPATH_arg (path)
- char *path;
+jcf_path_extdirs_arg (cp)
+ const char *cp;
{
- free_entry (&classpath_u);
- add_path (&classpath_u, path, 0);
+ const char *startp, *endp;
+
+ free_entry (&extensions);
+
+ if (cp)
+ {
+ char *buf = alloca (strlen (cp) + 3);
+ startp = endp = cp;
+ while (1)
+ {
+ if (! *endp || *endp == PATH_SEPARATOR)
+ {
+ if (endp == startp)
+ return;
+
+ strncpy (buf, startp, endp - startp);
+ buf[endp - startp] = '\0';
+
+ {
+ DIR *dirp = NULL;
+ int dirname_length = strlen (buf);
+
+ dirp = opendir (buf);
+ if (dirp == NULL)
+ return;
+
+ for (;;)
+ {
+ struct dirent *direntp = readdir (dirp);
+
+ if (!direntp)
+ break;
+
+ if (direntp->d_name[0] != '.')
+ {
+ char *name = alloca (dirname_length
+ + strlen (direntp->d_name) + 2);
+ strcpy (name, buf);
+ if (name[dirname_length-1] != DIR_SEPARATOR)
+ {
+ name[dirname_length] = DIR_SEPARATOR;
+ name[dirname_length+1] = 0;
+ }
+ strcat (name, direntp->d_name);
+ add_entry (&extensions, name, 0);
+ }
+ }
+ }
+
+ if (! *endp)
+ break;
+ ++endp;
+ startp = endp;
+ }
+ else
+ ++endp;
+ }
+ }
}
/* Call this when -I is seen on the command line. */
void
jcf_path_include_arg (path)
- char *path;
+ const char *path;
{
add_entry (&include_dirs, path, 0);
}
/* We `seal' the path by linking everything into one big list. Then
- we provide a way to iterate through the sealed list. */
+ we provide a way to iterate through the sealed list. If PRINT is
+ true then we print the final class path to stderr. */
void
-jcf_path_seal ()
+jcf_path_seal (print)
+ int print;
{
- int do_system = 1;
struct entry *secondary;
sealed = include_dirs;
include_dirs = NULL;
- if (classpath_l)
+ if (classpath_user)
{
- secondary = classpath_l;
- classpath_l = NULL;
- do_system = 0;
- }
- else if (classpath_u)
- {
- secondary = classpath_u;
- classpath_u = NULL;
+ secondary = classpath_user;
+ classpath_user = NULL;
}
else
{
+ if (! classpath_env)
+ add_entry (&classpath_env, ".", 0);
+
secondary = classpath_env;
classpath_env = NULL;
}
- free_entry (&classpath_l);
- free_entry (&classpath_u);
+
+ free_entry (&classpath_user);
free_entry (&classpath_env);
append_entry (&sealed, secondary);
+ append_entry (&sealed, sys_dirs);
+ append_entry (&sealed, extensions);
+ sys_dirs = NULL;
+ extensions = NULL;
- if (do_system)
+ if (print)
{
- append_entry (&sealed, sys_dirs);
- sys_dirs = NULL;
+ struct entry *ent;
+ fprintf (stderr, "Class path starts here:\n");
+ for (ent = sealed; ent; ent = ent->next)
+ {
+ fprintf (stderr, " %s", ent->name);
+ if ((ent->flags & FLAG_SYSTEM))
+ fprintf (stderr, " (system)");
+ if ((ent->flags & FLAG_ZIP))
+ fprintf (stderr, " (zip)");
+ fprintf (stderr, "\n");
+ }
}
- else
- free_entry (&sys_dirs);
}
void *