Merge basic-improvements-branch to trunk
[official-gcc.git] / gcc / java / jcf-io.c
blobe0138f4398cd74b57390617b9e77544ced8992ff
1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
7 any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with GNU CC; see the file COPYING. If not, write to
16 the Free Software Foundation, 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
19 Java and all Java-based marks are trademarks or registered trademarks
20 of Sun Microsystems, Inc. in the United States and other countries.
21 The Free Software Foundation is independent of Sun Microsystems, Inc. */
23 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
25 #include "config.h"
26 #include "system.h"
27 #include "coretypes.h"
28 #include "tm.h"
30 #include "jcf.h"
31 #include "tree.h"
32 #include "toplev.h"
33 #include "java-tree.h"
34 #include "hashtab.h"
35 #if JCF_USE_SCANDIR
36 #include <dirent.h>
37 #include <fnmatch.h>
38 #endif
40 #include "zlib.h"
42 /* DOS brain-damage */
43 #ifndef O_BINARY
44 #define O_BINARY 0 /* MS-DOS brain-damage */
45 #endif
47 int
48 DEFUN(jcf_unexpected_eof, (jcf, count),
49 JCF *jcf AND int count ATTRIBUTE_UNUSED)
51 if (jcf->filename)
52 fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
53 else
54 fprintf (stderr, "Premature end of .class file <stdin>.\n");
55 exit (-1);
58 void
59 DEFUN(jcf_trim_old_input, (jcf),
60 JCF *jcf)
62 int count = jcf->read_ptr - jcf->buffer;
63 if (count > 0)
65 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
66 jcf->read_ptr -= count;
67 jcf->read_end -= count;
71 int
72 DEFUN(jcf_filbuf_from_stdio, (jcf, count),
73 JCF *jcf AND 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 DEFUN(opendir_in_zip, (zipfile, is_system),
109 const char *zipfile AND int is_system)
111 struct ZipFile* zipf;
112 char magic [4];
113 int fd;
114 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
116 if (strcmp (zipf->name, zipfile) == 0)
117 return zipf;
120 zipf = ALLOC (sizeof (struct ZipFile) + strlen (zipfile) + 1);
121 zipf->next = SeenZipFiles;
122 zipf->name = (char*)(zipf+1);
123 strcpy (zipf->name, zipfile);
124 SeenZipFiles = zipf;
125 fd = open (zipfile, O_RDONLY | O_BINARY);
126 zipf->fd = fd;
127 if (fd < 0)
129 /* A missing zip file is not considered an error.
130 We may want to re-consider that. FIXME. */
131 zipf->count = 0;
132 zipf->dir_size = 0;
133 zipf->central_directory = NULL;
135 else
137 jcf_dependency_add_file (zipfile, is_system);
138 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
139 return NULL;
140 lseek (fd, 0L, SEEK_SET);
141 if (read_zip_archive (zipf) != 0)
142 return NULL;
144 return zipf;
147 /* Returns:
148 0: OK - zipmember found.
149 -1: Not found.
150 -2: Malformed archive.
154 DEFUN(open_in_zip, (jcf, zipfile, zipmember, is_system),
155 JCF *jcf AND const char *zipfile AND const char *zipmember
156 AND int is_system)
158 ZipDirectory *zipd;
159 int i, len;
160 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
162 if (zipf == NULL)
163 return -2;
165 if (!zipmember)
166 return 0;
168 len = strlen (zipmember);
170 zipd = (struct ZipDirectory*) zipf->central_directory;
171 for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
173 if (len == zipd->filename_length &&
174 strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
176 JCF_ZERO (jcf);
178 jcf->filename = xstrdup (zipfile);
179 jcf->classname = xstrdup (zipmember);
180 return read_zip_member(jcf, zipd, zipf);
183 return -1;
186 /* Read data from zip archive member. */
189 DEFUN(read_zip_member, (jcf, zipd, zipf),
190 JCF *jcf AND ZipDirectory *zipd AND ZipFile *zipf)
192 jcf->filbuf = jcf_unexpected_eof;
193 jcf->zipd = (void *)zipd;
195 if (zipd->compression_method == Z_NO_COMPRESSION)
197 jcf->buffer = ALLOC (zipd->size);
198 jcf->buffer_end = jcf->buffer + zipd->size;
199 jcf->read_ptr = jcf->buffer;
200 jcf->read_end = jcf->buffer_end;
201 if (lseek (zipf->fd, zipd->filestart, 0) < 0
202 || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
203 return -2;
205 else
207 char *buffer;
208 z_stream d_stream; /* decompression stream */
209 d_stream.zalloc = (alloc_func) 0;
210 d_stream.zfree = (free_func) 0;
211 d_stream.opaque = (voidpf) 0;
213 jcf->buffer = ALLOC (zipd->uncompressed_size);
214 d_stream.next_out = jcf->buffer;
215 d_stream.avail_out = zipd->uncompressed_size;
216 jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
217 jcf->read_ptr = jcf->buffer;
218 jcf->read_end = jcf->buffer_end;
219 buffer = ALLOC (zipd->size);
220 d_stream.next_in = buffer;
221 d_stream.avail_in = zipd->size;
222 if (lseek (zipf->fd, zipd->filestart, 0) < 0
223 || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
224 return -2;
225 /* Handle NO_HEADER using undocumented zlib feature.
226 This is a very common hack. */
227 inflateInit2 (&d_stream, -MAX_WBITS);
228 inflate (&d_stream, Z_NO_FLUSH);
229 inflateEnd (&d_stream);
230 FREE (buffer);
233 return 0;
236 const char *
237 DEFUN(open_class, (filename, jcf, fd, dep_name),
238 const char *filename AND JCF *jcf AND int fd AND const char *dep_name)
240 if (jcf)
242 struct stat stat_buf;
243 if (fstat (fd, &stat_buf) != 0
244 || ! S_ISREG (stat_buf.st_mode))
246 perror ("Could not figure length of .class file");
247 return NULL;
249 if (dep_name != NULL)
250 jcf_dependency_add_file (dep_name, 0);
251 JCF_ZERO (jcf);
252 jcf->buffer = ALLOC (stat_buf.st_size);
253 jcf->buffer_end = jcf->buffer + stat_buf.st_size;
254 jcf->read_ptr = jcf->buffer;
255 jcf->read_end = jcf->buffer_end;
256 jcf->read_state = NULL;
257 jcf->filename = filename;
258 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
260 perror ("Failed to read .class file");
261 return NULL;
263 close (fd);
264 jcf->filbuf = jcf_unexpected_eof;
266 else
267 close (fd);
268 return filename;
272 const char *
273 DEFUN(find_classfile, (filename, jcf, dep_name),
274 char *filename AND JCF *jcf AND const char *dep_name)
276 int fd = open (filename, O_RDONLY | O_BINARY);
277 if (fd < 0)
278 return NULL;
279 return open_class (filename, jcf, fd, dep_name);
282 #if JCF_USE_SCANDIR
284 /* A comparison function (as for qsort) that compares KEY (a char *
285 giving the basename of a file) with the name stored in ENTRY (a
286 dirent **). */
288 static int
289 DEFUN(compare_path, (key, entry),
290 const void *key AND const void *entry)
292 return strcmp ((const char *) key,
293 (*((const struct dirent **) entry))->d_name);
296 /* Returns nonzero if ENTRY names a .java or .class file. */
298 static int
299 DEFUN(java_or_class_file, (entry),
300 const struct dirent *entry)
302 const char *base = basename (entry->d_name);
303 return (fnmatch ("*.java", base, 0) == 0 ||
304 fnmatch ("*.class", base, 0) == 0);
307 /* Information about the files present in a particular directory. */
308 typedef struct memoized_dirlist_entry
310 /* The name of the directory. */
311 const char *dir;
312 /* The number of .java and .class files present, or -1 if we could
313 not, for some reason, obtain the list. */
314 int num_files;
315 /* The .java and .class files in the directory, in alphabetical
316 order. */
317 struct dirent **files;
318 } memoized_dirlist_entry;
320 /* Returns true if ENTRY (a memoized_dirlist_entry *) correponds to
321 the directory given by KEY (a char *) giving the directory
322 name. */
324 static int
325 DEFUN(memoized_dirlist_lookup_eq, (entry, key),
326 const void *entry AND const void *key)
328 return strcmp ((const char *) key,
329 ((const memoized_dirlist_entry *) entry)->dir) == 0;
332 /* A hash table mapping directory names to the lists of .java and
333 .class files in that directory. */
335 static htab_t memoized_dirlists;
337 #endif
339 /* Like stat, but avoids actually making the stat system call if we
340 know that it cannot succeed. FILENAME and BUF are as for stat. */
342 static int
343 DEFUN(caching_stat, (filename, buf),
344 char *filename AND struct stat *buf)
346 #if JCF_USE_SCANDIR
347 char *sep;
348 char *base;
349 memoized_dirlist_entry *dent;
350 void **slot;
352 /* If the hashtable has not already been created, create it now. */
353 if (!memoized_dirlists)
354 memoized_dirlists = htab_create (37,
355 htab_hash_string,
356 memoized_dirlist_lookup_eq,
357 NULL);
359 /* Get the name of the directory. */
360 sep = strrchr (filename, DIR_SEPARATOR);
361 if (sep)
363 *sep = '\0';
364 base = sep + 1;
366 else
367 base = filename;
369 /* Obtain the entry for this directory form the hash table. */
370 slot = htab_find_slot (memoized_dirlists, filename, INSERT);
371 if (!*slot)
373 /* We have not already scanned this directory; scan it now. */
374 dent = ((memoized_dirlist_entry *)
375 ALLOC (sizeof (memoized_dirlist_entry)));
376 dent->dir = xstrdup (filename);
377 /* Unfortunately, scandir is not fully standardized. In
378 particular, the type of the function pointer passed as the
379 third argument sometimes takes a "const struct dirent *"
380 parameter, and sometimes just a "struct dirent *". We rely
381 on the ability to interchange these two types of function
382 pointers. */
383 dent->num_files = scandir (filename, &dent->files,
384 java_or_class_file,
385 alphasort);
386 *slot = dent;
388 else
389 dent = *((memoized_dirlist_entry **) slot);
391 /* Put the spearator back. */
392 if (sep)
393 *sep = DIR_SEPARATOR;
395 /* If the file is not in the list, there is no need to stat it; it
396 does not exist. */
397 if (dent->num_files != -1
398 && !bsearch (base, dent->files, dent->num_files,
399 sizeof (struct dirent *), compare_path))
400 return -1;
401 #endif
403 return stat (filename, buf);
406 /* Returns 1 if the CLASSNAME (really a char *) matches the name
407 stored in TABLE_ENTRY (also a char *). */
409 static int
410 DEFUN(memoized_class_lookup_eq, (table_entry, classname),
411 const void *table_entry AND const void *classname)
413 return strcmp ((const char *)classname, (const char *)table_entry) == 0;
416 /* A hash table keeping track of class names that were not found
417 during class lookup. (There is no need to cache the values
418 associated with names that were found; they are saved in
419 IDENTIFIER_CLASS_VALUE.) */
420 static htab_t memoized_class_lookups;
422 /* Returns a freshly malloc'd string with the fully qualified pathname
423 of the .class file for the class CLASSNAME. CLASSNAME must be
424 allocated in permanent storage; this function may retain a pointer
425 to it. Returns NULL on failure. If JCF != NULL, it is suitably
426 initialized. SOURCE_OK is true if we should also look for .java
427 file. */
429 const char *
430 DEFUN(find_class, (classname, classname_length, jcf, source_ok),
431 const char *classname AND int classname_length AND JCF *jcf AND int source_ok)
434 int fd;
435 int i, k, java = -1, class = -1;
436 struct stat java_buf, class_buf;
437 char *dep_file;
438 void *entry;
439 char *java_buffer;
440 int buflen;
441 char *buffer;
442 hashval_t hash;
444 /* Create the hash table, if it does not already exist. */
445 if (!memoized_class_lookups)
446 memoized_class_lookups = htab_create (37,
447 htab_hash_string,
448 memoized_class_lookup_eq,
449 NULL);
451 /* Loop for this class in the hashtable. If it is present, we've
452 already looked for this class and failed to find it. */
453 hash = htab_hash_string (classname);
454 if (htab_find_with_hash (memoized_class_lookups, classname, hash))
455 return NULL;
457 /* Allocate and zero out the buffer, since we don't explicitly put a
458 null pointer when we're copying it below. */
459 buflen = jcf_path_max_len () + classname_length + 10;
460 buffer = ALLOC (buflen);
461 memset (buffer, 0, buflen);
463 java_buffer = alloca (buflen);
465 jcf->java_source = 0;
467 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
469 const char *path_name = jcf_path_name (entry);
470 if (class != 0)
472 int dir_len;
474 strcpy (buffer, path_name);
475 i = strlen (buffer);
477 /* This is right because we know that `.zip' entries will have a
478 trailing slash. See jcf-path.c. */
479 dir_len = i - 1;
481 for (k = 0; k < classname_length; k++, i++)
483 char ch = classname[k];
484 buffer[i] = ch == '.' ? '/' : ch;
486 strcpy (buffer+i, ".class");
488 if (jcf_path_is_zipfile (entry))
490 int err_code;
491 JCF _jcf;
492 buffer[dir_len] = '\0';
493 SOURCE_FRONTEND_DEBUG
494 (("Trying [...%s]:%s",
495 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
496 buffer+dir_len+1));
497 if (jcf == NULL)
498 jcf = &_jcf;
499 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
500 jcf_path_is_system (entry));
501 if (err_code == 0)
503 /* Should we check if .zip is out-of-date wrt .java? */
504 buffer[dir_len] = '(';
505 strcpy (buffer+i, ".class)");
506 if (jcf == &_jcf)
507 JCF_FINISH (jcf);
508 return buffer;
510 else
511 continue;
513 class = caching_stat(buffer, &class_buf);
516 if (source_ok)
518 /* Compute name of .java file. */
519 int l, m;
520 strcpy (java_buffer, path_name);
521 l = strlen (java_buffer);
522 for (m = 0; m < classname_length; ++m)
523 java_buffer[m + l] = (classname[m] == '.' ? '/' : classname[m]);
524 strcpy (java_buffer + m + l, ".java");
525 java = caching_stat (java_buffer, &java_buf);
526 if (java == 0)
527 break;
531 /* We preferably pick a class file if we have a chance. If the source
532 file is newer than the class file, we issue a warning and parse the
533 source file instead.
534 There should be a flag to allow people have the class file picked
535 up no matter what. FIXME. */
536 if (! java && ! class && java_buf.st_mtime > class_buf.st_mtime)
538 if (flag_newer)
539 warning ("source file for class `%s' is newer than its matching class file. Source file `%s' used instead", classname, java_buffer);
540 class = -1;
543 if (! java)
544 dep_file = java_buffer;
545 else
546 dep_file = buffer;
547 if (!class)
549 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
550 classname+classname_length-
551 (classname_length <= 30 ?
552 classname_length : 30)));
553 fd = open (buffer, O_RDONLY | O_BINARY);
554 if (fd >= 0)
555 goto found;
557 /* Give .java a try, if necessary */
558 if (!java)
560 strcpy (buffer, java_buffer);
561 SOURCE_FRONTEND_DEBUG ((stderr, "[Source selected: %s]\n",
562 classname+classname_length-
563 (classname_length <= 30 ?
564 classname_length : 30)));
565 fd = open (buffer, O_RDONLY);
566 if (fd >= 0)
568 jcf->java_source = 1;
569 goto found;
573 free (buffer);
575 /* Remember that this class could not be found so that we do not
576 have to look again. */
577 *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT)
578 = (void *) classname;
580 return NULL;
581 found:
582 if (jcf->java_source)
584 JCF_ZERO (jcf); /* JCF_FINISH relies on this */
585 jcf->java_source = 1;
586 jcf->filename = xstrdup (buffer);
587 close (fd); /* We use STDIO for source file */
589 else
590 buffer = (char *) open_class (buffer, jcf, fd, dep_file);
591 jcf->classname = xstrdup (classname);
592 return buffer;
595 void
596 DEFUN(jcf_print_char, (stream, ch),
597 FILE *stream AND int ch)
599 switch (ch)
601 case '\'':
602 case '\\':
603 case '\"':
604 fprintf (stream, "\\%c", ch);
605 break;
606 case '\n':
607 fprintf (stream, "\\n");
608 break;
609 case '\t':
610 fprintf (stream, "\\t");
611 break;
612 case '\r':
613 fprintf (stream, "\\r");
614 break;
615 default:
616 if (ch >= ' ' && ch < 127)
617 putc (ch, stream);
618 else if (ch < 256)
619 fprintf (stream, "\\%03x", ch);
620 else
621 fprintf (stream, "\\u%04x", ch);
625 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
627 void
628 DEFUN(jcf_print_utf8, (stream, str, length),
629 FILE *stream AND register const unsigned char *str AND int length)
631 const unsigned char * limit = str + length;
632 while (str < limit)
634 int ch = UTF8_GET (str, limit);
635 if (ch < 0)
637 fprintf (stream, "\\<invalid>");
638 return;
640 jcf_print_char (stream, ch);
644 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
646 void
647 DEFUN(jcf_print_utf8_replace, (stream, str, length, in_char, out_char),
648 FILE *stream AND const unsigned char *str AND int length
649 AND int in_char AND int out_char)
651 const unsigned char *limit = str + length;
652 while (str < limit)
654 int ch = UTF8_GET (str, limit);
655 if (ch < 0)
657 fprintf (stream, "\\<invalid>");
658 return;
660 jcf_print_char (stream, ch == in_char ? out_char : ch);
664 /* Check that all the cross-references in the constant pool are
665 valid. Returns 0 on success.
666 Otherwise, returns the index of the (first) invalid entry.
667 Only checks internal consistency, but does not check that
668 any classes, fields, or methods are valid.*/
671 DEFUN(verify_constant_pool, (jcf),
672 JCF *jcf)
674 int i, n;
675 for (i = 1; i < JPOOL_SIZE (jcf); i++)
677 switch (JPOOL_TAG (jcf, i))
679 case CONSTANT_NameAndType:
680 n = JPOOL_USHORT2 (jcf, i);
681 if (n <= 0 || n >= JPOOL_SIZE(jcf)
682 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
683 return i;
684 /* ... fall through ... */
685 case CONSTANT_Class:
686 case CONSTANT_String:
687 n = JPOOL_USHORT1 (jcf, i);
688 if (n <= 0 || n >= JPOOL_SIZE(jcf)
689 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
690 return i;
691 break;
692 case CONSTANT_Fieldref:
693 case CONSTANT_Methodref:
694 case CONSTANT_InterfaceMethodref:
695 n = JPOOL_USHORT1 (jcf, i);
696 if (n <= 0 || n >= JPOOL_SIZE(jcf)
697 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
698 return i;
699 n = JPOOL_USHORT2 (jcf, i);
700 if (n <= 0 || n >= JPOOL_SIZE(jcf)
701 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
702 return i;
703 break;
704 case CONSTANT_Long:
705 case CONSTANT_Double:
706 i++;
707 break;
708 case CONSTANT_Float:
709 case CONSTANT_Integer:
710 case CONSTANT_Utf8:
711 case CONSTANT_Unicode:
712 break;
713 default:
714 return i;
717 return 0;
720 void
721 DEFUN(format_uint, (buffer, value, base),
722 char *buffer AND uint64 value AND int base)
724 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
725 char buf[WRITE_BUF_SIZE];
726 register char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
727 int chars_written;
728 int i;
730 /* Now do the actual conversion, placing the result at the *end* of buf. */
731 /* Note this code does not pretend to be optimized. */
732 do {
733 int digit = value % base;
734 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
735 *--buf_ptr = digit_chars[digit];
736 value /= base;
737 } while (value != 0);
739 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
740 for (i = 0; i < chars_written; i++)
741 buffer[i] = *buf_ptr++;
742 buffer[i] = 0;
745 void
746 DEFUN(format_int, (buffer, value, base),
747 char *buffer AND jlong value AND int base)
749 uint64 abs_value;
750 if (value < 0)
752 abs_value = -(uint64)value;
753 *buffer++ = '-';
755 else
756 abs_value = (uint64) value;
757 format_uint (buffer, abs_value, base);