blob: 86b9d7722fe811503a7beef3eb5d4a1d553bca03 [file] [log] [blame]
/* Functions for handling dependency tracking when reading .class files.
Copyright (C) 1998 Free Software Foundation, Inc.
This program 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,
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
the Free Software Foundation, 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
Java and all Java-based marks are trademarks or registered trademarks
of Sun Microsystems, Inc. in the United States and other countries.
The Free Software Foundation is independent of Sun Microsystems, Inc. */
/* Written by Tom Tromey <tromey@cygnus.com>, October 1998. */
#include "config.h"
#include "system.h"
#include <assert.h>
#include "jcf.h"
/* We keep a linked list of all the files we've already read. */
struct entry
{
char *file;
struct entry *next;
};
/* List of files. */
static struct entry *dependencies = NULL;
/* Name of targets. We support multiple targets when writing .class
files. */
static struct entry *targets = NULL;
/* Number of columns in output. */
#define MAX_OUTPUT_COLUMNS 72
/* The output file, or NULL if we aren't doing dependency tracking. */
static FILE *dep_out = NULL;
/* Nonzero if system files should be added. */
static int system_files;
/* Helper to free an entry list. */
static void
free_entry (entp)
struct entry **entp;
{
struct entry *ent, *next;
for (ent = *entp; ent != NULL; ent = next)
{
next = ent->next;
free (ent->file);
free (ent);
}
*entp = NULL;
}
/* Helper to add to entry list. */
static void
add_entry (entp, name)
struct entry **entp;
char *name;
{
struct entry *ent;
for (ent = *entp; ent != NULL; ent = ent->next)
if (! strcmp (ent->file, name))
return;
ent = (struct entry *) malloc (sizeof (struct entry));
ent->file = strdup (name);
ent->next = *entp;
*entp = ent;
}
/* Call this to reset the dependency module. This is required if
multiple dependency files are being generated from a single tool
invocation. */
void
jcf_dependency_reset ()
{
free_entry (&dependencies);
free_entry (&targets);
if (dep_out != NULL)
{
if (dep_out != stdout)
fclose (dep_out);
dep_out = NULL;
}
}
void
jcf_dependency_set_target (name)
char *name;
{
free_entry (&targets);
if (name != NULL)
add_entry (&targets, name);
}
void
jcf_dependency_add_target (name)
char *name;
{
add_entry (&targets, name);
}
void
jcf_dependency_set_dep_file (name)
const char *name;
{
assert (dep_out != stdout);
if (dep_out)
fclose (dep_out);
if (! strcmp (name, "-"))
dep_out = stdout;
else
dep_out = fopen (name, "w");
}
void
jcf_dependency_add_file (filename, system_p)
const char *filename;
int system_p;
{
/* Just omit system files. */
if (system_p && ! system_files)
return;
add_entry (&dependencies, filename);
}
void
jcf_dependency_init (system_p)
int system_p;
{
system_files = system_p;
}
/* FIXME: this is taken almost directly from cccp.c. Such duplication
is bad. */
static char *
munge (filename)
char *filename;
{
static char *buffer = NULL;
static int buflen = 0;
int len = 2 * strlen (filename) + 1;
char *p, *dst;
if (buflen < len)
{
buflen = len;
if (buffer == NULL)
buffer = malloc (buflen);
else
buffer = realloc (buffer, buflen);
}
dst = buffer;
for (p = filename; *p; ++p)
{
switch (*p)
{
case ' ':
case '\t':
{
/* GNU make uses a weird quoting scheme for white space.
A space or tab preceded by 2N+1 backslashes represents
N backslashes followed by space; a space or tab
preceded by 2N backslashes represents N backslashes at
the end of a file name; and backslashes in other
contexts should not be doubled. */
char *q;
for (q = p - 1; filename < q && q[-1] == '\\'; q--)
*dst++ = '\\';
}
*dst++ = '\\';
goto ordinary_char;
case '$':
*dst++ = '$';
/* Fall through. This can mishandle things like "$(" but
there's no easy fix. */
default:
ordinary_char:
/* This can mishandle characters in the string "\0\n%*?[\\~";
exactly which chars are mishandled depends on the `make' version.
We know of no portable solution for this;
even GNU make 3.76.1 doesn't solve the problem entirely.
(Also, '\0' is mishandled due to our calling conventions.) */
*dst++ = *p;
break;
}
}
*dst++ = '\0';
return buffer;
}
/* Helper to print list of files. */
static int
print_ents (ent, column)
struct entry *ent;
int column;
{
int first = 1;
for (; ent != NULL; ent = ent->next)
{
char *depname = munge (ent->file);
int len = strlen (depname);
if (column + len + 2 > MAX_OUTPUT_COLUMNS)
{
fprintf (dep_out, " \\\n ");
column = 1;
}
if (! first)
fputs (" ", dep_out);
fputs (depname, dep_out);
first = 0;
column += len + 1;
}
return column;
}
void
jcf_dependency_write ()
{
int column = 0;
if (! dep_out)
return;
assert (targets);
column = print_ents (targets, 0);
fputs (" : ", dep_out);
print_ents (dependencies, column);
fputs ("\n", dep_out);
fflush (dep_out);
}