OSDN Git Service

0c9b07bfc25b7fe06cf59d6272ae5ffe5c70edc5
[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 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 2, 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 COPYING.  If not, write to
19 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA.  
21
22 Java and all Java-based marks are trademarks or registered trademarks
23 of Sun Microsystems, Inc. in the United States and other countries.
24 The Free Software Foundation is independent of Sun Microsystems, Inc.  */
25
26 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
27
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
32
33 #include "jcf.h"
34 #include "tree.h"
35 #include "toplev.h"
36 #include "java-tree.h"
37 #include "hashtab.h"
38 #if JCF_USE_SCANDIR
39 #include <dirent.h>
40 #include <fnmatch.h>
41 #endif
42
43 #include "zlib.h"
44
45 /* DOS brain-damage */
46 #ifndef O_BINARY
47 #define O_BINARY 0 /* MS-DOS brain-damage */
48 #endif
49
50 int
51 jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
52 {
53   if (jcf->filename)
54     fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
55   else
56     fprintf (stderr, "Premature end of .class file <stdin>.\n");
57   exit (-1);
58 }
59
60 void
61 jcf_trim_old_input (JCF *jcf)
62 {
63   int count = jcf->read_ptr - jcf->buffer;
64   if (count > 0)
65     {
66       memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
67       jcf->read_ptr -= count;
68       jcf->read_end -= count;
69     }
70 }
71
72 int
73 jcf_filbuf_from_stdio (JCF *jcf, int count)
74 {
75   FILE *file = (FILE*) (jcf->read_state);
76   if (count > jcf->buffer_end - jcf->read_ptr)
77     {
78       JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
79       JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
80       JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
81       JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
82       unsigned char *new_buffer = jcf->buffer == NULL ? ALLOC (new_size)
83         : REALLOC (jcf->buffer, new_size);
84       jcf->buffer = new_buffer;
85       jcf->buffer_end = new_buffer + new_size;
86       jcf->read_ptr = new_buffer + old_read_ptr;
87       jcf->read_end = new_buffer + old_read_end;
88     }
89   count -= jcf->read_end - jcf->read_ptr;
90   if (count <= 0)
91     return 0;
92   if ((int) fread (jcf->read_end, 1, count, file) != count)
93     jcf_unexpected_eof (jcf, count);
94   jcf->read_end += count;
95   return 0;
96 }
97
98 #include "zipfile.h"
99
100 struct ZipFile *SeenZipFiles = NULL;
101
102 /* Open a zip file with the given name, and cache directory and file
103    descriptor.  If the file is missing, treat it as an empty archive.
104    Return NULL if the .zip file is malformed.
105 */
106
107 ZipFile *
108 opendir_in_zip (const char *zipfile, int is_system)
109 {
110   struct ZipFile* zipf;
111   char magic [4];
112   int fd;
113   for (zipf = SeenZipFiles;  zipf != NULL;  zipf = zipf->next)
114     {
115       if (strcmp (zipf->name, zipfile) == 0)
116         return zipf;
117     }
118
119   zipf = ALLOC (sizeof (struct ZipFile) + strlen (zipfile) + 1);
120   zipf->next = SeenZipFiles;
121   zipf->name = (char*)(zipf+1);
122   strcpy (zipf->name, zipfile);
123   fd = open (zipfile, O_RDONLY | O_BINARY);
124   zipf->fd = fd;
125   if (fd < 0)
126     {
127       /* A missing zip file is not considered an error.
128        We may want to re-consider that.  FIXME. */
129       zipf->count = 0;
130       zipf->dir_size = 0;
131       zipf->central_directory = NULL;
132     }
133   else
134     {
135       jcf_dependency_add_file (zipfile, is_system);
136       if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
137         {
138           free (zipf);
139           close (fd);
140           return NULL;
141         }
142       lseek (fd, 0L, SEEK_SET);
143       if (read_zip_archive (zipf) != 0)
144         {
145           free (zipf);
146           close (fd);
147           return NULL;
148         }
149     }
150
151   SeenZipFiles = zipf;  
152   return zipf;
153 }
154
155 /* Returns:
156    0:  OK - zipmember found.
157    -1: Not found.
158    -2: Malformed archive.
159 */
160
161 int
162 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
163              int is_system)
164 {
165   ZipDirectory *zipd;
166   int i, len;
167   ZipFile *zipf = opendir_in_zip (zipfile, is_system);
168
169   if (zipf == NULL)
170     return -2;
171
172   if (!zipmember)
173     return 0;
174
175   len = strlen (zipmember);
176   
177   zipd = (struct ZipDirectory*) zipf->central_directory;
178   for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
179     {
180       if (len == zipd->filename_length &&
181           strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
182         {
183           JCF_ZERO (jcf);
184
185           jcf->filename = xstrdup (zipfile);
186           jcf->classname = xstrdup (zipmember);
187           return read_zip_member(jcf, zipd, zipf);
188         }
189     }
190   return -1;
191 }
192
193 /* Read data from zip archive member. */
194
195 int
196 read_zip_member (JCF *jcf,  ZipDirectory *zipd, ZipFile *zipf)
197 {
198   jcf->filbuf = jcf_unexpected_eof;
199   jcf->zipd = zipd;
200
201   if (zipd->compression_method == Z_NO_COMPRESSION)
202     {
203       jcf->buffer = XNEWVEC (unsigned char, zipd->size);
204       jcf->buffer_end = jcf->buffer + zipd->size;
205       jcf->read_ptr = jcf->buffer;
206       jcf->read_end = jcf->buffer_end;
207       if (lseek (zipf->fd, zipd->filestart, 0) < 0
208           || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
209         return -2;
210     }
211   else
212     {
213       char *buffer;
214       z_stream d_stream; /* decompression stream */
215       d_stream.zalloc = (alloc_func) 0;
216       d_stream.zfree = (free_func) 0;
217       d_stream.opaque = (voidpf) 0;
218
219       jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
220       d_stream.next_out = jcf->buffer;
221       d_stream.avail_out = zipd->uncompressed_size;
222       jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
223       jcf->read_ptr = jcf->buffer;
224       jcf->read_end = jcf->buffer_end;
225       buffer = XNEWVEC (char, zipd->size);
226       d_stream.next_in = (unsigned char *) buffer;
227       d_stream.avail_in = zipd->size;
228       if (lseek (zipf->fd, zipd->filestart, 0) < 0
229           || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
230         return -2;
231       /* Handle NO_HEADER using undocumented zlib feature.
232          This is a very common hack.  */
233       inflateInit2 (&d_stream, -MAX_WBITS);
234       inflate (&d_stream, Z_NO_FLUSH);
235       inflateEnd (&d_stream);
236       free (buffer);
237     }
238
239   return 0;
240 }
241
242 const char *
243 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
244 {
245   if (jcf)
246     {
247       struct stat stat_buf;
248       if (fstat (fd, &stat_buf) != 0
249           || ! S_ISREG (stat_buf.st_mode))
250         {
251           perror ("Could not figure length of .class file");
252           return NULL;
253         }
254       if (dep_name != NULL)
255         jcf_dependency_add_file (dep_name, 0);
256       JCF_ZERO (jcf);
257       jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
258       jcf->buffer_end = jcf->buffer + stat_buf.st_size;
259       jcf->read_ptr = jcf->buffer;
260       jcf->read_end = jcf->buffer_end;
261       jcf->read_state = NULL;
262       jcf->filename = filename;
263       if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
264         {
265           perror ("Failed to read .class file");
266           return NULL;
267         }
268       close (fd);
269       jcf->filbuf = jcf_unexpected_eof;
270     }
271   else
272     close (fd);
273   return filename;
274 }
275
276
277 const char *
278 find_classfile (char *filename, JCF *jcf, const char *dep_name)
279 {
280   int fd = open (filename, O_RDONLY | O_BINARY);
281   if (fd < 0)
282     return NULL;
283   return open_class (filename, jcf, fd, dep_name);
284 }
285
286 #if JCF_USE_SCANDIR
287
288 /* A comparison function (as for qsort) that compares KEY (a char *
289    giving the basename of a file) with the name stored in ENTRY (a
290    dirent **).  */
291
292 static int
293 compare_path (const void *key, const void *entry)
294 {
295   return strcmp ((const char *) key, 
296                  (*((const struct dirent **) entry))->d_name);
297 }
298
299 /* Returns nonzero if ENTRY names a .java or .class file.  */
300
301 static int
302 java_or_class_file (const struct dirent *entry)
303 {
304   const char *base = lbasename (entry->d_name);
305   return (fnmatch ("*.java", base, 0) == 0 || 
306           fnmatch ("*.class", base, 0) == 0);
307 }
308
309 /* Information about the files present in a particular directory.  */
310 typedef struct memoized_dirlist_entry 
311 {
312   /* The name of the directory.  */
313   const char *dir;
314   /* The number of .java and .class files present, or -1 if we could
315      not, for some reason, obtain the list.  */
316   int num_files;
317   /* The .java and .class files in the directory, in alphabetical
318      order.  */
319   struct dirent **files;
320 } memoized_dirlist_entry;
321
322 /* A hash function for a memoized_dirlist_entry.  */
323 static hashval_t
324 memoized_dirlist_hash (const void *entry)
325 {
326   const memoized_dirlist_entry *mde = (const memoized_dirlist_entry *) entry;
327   return htab_hash_string (mde->dir);
328 }
329
330 /* Returns true if ENTRY (a memoized_dirlist_entry *) corresponds to
331    the directory given by KEY (a char *) giving the directory 
332    name.  */
333
334 static int
335 memoized_dirlist_lookup_eq (const void *entry, const void *key)
336 {
337   return strcmp ((const char *) key,
338                  ((const memoized_dirlist_entry *) entry)->dir) == 0;
339 }
340
341 /* A hash table mapping directory names to the lists of .java and
342    .class files in that directory.  */
343
344 static htab_t memoized_dirlists;
345
346 #endif
347
348 /* Like stat, but avoids actually making the stat system call if we
349    know that it cannot succeed.  FILENAME and BUF are as for stat.  */
350
351 static int
352 caching_stat (char *filename, struct stat *buf)
353 {
354 #if JCF_USE_SCANDIR
355   char *sep;
356   char origsep = 0;
357   char *base;
358   memoized_dirlist_entry *dent;
359   void **slot;
360   struct memoized_dirlist_entry temp;
361   
362   /* If the hashtable has not already been created, create it now.  */
363   if (!memoized_dirlists)
364     memoized_dirlists = htab_create (37,
365                                      memoized_dirlist_hash,
366                                      memoized_dirlist_lookup_eq,
367                                      NULL);
368
369   /* Get the name of the directory.  */
370   sep = strrchr (filename, DIR_SEPARATOR);
371 #ifdef DIR_SEPARATOR_2
372   if (! sep)
373     sep = strrchr (filename, DIR_SEPARATOR_2);
374 #endif
375   if (sep)
376     {
377       origsep = *sep;
378       *sep = '\0';
379       base = sep + 1;
380     }
381   else
382     base = filename;
383
384   /* Obtain the entry for this directory from the hash table.  This
385      approach is ok since we know that the hash function only looks at
386      the directory name.  */
387   temp.dir = filename;
388   temp.num_files = 0;
389   temp.files = NULL;
390   slot = htab_find_slot (memoized_dirlists, &temp, INSERT);
391   if (!*slot)
392     {
393       /* We have not already scanned this directory; scan it now.  */
394       dent = XNEW (memoized_dirlist_entry);
395       dent->dir = xstrdup (filename);
396       /* Unfortunately, scandir is not fully standardized.  In
397          particular, the type of the function pointer passed as the
398          third argument sometimes takes a "const struct dirent *"
399          parameter, and sometimes just a "struct dirent *".  We cast
400          to (void *) and use __extension__ so that either way it is
401          quietly accepted.  FIXME: scandir is not in POSIX.  */
402       dent->num_files = __extension__ scandir (filename, &dent->files, 
403                                                (void *) java_or_class_file, 
404                                                alphasort);
405       *slot = dent;
406     }
407   else
408     dent = *((memoized_dirlist_entry **) slot);
409
410   /* Put the separator back.  */
411   if (sep)
412     *sep = origsep;
413
414   /* If the file is not in the list, there is no need to stat it; it
415      does not exist.  */
416   if (dent->num_files != -1
417       && !bsearch (base, dent->files, dent->num_files,
418                    sizeof (struct dirent *), compare_path))
419     return -1;
420 #endif
421   
422   return stat (filename, buf);
423 }
424
425 /* Returns 1 if the CLASSNAME (really a char *) matches the name
426    stored in TABLE_ENTRY (also a char *).  */
427
428 static int
429 memoized_class_lookup_eq (const void *table_entry, const void *classname)
430 {
431   return strcmp ((const char *)classname, (const char *)table_entry) == 0;
432 }
433
434 /* A hash table keeping track of class names that were not found
435    during class lookup.  (There is no need to cache the values
436    associated with names that were found; they are saved in
437    IDENTIFIER_CLASS_VALUE.)  */
438 static htab_t memoized_class_lookups;
439
440 /* Returns a freshly malloc'd string with the fully qualified pathname
441    of the .class file for the class CLASSNAME.  CLASSNAME must be
442    allocated in permanent storage; this function may retain a pointer
443    to it.  Returns NULL on failure.  If JCF != NULL, it is suitably
444    initialized.  SOURCE_OK is true if we should also look for .java
445    file. */
446
447 const char *
448 find_class (const char *classname, int classname_length, JCF *jcf)
449 {
450   int fd;
451   int i, k, class = -1;
452   struct stat class_buf;
453   char *dep_file;
454   void *entry;
455   int buflen;
456   char *buffer;
457   hashval_t hash;
458
459   /* Create the hash table, if it does not already exist.  */
460   if (!memoized_class_lookups)
461     memoized_class_lookups = htab_create (37, 
462                                           htab_hash_string, 
463                                           memoized_class_lookup_eq,
464                                           NULL);
465
466   /* Loop for this class in the hashtable.  If it is present, we've
467      already looked for this class and failed to find it.  */
468   hash = htab_hash_string (classname);
469   if (htab_find_with_hash (memoized_class_lookups, classname, hash))
470     return NULL;
471
472   /* Allocate and zero out the buffer, since we don't explicitly put a
473      null pointer when we're copying it below.  */
474   buflen = jcf_path_max_len () + classname_length + 10;
475   buffer = ALLOC (buflen);
476   memset (buffer, 0, buflen);
477
478   for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
479     {
480       const char *path_name = jcf_path_name (entry);
481       if (class != 0)
482         {
483           int dir_len;
484
485           strcpy (buffer, path_name);
486           i = strlen (buffer);
487
488           /* This is right because we know that `.zip' entries will have a
489              trailing slash.  See jcf-path.c.  */
490           dir_len = i - 1;
491
492           for (k = 0; k < classname_length; k++, i++)
493             {
494               char ch = classname[k];
495               buffer[i] = ch == '.' ? '/' : ch;
496             }
497           strcpy (buffer+i, ".class");
498
499           if (jcf_path_is_zipfile (entry))
500             {
501               int err_code;
502               JCF _jcf;
503               buffer[dir_len] = '\0';
504               SOURCE_FRONTEND_DEBUG 
505                 (("Trying [...%s]:%s", 
506                   &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)], 
507                   buffer+dir_len+1));
508               if (jcf == NULL)
509                 jcf = &_jcf;
510               err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
511                                       jcf_path_is_system (entry));
512               if (err_code == 0)
513                 {
514                   /* Should we check if .zip is out-of-date wrt .java? */
515                   buffer[dir_len] = '(';
516                   strcpy (buffer+i, ".class)");
517                   if (jcf == &_jcf)
518                     JCF_FINISH (jcf);
519                   return buffer;
520                 }
521               else
522                 continue;
523             }
524           class = caching_stat(buffer, &class_buf);
525         }
526     }
527
528   dep_file = buffer;
529   if (!class)
530     {
531       SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
532                               classname+classname_length-
533                               (classname_length <= 30 ? 
534                                classname_length : 30)));
535       fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
536       if (fd >= 0)
537         goto found;
538     }
539
540   free (buffer);
541
542   /* Remember that this class could not be found so that we do not
543      have to look again.  */
544   *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT) 
545     = (void *) classname;
546
547   return NULL;
548  found:
549   buffer = (char *) open_class (buffer, jcf, fd, dep_file);
550   jcf->classname = xstrdup (classname);
551   return buffer;
552 }
553
554 void
555 jcf_print_char (FILE *stream, int ch)
556 {
557   switch (ch)
558     {
559     case '\'':
560     case '\\':
561     case '\"':
562       fprintf (stream, "\\%c", ch);
563       break;
564     case '\n':
565       fprintf (stream, "\\n");
566       break;
567     case '\t':
568       fprintf (stream, "\\t");
569       break;
570     case '\r':
571       fprintf (stream, "\\r");
572       break;
573     default:
574       if (ch >= ' ' && ch < 127)
575         putc (ch, stream);
576       else if (ch < 256)
577         fprintf (stream, "\\%03x", ch);
578       else
579         fprintf (stream, "\\u%04x", ch);
580     }
581 }
582
583 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
584
585 void
586 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
587 {
588   const unsigned char * limit = str + length;
589   while (str < limit)
590     {
591       int ch = UTF8_GET (str, limit);
592       if (ch < 0)
593         {
594           fprintf (stream, "\\<invalid>");
595           return;
596         }
597       jcf_print_char (stream, ch);
598     }
599 }
600
601 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
602
603 void
604 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
605                         int in_char, int out_char)
606 {
607   const unsigned char *limit = str + length;
608   while (str < limit)
609     {
610       int ch = UTF8_GET (str, limit);
611       if (ch < 0)
612         {
613           fprintf (stream, "\\<invalid>");
614           return;
615         }
616       jcf_print_char (stream, ch == in_char ? out_char : ch);
617     }
618 }
619
620 /* Check that all the cross-references in the constant pool are
621    valid.  Returns 0 on success.
622    Otherwise, returns the index of the (first) invalid entry.
623    Only checks internal consistency, but does not check that
624    any classes, fields, or methods are valid.*/
625
626 int
627 verify_constant_pool (JCF *jcf)
628 {
629   int i, n;
630   for (i = 1; i < JPOOL_SIZE (jcf); i++)
631     {
632       switch (JPOOL_TAG (jcf, i))
633         {
634         case CONSTANT_NameAndType:
635           n = JPOOL_USHORT2 (jcf, i);
636           if (n <= 0 || n >= JPOOL_SIZE(jcf)
637               || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
638             return i;
639           /* ... fall through ... */
640         case CONSTANT_Class:
641         case CONSTANT_String:
642           n = JPOOL_USHORT1 (jcf, i);
643           if (n <= 0 || n >= JPOOL_SIZE(jcf)
644               || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
645             return i;
646           break;
647         case CONSTANT_Fieldref:
648         case CONSTANT_Methodref:
649         case CONSTANT_InterfaceMethodref:
650           n = JPOOL_USHORT1 (jcf, i);
651           if (n <= 0 || n >= JPOOL_SIZE(jcf)
652               || JPOOL_TAG (jcf, n) != CONSTANT_Class)
653             return i;
654           n = JPOOL_USHORT2 (jcf, i);
655           if (n <= 0 || n >= JPOOL_SIZE(jcf)
656               || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
657             return i;
658           break;
659         case CONSTANT_Long:
660         case CONSTANT_Double:
661           i++;
662           break;
663         case CONSTANT_Float:
664         case CONSTANT_Integer:
665         case CONSTANT_Utf8:
666         case CONSTANT_Unicode:
667           break;
668         default:
669           return i;
670         }
671     }
672   return 0;
673 }
674
675 void
676 format_uint (char *buffer, uint64 value, int base)
677 {
678 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
679   char buf[WRITE_BUF_SIZE];
680   char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
681   int chars_written;
682   int i;
683
684   /* Now do the actual conversion, placing the result at the *end* of buf. */
685   /* Note this code does not pretend to be optimized. */
686   do {
687     int digit = value % base;
688     static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
689     *--buf_ptr = digit_chars[digit];
690     value /= base;
691   } while (value != 0);
692
693   chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
694   for (i = 0; i < chars_written; i++)
695     buffer[i] = *buf_ptr++;
696   buffer[i] = 0;
697 }
698
699 void
700 format_int (char *buffer, jlong value, int base)
701 {
702   uint64 abs_value;
703   if (value < 0)
704     {
705       abs_value = -(uint64)value;
706       *buffer++ = '-';
707     }
708   else
709     abs_value = (uint64) value;
710   format_uint (buffer, abs_value, base);
711 }