2006-08-07 Andrew John Hughes <gnu_andrew@member.fsf.org>
[official-gcc.git] / gcc / java / jcf-io.c
blob426b2532b128694a6f44e5053d06b38099264ef7
1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005, 2006
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)
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)
137 return NULL;
138 lseek (fd, 0L, SEEK_SET);
139 if (read_zip_archive (zipf) != 0)
140 return NULL;
143 SeenZipFiles = zipf;
144 return zipf;
147 /* Returns:
148 0: OK - zipmember found.
149 -1: Not found.
150 -2: Malformed archive.
154 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
155 int is_system)
157 ZipDirectory *zipd;
158 int i, len;
159 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
161 if (zipf == NULL)
162 return -2;
164 if (!zipmember)
165 return 0;
167 len = strlen (zipmember);
169 zipd = (struct ZipDirectory*) zipf->central_directory;
170 for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
172 if (len == zipd->filename_length &&
173 strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
175 JCF_ZERO (jcf);
177 jcf->filename = xstrdup (zipfile);
178 jcf->classname = xstrdup (zipmember);
179 return read_zip_member(jcf, zipd, zipf);
182 return -1;
185 /* Read data from zip archive member. */
188 read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf)
190 jcf->filbuf = jcf_unexpected_eof;
191 jcf->zipd = zipd;
193 if (zipd->compression_method == Z_NO_COMPRESSION)
195 jcf->buffer = XNEWVEC (unsigned char, zipd->size);
196 jcf->buffer_end = jcf->buffer + zipd->size;
197 jcf->read_ptr = jcf->buffer;
198 jcf->read_end = jcf->buffer_end;
199 if (lseek (zipf->fd, zipd->filestart, 0) < 0
200 || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
201 return -2;
203 else
205 char *buffer;
206 z_stream d_stream; /* decompression stream */
207 d_stream.zalloc = (alloc_func) 0;
208 d_stream.zfree = (free_func) 0;
209 d_stream.opaque = (voidpf) 0;
211 jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
212 d_stream.next_out = jcf->buffer;
213 d_stream.avail_out = zipd->uncompressed_size;
214 jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
215 jcf->read_ptr = jcf->buffer;
216 jcf->read_end = jcf->buffer_end;
217 buffer = XNEWVEC (char, zipd->size);
218 d_stream.next_in = (unsigned char *) buffer;
219 d_stream.avail_in = zipd->size;
220 if (lseek (zipf->fd, zipd->filestart, 0) < 0
221 || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
222 return -2;
223 /* Handle NO_HEADER using undocumented zlib feature.
224 This is a very common hack. */
225 inflateInit2 (&d_stream, -MAX_WBITS);
226 inflate (&d_stream, Z_NO_FLUSH);
227 inflateEnd (&d_stream);
228 free (buffer);
231 return 0;
234 const char *
235 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
237 if (jcf)
239 struct stat stat_buf;
240 if (fstat (fd, &stat_buf) != 0
241 || ! S_ISREG (stat_buf.st_mode))
243 perror ("Could not figure length of .class file");
244 return NULL;
246 if (dep_name != NULL)
247 jcf_dependency_add_file (dep_name, 0);
248 JCF_ZERO (jcf);
249 jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
250 jcf->buffer_end = jcf->buffer + stat_buf.st_size;
251 jcf->read_ptr = jcf->buffer;
252 jcf->read_end = jcf->buffer_end;
253 jcf->read_state = NULL;
254 jcf->filename = filename;
255 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
257 perror ("Failed to read .class file");
258 return NULL;
260 close (fd);
261 jcf->filbuf = jcf_unexpected_eof;
263 else
264 close (fd);
265 return filename;
269 const char *
270 find_classfile (char *filename, JCF *jcf, const char *dep_name)
272 int fd = open (filename, O_RDONLY | O_BINARY);
273 if (fd < 0)
274 return NULL;
275 return open_class (filename, jcf, fd, dep_name);
278 #if JCF_USE_SCANDIR
280 /* A comparison function (as for qsort) that compares KEY (a char *
281 giving the basename of a file) with the name stored in ENTRY (a
282 dirent **). */
284 static int
285 compare_path (const void *key, const void *entry)
287 return strcmp ((const char *) key,
288 (*((const struct dirent **) entry))->d_name);
291 /* Returns nonzero if ENTRY names a .java or .class file. */
293 static int
294 java_or_class_file (const struct dirent *entry)
296 const char *base = lbasename (entry->d_name);
297 return (fnmatch ("*.java", base, 0) == 0 ||
298 fnmatch ("*.class", base, 0) == 0);
301 /* Information about the files present in a particular directory. */
302 typedef struct memoized_dirlist_entry
304 /* The name of the directory. */
305 const char *dir;
306 /* The number of .java and .class files present, or -1 if we could
307 not, for some reason, obtain the list. */
308 int num_files;
309 /* The .java and .class files in the directory, in alphabetical
310 order. */
311 struct dirent **files;
312 } memoized_dirlist_entry;
314 /* A hash function for a memoized_dirlist_entry. */
315 static hashval_t
316 memoized_dirlist_hash (const void *entry)
318 const memoized_dirlist_entry *mde = (const memoized_dirlist_entry *) entry;
319 return htab_hash_string (mde->dir);
322 /* Returns true if ENTRY (a memoized_dirlist_entry *) corresponds to
323 the directory given by KEY (a char *) giving the directory
324 name. */
326 static int
327 memoized_dirlist_lookup_eq (const void *entry, const void *key)
329 return strcmp ((const char *) key,
330 ((const memoized_dirlist_entry *) entry)->dir) == 0;
333 /* A hash table mapping directory names to the lists of .java and
334 .class files in that directory. */
336 static htab_t memoized_dirlists;
338 #endif
340 /* Like stat, but avoids actually making the stat system call if we
341 know that it cannot succeed. FILENAME and BUF are as for stat. */
343 static int
344 caching_stat (char *filename, struct stat *buf)
346 #if JCF_USE_SCANDIR
347 char *sep;
348 char origsep = 0;
349 char *base;
350 memoized_dirlist_entry *dent;
351 void **slot;
352 struct memoized_dirlist_entry temp;
354 /* If the hashtable has not already been created, create it now. */
355 if (!memoized_dirlists)
356 memoized_dirlists = htab_create (37,
357 memoized_dirlist_hash,
358 memoized_dirlist_lookup_eq,
359 NULL);
361 /* Get the name of the directory. */
362 sep = strrchr (filename, DIR_SEPARATOR);
363 #ifdef DIR_SEPARATOR_2
364 if (! sep)
365 sep = strrchr (filename, DIR_SEPARATOR_2);
366 #endif
367 if (sep)
369 origsep = *sep;
370 *sep = '\0';
371 base = sep + 1;
373 else
374 base = filename;
376 /* Obtain the entry for this directory from the hash table. This
377 approach is ok since we know that the hash function only looks at
378 the directory name. */
379 temp.dir = filename;
380 temp.num_files = 0;
381 temp.files = NULL;
382 slot = htab_find_slot (memoized_dirlists, &temp, INSERT);
383 if (!*slot)
385 /* We have not already scanned this directory; scan it now. */
386 dent = XNEW (memoized_dirlist_entry);
387 dent->dir = xstrdup (filename);
388 /* Unfortunately, scandir is not fully standardized. In
389 particular, the type of the function pointer passed as the
390 third argument sometimes takes a "const struct dirent *"
391 parameter, and sometimes just a "struct dirent *". We cast
392 to (void *) and use __extension__ so that either way it is
393 quietly accepted. FIXME: scandir is not in POSIX. */
394 dent->num_files = __extension__ scandir (filename, &dent->files,
395 (void *) java_or_class_file,
396 alphasort);
397 *slot = dent;
399 else
400 dent = *((memoized_dirlist_entry **) slot);
402 /* Put the separator back. */
403 if (sep)
404 *sep = origsep;
406 /* If the file is not in the list, there is no need to stat it; it
407 does not exist. */
408 if (dent->num_files != -1
409 && !bsearch (base, dent->files, dent->num_files,
410 sizeof (struct dirent *), compare_path))
411 return -1;
412 #endif
414 return stat (filename, buf);
417 /* Returns 1 if the CLASSNAME (really a char *) matches the name
418 stored in TABLE_ENTRY (also a char *). */
420 static int
421 memoized_class_lookup_eq (const void *table_entry, const void *classname)
423 return strcmp ((const char *)classname, (const char *)table_entry) == 0;
426 /* A hash table keeping track of class names that were not found
427 during class lookup. (There is no need to cache the values
428 associated with names that were found; they are saved in
429 IDENTIFIER_CLASS_VALUE.) */
430 static htab_t memoized_class_lookups;
432 /* Returns a freshly malloc'd string with the fully qualified pathname
433 of the .class file for the class CLASSNAME. CLASSNAME must be
434 allocated in permanent storage; this function may retain a pointer
435 to it. Returns NULL on failure. If JCF != NULL, it is suitably
436 initialized. SOURCE_OK is true if we should also look for .java
437 file. */
439 const char *
440 find_class (const char *classname, int classname_length, JCF *jcf,
441 int source_ok)
443 int fd;
444 int i, k, java = -1, class = -1;
445 struct stat java_buf, class_buf;
446 char *dep_file;
447 void *entry;
448 char *java_buffer;
449 int buflen;
450 char *buffer;
451 hashval_t hash;
453 /* FIXME: ecj hack. */
454 source_ok = 0;
456 /* Create the hash table, if it does not already exist. */
457 if (!memoized_class_lookups)
458 memoized_class_lookups = htab_create (37,
459 htab_hash_string,
460 memoized_class_lookup_eq,
461 NULL);
463 /* Loop for this class in the hashtable. If it is present, we've
464 already looked for this class and failed to find it. */
465 hash = htab_hash_string (classname);
466 if (htab_find_with_hash (memoized_class_lookups, classname, hash))
467 return NULL;
469 /* Allocate and zero out the buffer, since we don't explicitly put a
470 null pointer when we're copying it below. */
471 buflen = jcf_path_max_len () + classname_length + 10;
472 buffer = ALLOC (buflen);
473 memset (buffer, 0, buflen);
475 java_buffer = alloca (buflen);
477 jcf->java_source = 0;
479 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
481 const char *path_name = jcf_path_name (entry);
482 if (class != 0)
484 int dir_len;
486 strcpy (buffer, path_name);
487 i = strlen (buffer);
489 /* This is right because we know that `.zip' entries will have a
490 trailing slash. See jcf-path.c. */
491 dir_len = i - 1;
493 for (k = 0; k < classname_length; k++, i++)
495 char ch = classname[k];
496 buffer[i] = ch == '.' ? '/' : ch;
498 strcpy (buffer+i, ".class");
500 if (jcf_path_is_zipfile (entry))
502 int err_code;
503 JCF _jcf;
504 buffer[dir_len] = '\0';
505 SOURCE_FRONTEND_DEBUG
506 (("Trying [...%s]:%s",
507 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
508 buffer+dir_len+1));
509 if (jcf == NULL)
510 jcf = &_jcf;
511 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
512 jcf_path_is_system (entry));
513 if (err_code == 0)
515 /* Should we check if .zip is out-of-date wrt .java? */
516 buffer[dir_len] = '(';
517 strcpy (buffer+i, ".class)");
518 if (jcf == &_jcf)
519 JCF_FINISH (jcf);
520 return buffer;
522 else
523 continue;
525 class = caching_stat(buffer, &class_buf);
528 if (source_ok)
530 /* Compute name of .java file. */
531 int l, m;
532 strcpy (java_buffer, path_name);
533 l = strlen (java_buffer);
534 for (m = 0; m < classname_length; ++m)
535 java_buffer[m + l] = (classname[m] == '.'
536 ? DIR_SEPARATOR : classname[m]);
537 strcpy (java_buffer + m + l, ".java");
538 java = caching_stat (java_buffer, &java_buf);
539 if (java == 0)
540 break;
544 /* We preferably pick a class file if we have a chance. If the source
545 file is newer than the class file, we issue a warning and parse the
546 source file instead.
547 There should be a flag to allow people have the class file picked
548 up no matter what. FIXME. */
549 if (! java && ! class && java_buf.st_mtime > class_buf.st_mtime)
551 if (flag_newer)
552 warning (0, "source file for class %qs is newer than its matching class file. Source file %qs used instead", classname, java_buffer);
553 class = -1;
556 if (! java)
557 dep_file = java_buffer;
558 else
559 dep_file = buffer;
560 if (!class)
562 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
563 classname+classname_length-
564 (classname_length <= 30 ?
565 classname_length : 30)));
566 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
567 if (fd >= 0)
568 goto found;
570 /* Give .java a try, if necessary */
571 if (!java)
573 strcpy (buffer, java_buffer);
574 SOURCE_FRONTEND_DEBUG ((stderr, "[Source selected: %s]\n",
575 classname+classname_length-
576 (classname_length <= 30 ?
577 classname_length : 30)));
578 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY);
579 if (fd >= 0)
581 jcf->java_source = 1;
582 goto found;
586 free (buffer);
588 /* Remember that this class could not be found so that we do not
589 have to look again. */
590 *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT)
591 = (void *) classname;
593 return NULL;
594 found:
595 if (jcf->java_source)
597 JCF_ZERO (jcf); /* JCF_FINISH relies on this */
598 jcf->java_source = 1;
599 jcf->filename = xstrdup (buffer);
600 close (fd); /* We use STDIO for source file */
602 else
603 buffer = (char *) open_class (buffer, jcf, fd, dep_file);
604 jcf->classname = xstrdup (classname);
605 return buffer;
608 void
609 jcf_print_char (FILE *stream, int ch)
611 switch (ch)
613 case '\'':
614 case '\\':
615 case '\"':
616 fprintf (stream, "\\%c", ch);
617 break;
618 case '\n':
619 fprintf (stream, "\\n");
620 break;
621 case '\t':
622 fprintf (stream, "\\t");
623 break;
624 case '\r':
625 fprintf (stream, "\\r");
626 break;
627 default:
628 if (ch >= ' ' && ch < 127)
629 putc (ch, stream);
630 else if (ch < 256)
631 fprintf (stream, "\\%03x", ch);
632 else
633 fprintf (stream, "\\u%04x", ch);
637 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
639 void
640 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
642 const unsigned char * limit = str + length;
643 while (str < limit)
645 int ch = UTF8_GET (str, limit);
646 if (ch < 0)
648 fprintf (stream, "\\<invalid>");
649 return;
651 jcf_print_char (stream, ch);
655 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
657 void
658 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
659 int in_char, int out_char)
661 const unsigned char *limit = str + length;
662 while (str < limit)
664 int ch = UTF8_GET (str, limit);
665 if (ch < 0)
667 fprintf (stream, "\\<invalid>");
668 return;
670 jcf_print_char (stream, ch == in_char ? out_char : ch);
674 /* Check that all the cross-references in the constant pool are
675 valid. Returns 0 on success.
676 Otherwise, returns the index of the (first) invalid entry.
677 Only checks internal consistency, but does not check that
678 any classes, fields, or methods are valid.*/
681 verify_constant_pool (JCF *jcf)
683 int i, n;
684 for (i = 1; i < JPOOL_SIZE (jcf); i++)
686 switch (JPOOL_TAG (jcf, i))
688 case CONSTANT_NameAndType:
689 n = JPOOL_USHORT2 (jcf, i);
690 if (n <= 0 || n >= JPOOL_SIZE(jcf)
691 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
692 return i;
693 /* ... fall through ... */
694 case CONSTANT_Class:
695 case CONSTANT_String:
696 n = JPOOL_USHORT1 (jcf, i);
697 if (n <= 0 || n >= JPOOL_SIZE(jcf)
698 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
699 return i;
700 break;
701 case CONSTANT_Fieldref:
702 case CONSTANT_Methodref:
703 case CONSTANT_InterfaceMethodref:
704 n = JPOOL_USHORT1 (jcf, i);
705 if (n <= 0 || n >= JPOOL_SIZE(jcf)
706 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
707 return i;
708 n = JPOOL_USHORT2 (jcf, i);
709 if (n <= 0 || n >= JPOOL_SIZE(jcf)
710 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
711 return i;
712 break;
713 case CONSTANT_Long:
714 case CONSTANT_Double:
715 i++;
716 break;
717 case CONSTANT_Float:
718 case CONSTANT_Integer:
719 case CONSTANT_Utf8:
720 case CONSTANT_Unicode:
721 break;
722 default:
723 return i;
726 return 0;
729 void
730 format_uint (char *buffer, uint64 value, int base)
732 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
733 char buf[WRITE_BUF_SIZE];
734 char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
735 int chars_written;
736 int i;
738 /* Now do the actual conversion, placing the result at the *end* of buf. */
739 /* Note this code does not pretend to be optimized. */
740 do {
741 int digit = value % base;
742 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
743 *--buf_ptr = digit_chars[digit];
744 value /= base;
745 } while (value != 0);
747 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
748 for (i = 0; i < chars_written; i++)
749 buffer[i] = *buf_ptr++;
750 buffer[i] = 0;
753 void
754 format_int (char *buffer, jlong value, int base)
756 uint64 abs_value;
757 if (value < 0)
759 abs_value = -(uint64)value;
760 *buffer++ = '-';
762 else
763 abs_value = (uint64) value;
764 format_uint (buffer, abs_value, base);