1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003
3 Free Software Foundation, Inc.
5 This file is part of GCC.
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)
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.
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, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
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. */
26 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
30 #include "coretypes.h"
36 #include "java-tree.h"
45 /* DOS brain-damage */
47 #define O_BINARY 0 /* MS-DOS brain-damage */
51 jcf_unexpected_eof (JCF
*jcf
, int count ATTRIBUTE_UNUSED
)
54 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
56 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
61 jcf_trim_old_input (JCF
*jcf
)
63 int count
= jcf
->read_ptr
- jcf
->buffer
;
66 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
67 jcf
->read_ptr
-= count
;
68 jcf
->read_end
-= count
;
73 jcf_filbuf_from_stdio (JCF
*jcf
, int count
)
75 FILE *file
= (FILE*) (jcf
->read_state
);
76 if (count
> jcf
->buffer_end
- jcf
->read_ptr
)
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
;
89 count
-= jcf
->read_end
- jcf
->read_ptr
;
92 if ((int) fread (jcf
->read_end
, 1, count
, file
) != count
)
93 jcf_unexpected_eof (jcf
, count
);
94 jcf
->read_end
+= count
;
100 struct ZipFile
*SeenZipFiles
= NULL
;
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.
108 opendir_in_zip (const char *zipfile
, int is_system
)
110 struct ZipFile
* zipf
;
113 for (zipf
= SeenZipFiles
; zipf
!= NULL
; zipf
= zipf
->next
)
115 if (strcmp (zipf
->name
, zipfile
) == 0)
119 zipf
= ALLOC (sizeof (struct ZipFile
) + strlen (zipfile
) + 1);
120 zipf
->next
= SeenZipFiles
;
121 zipf
->name
= (char*)(zipf
+1);
122 strcpy (zipf
->name
, zipfile
);
124 fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
128 /* A missing zip file is not considered an error.
129 We may want to re-consider that. FIXME. */
132 zipf
->central_directory
= NULL
;
136 jcf_dependency_add_file (zipfile
, is_system
);
137 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
139 lseek (fd
, 0L, SEEK_SET
);
140 if (read_zip_archive (zipf
) != 0)
147 0: OK - zipmember found.
149 -2: Malformed archive.
153 open_in_zip (JCF
*jcf
, const char *zipfile
, const char *zipmember
,
158 ZipFile
*zipf
= opendir_in_zip (zipfile
, is_system
);
166 len
= strlen (zipmember
);
168 zipd
= (struct ZipDirectory
*) zipf
->central_directory
;
169 for (i
= 0; i
< zipf
->count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
171 if (len
== zipd
->filename_length
&&
172 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
176 jcf
->filename
= xstrdup (zipfile
);
177 jcf
->classname
= xstrdup (zipmember
);
178 return read_zip_member(jcf
, zipd
, zipf
);
184 /* Read data from zip archive member. */
187 read_zip_member (JCF
*jcf
, ZipDirectory
*zipd
, ZipFile
*zipf
)
189 jcf
->filbuf
= jcf_unexpected_eof
;
190 jcf
->zipd
= (void *)zipd
;
192 if (zipd
->compression_method
== Z_NO_COMPRESSION
)
194 jcf
->buffer
= ALLOC (zipd
->size
);
195 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
196 jcf
->read_ptr
= jcf
->buffer
;
197 jcf
->read_end
= jcf
->buffer_end
;
198 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
199 || read (zipf
->fd
, jcf
->buffer
, zipd
->size
) != (long) zipd
->size
)
205 z_stream d_stream
; /* decompression stream */
206 d_stream
.zalloc
= (alloc_func
) 0;
207 d_stream
.zfree
= (free_func
) 0;
208 d_stream
.opaque
= (voidpf
) 0;
210 jcf
->buffer
= ALLOC (zipd
->uncompressed_size
);
211 d_stream
.next_out
= jcf
->buffer
;
212 d_stream
.avail_out
= zipd
->uncompressed_size
;
213 jcf
->buffer_end
= jcf
->buffer
+ zipd
->uncompressed_size
;
214 jcf
->read_ptr
= jcf
->buffer
;
215 jcf
->read_end
= jcf
->buffer_end
;
216 buffer
= ALLOC (zipd
->size
);
217 d_stream
.next_in
= buffer
;
218 d_stream
.avail_in
= zipd
->size
;
219 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
220 || read (zipf
->fd
, buffer
, zipd
->size
) != (long) zipd
->size
)
222 /* Handle NO_HEADER using undocumented zlib feature.
223 This is a very common hack. */
224 inflateInit2 (&d_stream
, -MAX_WBITS
);
225 inflate (&d_stream
, Z_NO_FLUSH
);
226 inflateEnd (&d_stream
);
234 open_class (const char *filename
, JCF
*jcf
, int fd
, const char *dep_name
)
238 struct stat stat_buf
;
239 if (fstat (fd
, &stat_buf
) != 0
240 || ! S_ISREG (stat_buf
.st_mode
))
242 perror ("Could not figure length of .class file");
245 if (dep_name
!= NULL
)
246 jcf_dependency_add_file (dep_name
, 0);
248 jcf
->buffer
= ALLOC (stat_buf
.st_size
);
249 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
250 jcf
->read_ptr
= jcf
->buffer
;
251 jcf
->read_end
= jcf
->buffer_end
;
252 jcf
->read_state
= NULL
;
253 jcf
->filename
= filename
;
254 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
256 perror ("Failed to read .class file");
260 jcf
->filbuf
= jcf_unexpected_eof
;
269 find_classfile (char *filename
, JCF
*jcf
, const char *dep_name
)
271 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
274 return open_class (filename
, jcf
, fd
, dep_name
);
279 /* A comparison function (as for qsort) that compares KEY (a char *
280 giving the basename of a file) with the name stored in ENTRY (a
284 compare_path (const void *key
, const void *entry
)
286 return strcmp ((const char *) key
,
287 (*((const struct dirent
**) entry
))->d_name
);
290 /* Returns nonzero if ENTRY names a .java or .class file. */
293 java_or_class_file (const struct dirent
*entry
)
295 const char *base
= lbasename (entry
->d_name
);
296 return (fnmatch ("*.java", base
, 0) == 0 ||
297 fnmatch ("*.class", base
, 0) == 0);
300 /* Information about the files present in a particular directory. */
301 typedef struct memoized_dirlist_entry
303 /* The name of the directory. */
305 /* The number of .java and .class files present, or -1 if we could
306 not, for some reason, obtain the list. */
308 /* The .java and .class files in the directory, in alphabetical
310 struct dirent
**files
;
311 } memoized_dirlist_entry
;
313 /* Returns true if ENTRY (a memoized_dirlist_entry *) corresponds to
314 the directory given by KEY (a char *) giving the directory
318 memoized_dirlist_lookup_eq (const void *entry
, const void *key
)
320 return strcmp ((const char *) key
,
321 ((const memoized_dirlist_entry
*) entry
)->dir
) == 0;
324 /* A hash table mapping directory names to the lists of .java and
325 .class files in that directory. */
327 static htab_t memoized_dirlists
;
331 /* Like stat, but avoids actually making the stat system call if we
332 know that it cannot succeed. FILENAME and BUF are as for stat. */
335 caching_stat (char *filename
, struct stat
*buf
)
341 memoized_dirlist_entry
*dent
;
344 /* If the hashtable has not already been created, create it now. */
345 if (!memoized_dirlists
)
346 memoized_dirlists
= htab_create (37,
348 memoized_dirlist_lookup_eq
,
351 /* Get the name of the directory. */
352 sep
= strrchr (filename
, DIR_SEPARATOR
);
353 #ifdef DIR_SEPARATOR_2
355 sep
= strrchr (filename
, DIR_SEPARATOR_2
);
366 /* Obtain the entry for this directory from the hash table. */
367 slot
= htab_find_slot (memoized_dirlists
, filename
, INSERT
);
370 /* We have not already scanned this directory; scan it now. */
371 dent
= ((memoized_dirlist_entry
*)
372 ALLOC (sizeof (memoized_dirlist_entry
)));
373 dent
->dir
= xstrdup (filename
);
374 /* Unfortunately, scandir is not fully standardized. In
375 particular, the type of the function pointer passed as the
376 third argument sometimes takes a "const struct dirent *"
377 parameter, and sometimes just a "struct dirent *". We cast
378 to (void *) so that either way it is quietly accepted. */
379 dent
->num_files
= scandir (filename
, &dent
->files
,
380 (void *) java_or_class_file
,
385 dent
= *((memoized_dirlist_entry
**) slot
);
387 /* Put the separator back. */
391 /* If the file is not in the list, there is no need to stat it; it
393 if (dent
->num_files
!= -1
394 && !bsearch (base
, dent
->files
, dent
->num_files
,
395 sizeof (struct dirent
*), compare_path
))
399 return stat (filename
, buf
);
402 /* Returns 1 if the CLASSNAME (really a char *) matches the name
403 stored in TABLE_ENTRY (also a char *). */
406 memoized_class_lookup_eq (const void *table_entry
, const void *classname
)
408 return strcmp ((const char *)classname
, (const char *)table_entry
) == 0;
411 /* A hash table keeping track of class names that were not found
412 during class lookup. (There is no need to cache the values
413 associated with names that were found; they are saved in
414 IDENTIFIER_CLASS_VALUE.) */
415 static htab_t memoized_class_lookups
;
417 /* Returns a freshly malloc'd string with the fully qualified pathname
418 of the .class file for the class CLASSNAME. CLASSNAME must be
419 allocated in permanent storage; this function may retain a pointer
420 to it. Returns NULL on failure. If JCF != NULL, it is suitably
421 initialized. SOURCE_OK is true if we should also look for .java
425 find_class (const char *classname
, int classname_length
, JCF
*jcf
,
429 int i
, k
, java
= -1, class = -1;
430 struct stat java_buf
, class_buf
;
438 /* Create the hash table, if it does not already exist. */
439 if (!memoized_class_lookups
)
440 memoized_class_lookups
= htab_create (37,
442 memoized_class_lookup_eq
,
445 /* Loop for this class in the hashtable. If it is present, we've
446 already looked for this class and failed to find it. */
447 hash
= htab_hash_string (classname
);
448 if (htab_find_with_hash (memoized_class_lookups
, classname
, hash
))
451 /* Allocate and zero out the buffer, since we don't explicitly put a
452 null pointer when we're copying it below. */
453 buflen
= jcf_path_max_len () + classname_length
+ 10;
454 buffer
= ALLOC (buflen
);
455 memset (buffer
, 0, buflen
);
457 java_buffer
= alloca (buflen
);
459 jcf
->java_source
= 0;
461 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
463 const char *path_name
= jcf_path_name (entry
);
468 strcpy (buffer
, path_name
);
471 /* This is right because we know that `.zip' entries will have a
472 trailing slash. See jcf-path.c. */
475 for (k
= 0; k
< classname_length
; k
++, i
++)
477 char ch
= classname
[k
];
478 buffer
[i
] = ch
== '.' ? '/' : ch
;
480 strcpy (buffer
+i
, ".class");
482 if (jcf_path_is_zipfile (entry
))
486 buffer
[dir_len
] = '\0';
487 SOURCE_FRONTEND_DEBUG
488 (("Trying [...%s]:%s",
489 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
493 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
494 jcf_path_is_system (entry
));
497 /* Should we check if .zip is out-of-date wrt .java? */
498 buffer
[dir_len
] = '(';
499 strcpy (buffer
+i
, ".class)");
507 class = caching_stat(buffer
, &class_buf
);
512 /* Compute name of .java file. */
514 strcpy (java_buffer
, path_name
);
515 l
= strlen (java_buffer
);
516 for (m
= 0; m
< classname_length
; ++m
)
517 java_buffer
[m
+ l
] = (classname
[m
] == '.'
518 ? DIR_SEPARATOR
: classname
[m
]);
519 strcpy (java_buffer
+ m
+ l
, ".java");
520 java
= caching_stat (java_buffer
, &java_buf
);
526 /* We preferably pick a class file if we have a chance. If the source
527 file is newer than the class file, we issue a warning and parse the
529 There should be a flag to allow people have the class file picked
530 up no matter what. FIXME. */
531 if (! java
&& ! class && java_buf
.st_mtime
> class_buf
.st_mtime
)
534 warning ("source file for class `%s' is newer than its matching class file. Source file `%s' used instead", classname
, java_buffer
);
539 dep_file
= java_buffer
;
544 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
545 classname
+classname_length
-
546 (classname_length
<= 30 ?
547 classname_length
: 30)));
548 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
| O_BINARY
);
552 /* Give .java a try, if necessary */
555 strcpy (buffer
, java_buffer
);
556 SOURCE_FRONTEND_DEBUG ((stderr
, "[Source selected: %s]\n",
557 classname
+classname_length
-
558 (classname_length
<= 30 ?
559 classname_length
: 30)));
560 fd
= JCF_OPEN_EXACT_CASE (buffer
, O_RDONLY
);
563 jcf
->java_source
= 1;
570 /* Remember that this class could not be found so that we do not
571 have to look again. */
572 *htab_find_slot_with_hash (memoized_class_lookups
, classname
, hash
, INSERT
)
573 = (void *) classname
;
577 if (jcf
->java_source
)
579 JCF_ZERO (jcf
); /* JCF_FINISH relies on this */
580 jcf
->java_source
= 1;
581 jcf
->filename
= xstrdup (buffer
);
582 close (fd
); /* We use STDIO for source file */
585 buffer
= (char *) open_class (buffer
, jcf
, fd
, dep_file
);
586 jcf
->classname
= xstrdup (classname
);
591 jcf_print_char (FILE *stream
, int ch
)
598 fprintf (stream
, "\\%c", ch
);
601 fprintf (stream
, "\\n");
604 fprintf (stream
, "\\t");
607 fprintf (stream
, "\\r");
610 if (ch
>= ' ' && ch
< 127)
613 fprintf (stream
, "\\%03x", ch
);
615 fprintf (stream
, "\\u%04x", ch
);
619 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
622 jcf_print_utf8 (FILE *stream
, const unsigned char *str
, int length
)
624 const unsigned char * limit
= str
+ length
;
627 int ch
= UTF8_GET (str
, limit
);
630 fprintf (stream
, "\\<invalid>");
633 jcf_print_char (stream
, ch
);
637 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
640 jcf_print_utf8_replace (FILE *stream
, const unsigned char *str
, int length
,
641 int in_char
, int out_char
)
643 const unsigned char *limit
= str
+ length
;
646 int ch
= UTF8_GET (str
, limit
);
649 fprintf (stream
, "\\<invalid>");
652 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
656 /* Check that all the cross-references in the constant pool are
657 valid. Returns 0 on success.
658 Otherwise, returns the index of the (first) invalid entry.
659 Only checks internal consistency, but does not check that
660 any classes, fields, or methods are valid.*/
663 verify_constant_pool (JCF
*jcf
)
666 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
668 switch (JPOOL_TAG (jcf
, i
))
670 case CONSTANT_NameAndType
:
671 n
= JPOOL_USHORT2 (jcf
, i
);
672 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
673 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
675 /* ... fall through ... */
677 case CONSTANT_String
:
678 n
= JPOOL_USHORT1 (jcf
, i
);
679 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
680 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
683 case CONSTANT_Fieldref
:
684 case CONSTANT_Methodref
:
685 case CONSTANT_InterfaceMethodref
:
686 n
= JPOOL_USHORT1 (jcf
, i
);
687 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
688 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
690 n
= JPOOL_USHORT2 (jcf
, i
);
691 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
692 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
696 case CONSTANT_Double
:
700 case CONSTANT_Integer
:
702 case CONSTANT_Unicode
:
712 format_uint (char *buffer
, uint64 value
, int base
)
714 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
715 char buf
[WRITE_BUF_SIZE
];
716 char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
720 /* Now do the actual conversion, placing the result at the *end* of buf. */
721 /* Note this code does not pretend to be optimized. */
723 int digit
= value
% base
;
724 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
725 *--buf_ptr
= digit_chars
[digit
];
727 } while (value
!= 0);
729 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
730 for (i
= 0; i
< chars_written
; i
++)
731 buffer
[i
] = *buf_ptr
++;
736 format_int (char *buffer
, jlong value
, int base
)
741 abs_value
= -(uint64
)value
;
745 abs_value
= (uint64
) value
;
746 format_uint (buffer
, abs_value
, base
);