2007-03-01 Paul Brook <paul@codesourcery.com>
[official-gcc.git] / gcc / java / jcf-io.c
blob0c9b07bfc25b7fe06cf59d6272ae5ffe5c70edc5
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.
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)
10 any later version.
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, 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, 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. */
28 #include "config.h"
29 #include "system.h"
30 #include "coretypes.h"
31 #include "tm.h"
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
43 #include "zlib.h"
45 /* DOS brain-damage */
46 #ifndef O_BINARY
47 #define O_BINARY 0 /* MS-DOS brain-damage */
48 #endif
50 int
51 jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
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);
60 void
61 jcf_trim_old_input (JCF *jcf)
63 int count = jcf->read_ptr - jcf->buffer;
64 if (count > 0)
66 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
67 jcf->read_ptr -= count;
68 jcf->read_end -= count;
72 int
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;
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;
98 #include "zipfile.h"
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.
107 ZipFile *
108 opendir_in_zip (const char *zipfile, int is_system)
110 struct ZipFile* zipf;
111 char magic [4];
112 int fd;
113 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
115 if (strcmp (zipf->name, zipfile) == 0)
116 return zipf;
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)
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;
133 else
135 jcf_dependency_add_file (zipfile, is_system);
136 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
138 free (zipf);
139 close (fd);
140 return NULL;
142 lseek (fd, 0L, SEEK_SET);
143 if (read_zip_archive (zipf) != 0)
145 free (zipf);
146 close (fd);
147 return NULL;
151 SeenZipFiles = zipf;
152 return zipf;
155 /* Returns:
156 0: OK - zipmember found.
157 -1: Not found.
158 -2: Malformed archive.
162 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
163 int is_system)
165 ZipDirectory *zipd;
166 int i, len;
167 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
169 if (zipf == NULL)
170 return -2;
172 if (!zipmember)
173 return 0;
175 len = strlen (zipmember);
177 zipd = (struct ZipDirectory*) zipf->central_directory;
178 for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
180 if (len == zipd->filename_length &&
181 strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
183 JCF_ZERO (jcf);
185 jcf->filename = xstrdup (zipfile);
186 jcf->classname = xstrdup (zipmember);
187 return read_zip_member(jcf, zipd, zipf);
190 return -1;
193 /* Read data from zip archive member. */
196 read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf)
198 jcf->filbuf = jcf_unexpected_eof;
199 jcf->zipd = zipd;
201 if (zipd->compression_method == Z_NO_COMPRESSION)
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;
211 else
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;
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);
239 return 0;
242 const char *
243 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
245 if (jcf)
247 struct stat stat_buf;
248 if (fstat (fd, &stat_buf) != 0
249 || ! S_ISREG (stat_buf.st_mode))
251 perror ("Could not figure length of .class file");
252 return NULL;
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)
265 perror ("Failed to read .class file");
266 return NULL;
268 close (fd);
269 jcf->filbuf = jcf_unexpected_eof;
271 else
272 close (fd);
273 return filename;
277 const char *
278 find_classfile (char *filename, JCF *jcf, const char *dep_name)
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);
286 #if JCF_USE_SCANDIR
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 **). */
292 static int
293 compare_path (const void *key, const void *entry)
295 return strcmp ((const char *) key,
296 (*((const struct dirent **) entry))->d_name);
299 /* Returns nonzero if ENTRY names a .java or .class file. */
301 static int
302 java_or_class_file (const struct dirent *entry)
304 const char *base = lbasename (entry->d_name);
305 return (fnmatch ("*.java", base, 0) == 0 ||
306 fnmatch ("*.class", base, 0) == 0);
309 /* Information about the files present in a particular directory. */
310 typedef struct memoized_dirlist_entry
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;
322 /* A hash function for a memoized_dirlist_entry. */
323 static hashval_t
324 memoized_dirlist_hash (const void *entry)
326 const memoized_dirlist_entry *mde = (const memoized_dirlist_entry *) entry;
327 return htab_hash_string (mde->dir);
330 /* Returns true if ENTRY (a memoized_dirlist_entry *) corresponds to
331 the directory given by KEY (a char *) giving the directory
332 name. */
334 static int
335 memoized_dirlist_lookup_eq (const void *entry, const void *key)
337 return strcmp ((const char *) key,
338 ((const memoized_dirlist_entry *) entry)->dir) == 0;
341 /* A hash table mapping directory names to the lists of .java and
342 .class files in that directory. */
344 static htab_t memoized_dirlists;
346 #endif
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. */
351 static int
352 caching_stat (char *filename, struct stat *buf)
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;
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);
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)
377 origsep = *sep;
378 *sep = '\0';
379 base = sep + 1;
381 else
382 base = filename;
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)
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;
407 else
408 dent = *((memoized_dirlist_entry **) slot);
410 /* Put the separator back. */
411 if (sep)
412 *sep = origsep;
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
422 return stat (filename, buf);
425 /* Returns 1 if the CLASSNAME (really a char *) matches the name
426 stored in TABLE_ENTRY (also a char *). */
428 static int
429 memoized_class_lookup_eq (const void *table_entry, const void *classname)
431 return strcmp ((const char *)classname, (const char *)table_entry) == 0;
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;
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. */
447 const char *
448 find_class (const char *classname, int classname_length, JCF *jcf)
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;
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);
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;
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);
478 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
480 const char *path_name = jcf_path_name (entry);
481 if (class != 0)
483 int dir_len;
485 strcpy (buffer, path_name);
486 i = strlen (buffer);
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;
492 for (k = 0; k < classname_length; k++, i++)
494 char ch = classname[k];
495 buffer[i] = ch == '.' ? '/' : ch;
497 strcpy (buffer+i, ".class");
499 if (jcf_path_is_zipfile (entry))
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)
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;
521 else
522 continue;
524 class = caching_stat(buffer, &class_buf);
528 dep_file = buffer;
529 if (!class)
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;
540 free (buffer);
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;
547 return NULL;
548 found:
549 buffer = (char *) open_class (buffer, jcf, fd, dep_file);
550 jcf->classname = xstrdup (classname);
551 return buffer;
554 void
555 jcf_print_char (FILE *stream, int ch)
557 switch (ch)
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);
583 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
585 void
586 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
588 const unsigned char * limit = str + length;
589 while (str < limit)
591 int ch = UTF8_GET (str, limit);
592 if (ch < 0)
594 fprintf (stream, "\\<invalid>");
595 return;
597 jcf_print_char (stream, ch);
601 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
603 void
604 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
605 int in_char, int out_char)
607 const unsigned char *limit = str + length;
608 while (str < limit)
610 int ch = UTF8_GET (str, limit);
611 if (ch < 0)
613 fprintf (stream, "\\<invalid>");
614 return;
616 jcf_print_char (stream, ch == in_char ? out_char : ch);
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.*/
627 verify_constant_pool (JCF *jcf)
629 int i, n;
630 for (i = 1; i < JPOOL_SIZE (jcf); i++)
632 switch (JPOOL_TAG (jcf, i))
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;
672 return 0;
675 void
676 format_uint (char *buffer, uint64 value, int base)
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;
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);
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;
699 void
700 format_int (char *buffer, jlong value, int base)
702 uint64 abs_value;
703 if (value < 0)
705 abs_value = -(uint64)value;
706 *buffer++ = '-';
708 else
709 abs_value = (uint64) value;
710 format_uint (buffer, abs_value, base);