OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / java / jcf-depend.c
1 /* Functions for handling dependency tracking when reading .class files.
2
3    Copyright (C) 1998, 1999, 2000  Free Software Foundation, Inc.
4
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.
9
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.
14
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.  
19
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.  */
23
24 /* Written by Tom Tromey <tromey@cygnus.com>, October 1998.  */
25
26 #include "config.h"
27 #include "system.h"
28
29 #include <assert.h>
30
31 #include "jcf.h"
32
33 \f
34
35 /* We keep a linked list of all the files we've already read.  */
36 struct entry
37 {
38   char *file;
39   struct entry *next;
40 };
41
42 static void free_entry PARAMS ((struct entry **));
43 static void add_entry PARAMS ((struct entry **, const char *));
44 static const char *munge PARAMS ((const char *));
45 static int print_ents PARAMS ((struct entry *, int));
46
47 /* List of files.  */
48 static struct entry *dependencies = NULL;
49
50 /* Name of targets.  We support multiple targets when writing .class
51    files.  */
52 static struct entry *targets = NULL;
53
54 /* Number of columns in output.  */
55 #define MAX_OUTPUT_COLUMNS 72
56
57 /* The output file, or NULL if we aren't doing dependency tracking.  */
58 static FILE *dep_out = NULL;
59
60 /* Nonzero if system files should be added.  */
61 static int system_files;
62
63 \f
64
65 /* Helper to free an entry list.  */
66 static void
67 free_entry (entp)
68      struct entry **entp;
69 {
70   struct entry *ent, *next;
71
72   for (ent = *entp; ent != NULL; ent = next)
73     {
74       next = ent->next;
75       free (ent->file);
76       free (ent);
77     }
78   *entp = NULL;
79 }
80
81 /* Helper to add to the end of the entry list.  */
82 static void
83 add_entry (entp, name)
84      struct entry **entp;
85      const char *name;
86 {
87   struct entry *ent, *last;
88
89   for (last = ent = *entp; ent != NULL; last = ent, ent = ent->next)
90     if (! strcmp (ent->file, name))
91       return;
92
93   ent = (struct entry *) xmalloc (sizeof (struct entry));
94   ent->file = xstrdup (name);
95   ent->next = NULL;
96
97   if (last == *entp)
98     {
99       // This is only true the first time through, when the entry list
100       // is empty.
101       *entp = ent;
102     }     
103   else
104     last->next = ent;
105 }
106
107 /* Call this to reset the dependency module.  This is required if
108    multiple dependency files are being generated from a single tool
109    invocation.  */
110 void
111 jcf_dependency_reset ()
112 {
113   free_entry (&dependencies);
114   free_entry (&targets);
115
116   if (dep_out != NULL)
117     {
118       if (dep_out != stdout)
119         fclose (dep_out);
120       dep_out = NULL;
121     }
122 }
123
124 void
125 jcf_dependency_set_target (name)
126      const char *name;
127 {
128   free_entry (&targets);
129   if (name != NULL)
130     add_entry (&targets, name);
131 }
132
133 void
134 jcf_dependency_add_target (name)
135      const char *name;
136 {
137   add_entry (&targets, name);
138 }
139
140 void
141 jcf_dependency_set_dep_file (name)
142      const char *name;
143 {
144   assert (dep_out != stdout);
145   if (dep_out)
146     fclose (dep_out);
147   if (! strcmp (name, "-"))
148     dep_out = stdout;
149   else
150     dep_out = fopen (name, "w");
151 }
152
153 void
154 jcf_dependency_add_file (filename, system_p)
155      const char *filename;
156      int system_p;
157 {
158   /* Just omit system files.  */
159   if (system_p && ! system_files)
160     return;
161
162   add_entry (&dependencies, filename);
163 }
164
165 void
166 jcf_dependency_init (system_p)
167      int system_p;
168 {
169   system_files = system_p;
170 }
171
172 /* FIXME: this is taken almost directly from cccp.c.  Such duplication
173    is bad.  */
174 static const char *
175 munge (filename)
176      const char *filename;
177 {
178   static char *buffer = NULL;
179   static int buflen = 0;
180
181   int len = 2 * strlen (filename) + 1;
182   const char *p;
183   char *dst;
184
185   if (buflen < len)
186     {
187       buflen = len;
188       buffer = xrealloc (buffer, buflen);
189     }
190
191   dst = buffer;
192   for (p = filename; *p; ++p)
193     {
194       switch (*p)
195         {
196         case ' ':
197         case '\t':
198           {
199             /* GNU make uses a weird quoting scheme for white space.
200                A space or tab preceded by 2N+1 backslashes represents
201                N backslashes followed by space; a space or tab
202                preceded by 2N backslashes represents N backslashes at
203                the end of a file name; and backslashes in other
204                contexts should not be doubled.  */
205             const char *q;
206             for (q = p - 1; filename < q && q[-1] == '\\';  q--)
207               *dst++ = '\\';
208           }
209           *dst++ = '\\';
210           goto ordinary_char;
211
212         case '$':
213           *dst++ = '$';
214           /* Fall through.  This can mishandle things like "$(" but
215              there's no easy fix.  */
216         default:
217         ordinary_char:
218           /* This can mishandle characters in the string "\0\n%*?[\\~";
219              exactly which chars are mishandled depends on the `make' version.
220              We know of no portable solution for this;
221              even GNU make 3.76.1 doesn't solve the problem entirely.
222              (Also, '\0' is mishandled due to our calling conventions.)  */
223           *dst++ = *p;
224           break;
225         }
226     }
227
228   *dst++ = '\0';
229   return buffer;
230 }
231
232 /* Helper to print list of files.  */
233 static int
234 print_ents (ent, column)
235      struct entry *ent;
236      int column;
237 {
238   int first = 1;
239
240   for (; ent != NULL; ent = ent->next)
241     {
242       const char *depname = munge (ent->file);
243       int len = strlen (depname);
244
245       if (column + len + 2 > MAX_OUTPUT_COLUMNS)
246         {
247           fprintf (dep_out, " \\\n ");
248           column = 1;
249         }
250
251       if (! first)
252         fputs (" ", dep_out);
253       fputs (depname, dep_out);
254       first = 0;
255       column += len + 1;
256     }
257
258   return column;
259 }
260
261 void
262 jcf_dependency_write ()
263 {
264   int column = 0;
265
266   if (! dep_out)
267     return;
268
269   assert (targets);
270   column = print_ents (targets, 0);
271   fputs (" : ", dep_out);
272
273   print_ents (dependencies, column);
274   fputs ("\n", dep_out);
275   fflush (dep_out);
276 }