mips.c (build_mips16_call_stub): On 64-bit targets, combine an SC return value into...
[official-gcc.git] / gcc / java / jcf-io.c
blobf639e1089c999e82d91af99a5a566fb6b92f0c73
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 3, 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 COPYING3. If not see
19 <http://www.gnu.org/licenses/>.
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. */
25 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
27 #include "config.h"
28 #include "system.h"
29 #include "coretypes.h"
30 #include "tm.h"
32 #include "jcf.h"
33 #include "tree.h"
34 #include "toplev.h"
35 #include "java-tree.h"
36 #include "hashtab.h"
37 #if JCF_USE_SCANDIR
38 #include <dirent.h>
39 #include <fnmatch.h>
40 #endif
42 #include "zlib.h"
44 /* DOS brain-damage */
45 #ifndef O_BINARY
46 #define O_BINARY 0 /* MS-DOS brain-damage */
47 #endif
49 int
50 jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
52 if (jcf->filename)
53 fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
54 else
55 fprintf (stderr, "Premature end of .class file <stdin>.\n");
56 exit (-1);
59 void
60 jcf_trim_old_input (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 jcf_filbuf_from_stdio (JCF *jcf, int count)
74 FILE *file = (FILE*) (jcf->read_state);
75 if (count > jcf->buffer_end - jcf->read_ptr)
77 JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
78 JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
79 JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
80 JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
81 unsigned char *new_buffer = jcf->buffer == NULL ? ALLOC (new_size)
82 : REALLOC (jcf->buffer, new_size);
83 jcf->buffer = new_buffer;
84 jcf->buffer_end = new_buffer + new_size;
85 jcf->read_ptr = new_buffer + old_read_ptr;
86 jcf->read_end = new_buffer + old_read_end;
88 count -= jcf->read_end - jcf->read_ptr;
89 if (count <= 0)
90 return 0;
91 if ((int) fread (jcf->read_end, 1, count, file) != count)
92 jcf_unexpected_eof (jcf, count);
93 jcf->read_end += count;
94 return 0;
97 #include "zipfile.h"
99 struct ZipFile *SeenZipFiles = NULL;
101 /* Open a zip file with the given name, and cache directory and file
102 descriptor. If the file is missing, treat it as an empty archive.
103 Return NULL if the .zip file is malformed.
106 ZipFile *
107 opendir_in_zip (const char *zipfile, int is_system)
109 struct ZipFile* zipf;
110 char magic [4];
111 int fd;
112 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
114 if (strcmp (zipf->name, zipfile) == 0)
115 return zipf;
118 zipf = ALLOC (sizeof (struct ZipFile) + strlen (zipfile) + 1);
119 zipf->next = SeenZipFiles;
120 zipf->name = (char*)(zipf+1);
121 strcpy (zipf->name, zipfile);
122 fd = open (zipfile, O_RDONLY | O_BINARY);
123 zipf->fd = fd;
124 if (fd < 0)
126 /* A missing zip file is not considered an error.
127 We may want to re-consider that. FIXME. */
128 zipf->count = 0;
129 zipf->dir_size = 0;
130 zipf->central_directory = NULL;
132 else
134 jcf_dependency_add_file (zipfile, is_system);
135 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
137 free (zipf);
138 close (fd);
139 return NULL;
141 lseek (fd, 0L, SEEK_SET);
142 if (read_zip_archive (zipf) != 0)
144 free (zipf);
145 close (fd);
146 return NULL;
150 SeenZipFiles = zipf;
151 return zipf;
154 /* Returns:
155 0: OK - zipmember found.
156 -1: Not found.
157 -2: Malformed archive.
161 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
162 int is_system)
164 ZipDirectory *zipd;
165 int i, len;
166 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
168 if (zipf == NULL)
169 return -2;
171 if (!zipmember)
172 return 0;
174 len = strlen (zipmember);
176 zipd = (struct ZipDirectory*) zipf->central_directory;
177 for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
179 if (len == zipd->filename_length &&
180 strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
182 JCF_ZERO (jcf);
184 jcf->filename = xstrdup (zipfile);
185 jcf->classname = xstrdup (zipmember);
186 return read_zip_member(jcf, zipd, zipf);
189 return -1;
192 /* Read data from zip archive member. */
195 read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf)
197 jcf->filbuf = jcf_unexpected_eof;
198 jcf->zipd = zipd;
200 if (zipd->compression_method == Z_NO_COMPRESSION)
202 jcf->buffer = XNEWVEC (unsigned char, zipd->size);
203 jcf->buffer_end = jcf->buffer + zipd->size;
204 jcf->read_ptr = jcf->buffer;
205 jcf->read_end = jcf->buffer_end;
206 if (lseek (zipf->fd, zipd->filestart, 0) < 0
207 || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
208 return -2;
210 else
212 char *buffer;
213 z_stream d_stream; /* decompression stream */
214 d_stream.zalloc = (alloc_func) 0;
215 d_stream.zfree = (free_func) 0;
216 d_stream.opaque = (voidpf) 0;
218 jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
219 d_stream.next_out = jcf->buffer;
220 d_stream.avail_out = zipd->uncompressed_size;
221 jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
222 jcf->read_ptr = jcf->buffer;
223 jcf->read_end = jcf->buffer_end;
224 buffer = XNEWVEC (char, zipd->size);
225 d_stream.next_in = (unsigned char *) buffer;
226 d_stream.avail_in = zipd->size;
227 if (lseek (zipf->fd, zipd->filestart, 0) < 0
228 || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
229 return -2;
230 /* Handle NO_HEADER using undocumented zlib feature.
231 This is a very common hack. */
232 inflateInit2 (&d_stream, -MAX_WBITS);
233 inflate (&d_stream, Z_NO_FLUSH);
234 inflateEnd (&d_stream);
235 free (buffer);
238 return 0;
241 const char *
242 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
244 if (jcf)
246 struct stat stat_buf;
247 if (fstat (fd, &stat_buf) != 0
248 || ! S_ISREG (stat_buf.st_mode))
250 perror ("Could not figure length of .class file");
251 return NULL;
253 if (dep_name != NULL)
254 jcf_dependency_add_file (dep_name, 0);
255 JCF_ZERO (jcf);
256 jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
257 jcf->buffer_end = jcf->buffer + stat_buf.st_size;
258 jcf->read_ptr = jcf->buffer;
259 jcf->read_end = jcf->buffer_end;
260 jcf->read_state = NULL;
261 jcf->filename = xstrdup (filename);
262 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
264 perror ("Failed to read .class file");
265 return NULL;
267 close (fd);
268 jcf->filbuf = jcf_unexpected_eof;
270 else
271 close (fd);
272 return filename;
276 const char *
277 find_classfile (char *filename, JCF *jcf, const char *dep_name)
279 int fd = open (filename, O_RDONLY | O_BINARY);
280 if (fd < 0)
281 return NULL;
282 return open_class (filename, jcf, fd, dep_name);
285 #if JCF_USE_SCANDIR
287 /* A comparison function (as for qsort) that compares KEY (a char *
288 giving the basename of a file) with the name stored in ENTRY (a
289 dirent **). */
291 static int
292 compare_path (const void *key, const void *entry)
294 return strcmp ((const char *) key,
295 (*((const struct dirent *const*) entry))->d_name);
298 /* Returns nonzero if ENTRY names a .java or .class file. */
300 static int
301 java_or_class_file (const struct dirent *entry)
303 const char *base = lbasename (entry->d_name);
304 return (fnmatch ("*.java", base, 0) == 0 ||
305 fnmatch ("*.class", base, 0) == 0);
308 /* Information about the files present in a particular directory. */
309 typedef struct memoized_dirlist_entry
311 /* The name of the directory. */
312 const char *dir;
313 /* The number of .java and .class files present, or -1 if we could
314 not, for some reason, obtain the list. */
315 int num_files;
316 /* The .java and .class files in the directory, in alphabetical
317 order. */
318 struct dirent **files;
319 } memoized_dirlist_entry;
321 /* A hash function for a memoized_dirlist_entry. */
322 static hashval_t
323 memoized_dirlist_hash (const void *entry)
325 const memoized_dirlist_entry *mde = (const memoized_dirlist_entry *) entry;
326 return htab_hash_string (mde->dir);
329 /* Returns true if ENTRY (a memoized_dirlist_entry *) corresponds to
330 the directory given by KEY (a char *) giving the directory
331 name. */
333 static int
334 memoized_dirlist_lookup_eq (const void *entry, const void *key)
336 return strcmp ((const char *) key,
337 ((const memoized_dirlist_entry *) entry)->dir) == 0;
340 /* A hash table mapping directory names to the lists of .java and
341 .class files in that directory. */
343 static htab_t memoized_dirlists;
345 #endif
347 /* Like stat, but avoids actually making the stat system call if we
348 know that it cannot succeed. FILENAME and BUF are as for stat. */
350 static int
351 caching_stat (char *filename, struct stat *buf)
353 #if JCF_USE_SCANDIR
354 char *sep;
355 char origsep = 0;
356 char *base;
357 memoized_dirlist_entry *dent;
358 void **slot;
359 struct memoized_dirlist_entry temp;
361 /* If the hashtable has not already been created, create it now. */
362 if (!memoized_dirlists)
363 memoized_dirlists = htab_create (37,
364 memoized_dirlist_hash,
365 memoized_dirlist_lookup_eq,
366 NULL);
368 /* Get the name of the directory. */
369 sep = strrchr (filename, DIR_SEPARATOR);
370 #ifdef DIR_SEPARATOR_2
371 if (! sep)
372 sep = strrchr (filename, DIR_SEPARATOR_2);
373 #endif
374 if (sep)
376 origsep = *sep;
377 *sep = '\0';
378 base = sep + 1;
380 else
381 base = filename;
383 /* Obtain the entry for this directory from the hash table. This
384 approach is ok since we know that the hash function only looks at
385 the directory name. */
386 temp.dir = filename;
387 temp.num_files = 0;
388 temp.files = NULL;
389 slot = htab_find_slot (memoized_dirlists, &temp, INSERT);
390 if (!*slot)
392 /* We have not already scanned this directory; scan it now. */
393 dent = XNEW (memoized_dirlist_entry);
394 dent->dir = xstrdup (filename);
395 /* Unfortunately, scandir is not fully standardized. In
396 particular, the type of the function pointer passed as the
397 third argument sometimes takes a "const struct dirent *"
398 parameter, and sometimes just a "struct dirent *". We cast
399 to (void *) and use __extension__ so that either way it is
400 quietly accepted. FIXME: scandir is not in POSIX. */
401 dent->num_files = __extension__ scandir (filename, &dent->files,
402 (void *) java_or_class_file,
403 alphasort);
404 *slot = dent;
406 else
407 dent = *((memoized_dirlist_entry **) slot);
409 /* Put the separator back. */
410 if (sep)
411 *sep = origsep;
413 /* If the file is not in the list, there is no need to stat it; it
414 does not exist. */
415 if (dent->num_files != -1
416 && !bsearch (base, dent->files, dent->num_files,
417 sizeof (struct dirent *), compare_path))
418 return -1;
419 #endif
421 return stat (filename, buf);
424 /* Returns 1 if the CLASSNAME (really a char *) matches the name
425 stored in TABLE_ENTRY (also a char *). */
427 static int
428 memoized_class_lookup_eq (const void *table_entry, const void *classname)
430 return strcmp ((const char *)classname, (const char *)table_entry) == 0;
433 /* A hash table keeping track of class names that were not found
434 during class lookup. (There is no need to cache the values
435 associated with names that were found; they are saved in
436 IDENTIFIER_CLASS_VALUE.) */
437 static htab_t memoized_class_lookups;
439 /* Returns a freshly malloc'd string with the fully qualified pathname
440 of the .class file for the class CLASSNAME. CLASSNAME must be
441 allocated in permanent storage; this function may retain a pointer
442 to it. Returns NULL on failure. If JCF != NULL, it is suitably
443 initialized. SOURCE_OK is true if we should also look for .java
444 file. */
446 const char *
447 find_class (const char *classname, int classname_length, JCF *jcf)
449 int fd;
450 int i, k, class = -1;
451 struct stat class_buf;
452 char *dep_file;
453 void *entry;
454 int buflen;
455 char *buffer;
456 hashval_t hash;
458 /* Create the hash table, if it does not already exist. */
459 if (!memoized_class_lookups)
460 memoized_class_lookups = htab_create (37,
461 htab_hash_string,
462 memoized_class_lookup_eq,
463 NULL);
465 /* Loop for this class in the hashtable. If it is present, we've
466 already looked for this class and failed to find it. */
467 hash = htab_hash_string (classname);
468 if (htab_find_with_hash (memoized_class_lookups, classname, hash))
469 return NULL;
471 /* Allocate and zero out the buffer, since we don't explicitly put a
472 null pointer when we're copying it below. */
473 buflen = jcf_path_max_len () + classname_length + 10;
474 buffer = ALLOC (buflen);
475 memset (buffer, 0, buflen);
477 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
479 const char *path_name = jcf_path_name (entry);
480 if (class != 0)
482 int dir_len;
484 strcpy (buffer, path_name);
485 i = strlen (buffer);
487 /* This is right because we know that `.zip' entries will have a
488 trailing slash. See jcf-path.c. */
489 dir_len = i - 1;
491 for (k = 0; k < classname_length; k++, i++)
493 char ch = classname[k];
494 buffer[i] = ch == '.' ? '/' : ch;
496 strcpy (buffer+i, ".class");
498 if (jcf_path_is_zipfile (entry))
500 int err_code;
501 JCF _jcf;
502 buffer[dir_len] = '\0';
503 SOURCE_FRONTEND_DEBUG
504 (("Trying [...%s]:%s",
505 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
506 buffer+dir_len+1));
507 if (jcf == NULL)
508 jcf = &_jcf;
509 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
510 jcf_path_is_system (entry));
511 if (err_code == 0)
513 /* Should we check if .zip is out-of-date wrt .java? */
514 buffer[dir_len] = '(';
515 strcpy (buffer+i, ".class)");
516 if (jcf == &_jcf)
517 JCF_FINISH (jcf);
518 return buffer;
520 else
521 continue;
523 class = caching_stat(buffer, &class_buf);
527 dep_file = buffer;
528 if (!class)
530 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
531 classname+classname_length-
532 (classname_length <= 30 ?
533 classname_length : 30)));
534 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
535 if (fd >= 0)
536 goto found;
539 free (buffer);
541 /* Remember that this class could not be found so that we do not
542 have to look again. */
543 *(const void **)htab_find_slot_with_hash (memoized_class_lookups,
544 classname, hash, INSERT)
545 = classname;
547 return NULL;
548 found:
550 const char *const tmp = open_class (buffer, jcf, fd, dep_file);
551 jcf->classname = xstrdup (classname);
552 return tmp;
556 void
557 jcf_print_char (FILE *stream, int ch)
559 switch (ch)
561 case '\'':
562 case '\\':
563 case '\"':
564 fprintf (stream, "\\%c", ch);
565 break;
566 case '\n':
567 fprintf (stream, "\\n");
568 break;
569 case '\t':
570 fprintf (stream, "\\t");
571 break;
572 case '\r':
573 fprintf (stream, "\\r");
574 break;
575 default:
576 if (ch >= ' ' && ch < 127)
577 putc (ch, stream);
578 else if (ch < 256)
579 fprintf (stream, "\\%03x", ch);
580 else
581 fprintf (stream, "\\u%04x", ch);
585 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
587 void
588 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
590 const unsigned char * limit = str + length;
591 while (str < limit)
593 int ch = UTF8_GET (str, limit);
594 if (ch < 0)
596 fprintf (stream, "\\<invalid>");
597 return;
599 jcf_print_char (stream, ch);
603 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
605 void
606 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
607 int in_char, int out_char)
609 const unsigned char *limit = str + length;
610 while (str < limit)
612 int ch = UTF8_GET (str, limit);
613 if (ch < 0)
615 fprintf (stream, "\\<invalid>");
616 return;
618 jcf_print_char (stream, ch == in_char ? out_char : ch);
622 /* Check that all the cross-references in the constant pool are
623 valid. Returns 0 on success.
624 Otherwise, returns the index of the (first) invalid entry.
625 Only checks internal consistency, but does not check that
626 any classes, fields, or methods are valid.*/
629 verify_constant_pool (JCF *jcf)
631 int i, n;
632 for (i = 1; i < JPOOL_SIZE (jcf); i++)
634 switch (JPOOL_TAG (jcf, i))
636 case CONSTANT_NameAndType:
637 n = JPOOL_USHORT2 (jcf, i);
638 if (n <= 0 || n >= JPOOL_SIZE(jcf)
639 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
640 return i;
641 /* ... fall through ... */
642 case CONSTANT_Class:
643 case CONSTANT_String:
644 n = JPOOL_USHORT1 (jcf, i);
645 if (n <= 0 || n >= JPOOL_SIZE(jcf)
646 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
647 return i;
648 break;
649 case CONSTANT_Fieldref:
650 case CONSTANT_Methodref:
651 case CONSTANT_InterfaceMethodref:
652 n = JPOOL_USHORT1 (jcf, i);
653 if (n <= 0 || n >= JPOOL_SIZE(jcf)
654 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
655 return i;
656 n = JPOOL_USHORT2 (jcf, i);
657 if (n <= 0 || n >= JPOOL_SIZE(jcf)
658 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
659 return i;
660 break;
661 case CONSTANT_Long:
662 case CONSTANT_Double:
663 i++;
664 break;
665 case CONSTANT_Float:
666 case CONSTANT_Integer:
667 case CONSTANT_Utf8:
668 case CONSTANT_Unicode:
669 break;
670 default:
671 return i;
674 return 0;
677 void
678 format_uint (char *buffer, uint64 value, int base)
680 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
681 char buf[WRITE_BUF_SIZE];
682 char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
683 int chars_written;
684 int i;
686 /* Now do the actual conversion, placing the result at the *end* of buf. */
687 /* Note this code does not pretend to be optimized. */
688 do {
689 int digit = value % base;
690 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
691 *--buf_ptr = digit_chars[digit];
692 value /= base;
693 } while (value != 0);
695 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
696 for (i = 0; i < chars_written; i++)
697 buffer[i] = *buf_ptr++;
698 buffer[i] = 0;
701 void
702 format_int (char *buffer, jlong value, int base)
704 uint64 abs_value;
705 if (value < 0)
707 abs_value = -(uint64)value;
708 *buffer++ = '-';
710 else
711 abs_value = (uint64) value;
712 format_uint (buffer, abs_value, base);