OSDN Git Service

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