OSDN Git Service

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