OSDN Git Service

* tree-dfa.c (get_ref_base_and_extent) <ARRAY_REF>: Remove space.
[pf3gnuchains/gcc-fork.git] / gcc / java / jcf-io.c
1 /* Utility routines for finding and reading Java(TM) .class files.
2    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
3    2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
11
12 GCC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3.  If not see
19 <http://www.gnu.org/licenses/>.  
20
21 Java and all Java-based marks are trademarks or registered trademarks
22 of Sun Microsystems, Inc. in the United States and other countries.
23 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
24
25 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
26
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30
31 #include "jcf.h"
32 #include "tree.h"
33 #include "java-tree.h"
34 #include "hashtab.h"
35 #include <dirent.h>
36
37 #include "zlib.h"
38
39 int
40 jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
41 {
42   if (jcf->filename)
43     fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
44   else
45     fprintf (stderr, "Premature end of .class file <stdin>.\n");
46   exit (-1);
47 }
48
49 void
50 jcf_trim_old_input (JCF *jcf)
51 {
52   int count = jcf->read_ptr - jcf->buffer;
53   if (count > 0)
54     {
55       memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
56       jcf->read_ptr -= count;
57       jcf->read_end -= count;
58     }
59 }
60
61 int
62 jcf_filbuf_from_stdio (JCF *jcf, int count)
63 {
64   FILE *file = (FILE*) (jcf->read_state);
65   if (count > jcf->buffer_end - jcf->read_ptr)
66     {
67       JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
68       JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
69       JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
70       JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
71       unsigned char *new_buffer
72         = jcf->buffer == NULL ? XNEWVAR (unsigned char, new_size)
73         : XRESIZEVAR (unsigned char, jcf->buffer, new_size);
74       jcf->buffer = new_buffer;
75       jcf->buffer_end = new_buffer + new_size;
76       jcf->read_ptr = new_buffer + old_read_ptr;
77       jcf->read_end = new_buffer + old_read_end;
78     }
79   count -= jcf->read_end - jcf->read_ptr;
80   if (count <= 0)
81     return 0;
82   if ((int) fread (jcf->read_end, 1, count, file) != count)
83     jcf_unexpected_eof (jcf, count);
84   jcf->read_end += count;
85   return 0;
86 }
87
88 #include "zipfile.h"
89
90 struct ZipFile *SeenZipFiles = NULL;
91
92 /* Open a zip file with the given name, and cache directory and file
93    descriptor.  If the file is missing, treat it as an empty archive.
94    Return NULL if the .zip file is malformed.
95 */
96
97 ZipFile *
98 opendir_in_zip (const char *zipfile, int is_system)
99 {
100   struct ZipFile* zipf;
101   char magic [4];
102   int fd;
103   for (zipf = SeenZipFiles;  zipf != NULL;  zipf = zipf->next)
104     {
105       if (strcmp (zipf->name, zipfile) == 0)
106         return zipf;
107     }
108
109   zipf = XNEWVAR (struct ZipFile, sizeof (struct ZipFile) + strlen (zipfile) + 1);
110   zipf->next = SeenZipFiles;
111   zipf->name = (char*)(zipf+1);
112   strcpy (zipf->name, zipfile);
113   fd = open (zipfile, O_RDONLY | O_BINARY);
114   zipf->fd = fd;
115   if (fd < 0)
116     {
117       /* A missing zip file is not considered an error.
118        We may want to re-consider that.  FIXME. */
119       zipf->count = 0;
120       zipf->dir_size = 0;
121       zipf->central_directory = NULL;
122     }
123   else
124     {
125       jcf_dependency_add_file (zipfile, is_system);
126       if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
127         {
128           free (zipf);
129           close (fd);
130           return NULL;
131         }
132       lseek (fd, 0L, SEEK_SET);
133       if (read_zip_archive (zipf) != 0)
134         {
135           free (zipf);
136           close (fd);
137           return NULL;
138         }
139     }
140
141   SeenZipFiles = zipf;  
142   return zipf;
143 }
144
145 /* Returns:
146    0:  OK - zipmember found.
147    -1: Not found.
148    -2: Malformed archive.
149 */
150
151 int
152 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
153              int is_system)
154 {
155   ZipDirectory *zipd;
156   int i, len;
157   ZipFile *zipf = opendir_in_zip (zipfile, is_system);
158
159   if (zipf == NULL)
160     return -2;
161
162   if (!zipmember)
163     return 0;
164
165   len = strlen (zipmember);
166   
167   zipd = (struct ZipDirectory*) zipf->central_directory;
168   for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
169     {
170       if (len == zipd->filename_length &&
171           strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
172         {
173           JCF_ZERO (jcf);
174
175           jcf->filename = xstrdup (zipfile);
176           jcf->classname = xstrdup (zipmember);
177           return read_zip_member(jcf, zipd, zipf);
178         }
179     }
180   return -1;
181 }
182
183 /* Read data from zip archive member. */
184
185 int
186 read_zip_member (JCF *jcf,  ZipDirectory *zipd, ZipFile *zipf)
187 {
188   jcf->filbuf = jcf_unexpected_eof;
189   jcf->zipd = zipd;
190
191   if (zipd->compression_method == Z_NO_COMPRESSION)
192     {
193       jcf->buffer = XNEWVEC (unsigned char, zipd->size);
194       jcf->buffer_end = jcf->buffer + zipd->size;
195       jcf->read_ptr = jcf->buffer;
196       jcf->read_end = jcf->buffer_end;
197       if (lseek (zipf->fd, zipd->filestart, 0) < 0
198           || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
199         return -2;
200     }
201   else
202     {
203       char *buffer;
204       z_stream d_stream; /* decompression stream */
205       d_stream.zalloc = (alloc_func) 0;
206       d_stream.zfree = (free_func) 0;
207       d_stream.opaque = (voidpf) 0;
208
209       jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
210       d_stream.next_out = jcf->buffer;
211       d_stream.avail_out = zipd->uncompressed_size;
212       jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
213       jcf->read_ptr = jcf->buffer;
214       jcf->read_end = jcf->buffer_end;
215       buffer = XNEWVEC (char, zipd->size);
216       d_stream.next_in = (unsigned char *) buffer;
217       d_stream.avail_in = zipd->size;
218       if (lseek (zipf->fd, zipd->filestart, 0) < 0
219           || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
220         return -2;
221       /* Handle NO_HEADER using undocumented zlib feature.
222          This is a very common hack.  */
223       inflateInit2 (&d_stream, -MAX_WBITS);
224       inflate (&d_stream, Z_NO_FLUSH);
225       inflateEnd (&d_stream);
226       free (buffer);
227     }
228
229   return 0;
230 }
231
232 const char *
233 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
234 {
235   if (jcf)
236     {
237       struct stat stat_buf;
238       if (fstat (fd, &stat_buf) != 0
239           || ! S_ISREG (stat_buf.st_mode))
240         {
241           perror ("Could not figure length of .class file");
242           return NULL;
243         }
244       if (dep_name != NULL)
245         jcf_dependency_add_file (dep_name, 0);
246       JCF_ZERO (jcf);
247       jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
248       jcf->buffer_end = jcf->buffer + stat_buf.st_size;
249       jcf->read_ptr = jcf->buffer;
250       jcf->read_end = jcf->buffer_end;
251       jcf->read_state = NULL;
252       jcf->filename = xstrdup (filename);
253       if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
254         {
255           perror ("Failed to read .class file");
256           return NULL;
257         }
258       close (fd);
259       jcf->filbuf = jcf_unexpected_eof;
260     }
261   else
262     close (fd);
263   return filename;
264 }
265
266
267 const char *
268 find_classfile (char *filename, JCF *jcf, const char *dep_name)
269 {
270   int fd = open (filename, O_RDONLY | O_BINARY);
271   if (fd < 0)
272     return NULL;
273   return open_class (filename, jcf, fd, dep_name);
274 }
275
276 /* Returns 1 if the CLASSNAME (really a char *) matches the name
277    stored in TABLE_ENTRY (also a char *).  */
278
279 static int
280 memoized_class_lookup_eq (const void *table_entry, const void *classname)
281 {
282   return strcmp ((const char *)classname, (const char *)table_entry) == 0;
283 }
284
285 /* A hash table keeping track of class names that were not found
286    during class lookup.  (There is no need to cache the values
287    associated with names that were found; they are saved in
288    IDENTIFIER_CLASS_VALUE.)  */
289 static htab_t memoized_class_lookups;
290
291 /* Returns a freshly malloc'd string with the fully qualified pathname
292    of the .class file for the class CLASSNAME.  CLASSNAME must be
293    allocated in permanent storage; this function may retain a pointer
294    to it.  Returns NULL on failure.  If JCF != NULL, it is suitably
295    initialized.  SOURCE_OK is true if we should also look for .java
296    file. */
297
298 const char *
299 find_class (const char *classname, int classname_length, JCF *jcf)
300 {
301   int fd;
302   int i, k, klass = -1;
303   struct stat class_buf;
304   char *dep_file;
305   void *entry;
306   int buflen;
307   char *buffer;
308   hashval_t hash;
309
310   /* Create the hash table, if it does not already exist.  */
311   if (!memoized_class_lookups)
312     memoized_class_lookups = htab_create (37, 
313                                           htab_hash_string, 
314                                           memoized_class_lookup_eq,
315                                           NULL);
316
317   /* Loop for this class in the hashtable.  If it is present, we've
318      already looked for this class and failed to find it.  */
319   hash = htab_hash_string (classname);
320   if (htab_find_with_hash (memoized_class_lookups, classname, hash))
321     return NULL;
322
323   /* Allocate and zero out the buffer, since we don't explicitly put a
324      null pointer when we're copying it below.  */
325   buflen = jcf_path_max_len () + classname_length + 10;
326   buffer = XNEWVAR (char, buflen);
327   memset (buffer, 0, buflen);
328
329   for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
330     {
331       const char *path_name = jcf_path_name (entry);
332       if (klass != 0)
333         {
334           int dir_len;
335
336           strcpy (buffer, path_name);
337           i = strlen (buffer);
338
339           /* This is right because we know that `.zip' entries will have a
340              trailing slash.  See jcf-path.c.  */
341           dir_len = i - 1;
342
343           for (k = 0; k < classname_length; k++, i++)
344             {
345               char ch = classname[k];
346               buffer[i] = ch == '.' ? '/' : ch;
347             }
348           strcpy (buffer+i, ".class");
349
350           if (jcf_path_is_zipfile (entry))
351             {
352               int err_code;
353               JCF _jcf;
354               buffer[dir_len] = '\0';
355               SOURCE_FRONTEND_DEBUG 
356                 (("Trying [...%s]:%s", 
357                   &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)], 
358                   buffer+dir_len+1));
359               if (jcf == NULL)
360                 jcf = &_jcf;
361               err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
362                                       jcf_path_is_system (entry));
363               if (err_code == 0)
364                 {
365                   /* Should we check if .zip is out-of-date wrt .java? */
366                   buffer[dir_len] = '(';
367                   strcpy (buffer+i, ".class)");
368                   if (jcf == &_jcf)
369                     JCF_FINISH (jcf);
370                   return buffer;
371                 }
372               else
373                 continue;
374             }
375           klass = stat (buffer, &class_buf);
376         }
377     }
378
379   dep_file = buffer;
380   if (!klass)
381     {
382       SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
383                               classname+classname_length-
384                               (classname_length <= 30 ? 
385                                classname_length : 30)));
386       fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
387       if (fd >= 0)
388         goto found;
389     }
390
391   free (buffer);
392
393   /* Remember that this class could not be found so that we do not
394      have to look again.  */
395   *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT)
396     = (void *) CONST_CAST (char *, classname);
397
398   return NULL;
399  found:
400   {
401     const char *const tmp = open_class (buffer, jcf, fd, dep_file);
402     jcf->classname = xstrdup (classname);
403     return tmp;
404   }
405 }
406
407 void
408 jcf_print_char (FILE *stream, int ch)
409 {
410   switch (ch)
411     {
412     case '\'':
413     case '\\':
414     case '\"':
415       fprintf (stream, "\\%c", ch);
416       break;
417     case '\n':
418       fprintf (stream, "\\n");
419       break;
420     case '\t':
421       fprintf (stream, "\\t");
422       break;
423     case '\r':
424       fprintf (stream, "\\r");
425       break;
426     default:
427       if (ch >= ' ' && ch < 127)
428         putc (ch, stream);
429       else if (ch < 256)
430         fprintf (stream, "\\%03x", ch);
431       else
432         fprintf (stream, "\\u%04x", ch);
433     }
434 }
435
436 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
437
438 void
439 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
440 {
441   const unsigned char * limit = str + length;
442   while (str < limit)
443     {
444       int ch = UTF8_GET (str, limit);
445       if (ch < 0)
446         {
447           fprintf (stream, "\\<invalid>");
448           return;
449         }
450       jcf_print_char (stream, ch);
451     }
452 }
453
454 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
455
456 void
457 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
458                         int in_char, int out_char)
459 {
460   const unsigned char *limit = str + length;
461   while (str < limit)
462     {
463       int ch = UTF8_GET (str, limit);
464       if (ch < 0)
465         {
466           fprintf (stream, "\\<invalid>");
467           return;
468         }
469       jcf_print_char (stream, ch == in_char ? out_char : ch);
470     }
471 }
472
473 /* Check that all the cross-references in the constant pool are
474    valid.  Returns 0 on success.
475    Otherwise, returns the index of the (first) invalid entry.
476    Only checks internal consistency, but does not check that
477    any classes, fields, or methods are valid.*/
478
479 int
480 verify_constant_pool (JCF *jcf)
481 {
482   int i, n;
483   for (i = 1; i < JPOOL_SIZE (jcf); i++)
484     {
485       switch (JPOOL_TAG (jcf, i))
486         {
487         case CONSTANT_NameAndType:
488           n = JPOOL_USHORT2 (jcf, i);
489           if (n <= 0 || n >= JPOOL_SIZE(jcf)
490               || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
491             return i;
492           /* ... fall through ... */
493         case CONSTANT_Class:
494         case CONSTANT_String:
495           n = JPOOL_USHORT1 (jcf, i);
496           if (n <= 0 || n >= JPOOL_SIZE(jcf)
497               || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
498             return i;
499           break;
500         case CONSTANT_Fieldref:
501         case CONSTANT_Methodref:
502         case CONSTANT_InterfaceMethodref:
503           n = JPOOL_USHORT1 (jcf, i);
504           if (n <= 0 || n >= JPOOL_SIZE(jcf)
505               || JPOOL_TAG (jcf, n) != CONSTANT_Class)
506             return i;
507           n = JPOOL_USHORT2 (jcf, i);
508           if (n <= 0 || n >= JPOOL_SIZE(jcf)
509               || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
510             return i;
511           break;
512         case CONSTANT_Long:
513         case CONSTANT_Double:
514           i++;
515           break;
516         case CONSTANT_Float:
517         case CONSTANT_Integer:
518         case CONSTANT_Utf8:
519         case CONSTANT_Unicode:
520           break;
521         default:
522           return i;
523         }
524     }
525   return 0;
526 }
527
528 void
529 format_uint (char *buffer, uint64 value, int base)
530 {
531 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
532   char buf[WRITE_BUF_SIZE];
533   char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
534   int chars_written;
535   int i;
536
537   /* Now do the actual conversion, placing the result at the *end* of buf. */
538   /* Note this code does not pretend to be optimized. */
539   do {
540     int digit = value % base;
541     static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
542     *--buf_ptr = digit_chars[digit];
543     value /= base;
544   } while (value != 0);
545
546   chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
547   for (i = 0; i < chars_written; i++)
548     buffer[i] = *buf_ptr++;
549   buffer[i] = 0;
550 }
551
552 void
553 format_int (char *buffer, jlong value, int base)
554 {
555   uint64 abs_value;
556   if (value < 0)
557     {
558       abs_value = -(uint64)value;
559       *buffer++ = '-';
560     }
561   else
562     abs_value = (uint64) value;
563   format_uint (buffer, abs_value, base);
564 }