Merge from mainline (165734:167278).
[official-gcc/graphite-test-results.git] / gcc / java / jcf-io.c
blob0dc761534c6132b6f068fa46075475349c03d6cc
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, 2008, 2009, 2010 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"
31 #include "jcf.h"
32 #include "tree.h"
33 #include "java-tree.h"
34 #include "hashtab.h"
35 #include <dirent.h>
37 #include "zlib.h"
39 int
40 jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
42 if (jcf->filename)
43 fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
44 else
45 fprintf (stderr, "Premature end of .class file <stdin>.\n");
46 exit (-1);
49 void
50 jcf_trim_old_input (JCF *jcf)
52 int count = jcf->read_ptr - jcf->buffer;
53 if (count > 0)
55 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
56 jcf->read_ptr -= count;
57 jcf->read_end -= count;
61 int
62 jcf_filbuf_from_stdio (JCF *jcf, int count)
64 FILE *file = (FILE*) (jcf->read_state);
65 if (count > jcf->buffer_end - jcf->read_ptr)
67 JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
68 JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
69 JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
70 JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
71 unsigned char *new_buffer
72 = jcf->buffer == NULL ? XNEWVAR (unsigned char, new_size)
73 : XRESIZEVAR (unsigned char, jcf->buffer, new_size);
74 jcf->buffer = new_buffer;
75 jcf->buffer_end = new_buffer + new_size;
76 jcf->read_ptr = new_buffer + old_read_ptr;
77 jcf->read_end = new_buffer + old_read_end;
79 count -= jcf->read_end - jcf->read_ptr;
80 if (count <= 0)
81 return 0;
82 if ((int) fread (jcf->read_end, 1, count, file) != count)
83 jcf_unexpected_eof (jcf, count);
84 jcf->read_end += count;
85 return 0;
88 #include "zipfile.h"
90 struct ZipFile *SeenZipFiles = NULL;
92 /* Open a zip file with the given name, and cache directory and file
93 descriptor. If the file is missing, treat it as an empty archive.
94 Return NULL if the .zip file is malformed.
97 ZipFile *
98 opendir_in_zip (const char *zipfile, int is_system)
100 struct ZipFile* zipf;
101 char magic [4];
102 int fd;
103 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
105 if (strcmp (zipf->name, zipfile) == 0)
106 return zipf;
109 zipf = XNEWVAR (struct ZipFile, sizeof (struct ZipFile) + strlen (zipfile) + 1);
110 zipf->next = SeenZipFiles;
111 zipf->name = (char*)(zipf+1);
112 strcpy (zipf->name, zipfile);
113 fd = open (zipfile, O_RDONLY | O_BINARY);
114 zipf->fd = fd;
115 if (fd < 0)
117 /* A missing zip file is not considered an error.
118 We may want to re-consider that. FIXME. */
119 zipf->count = 0;
120 zipf->dir_size = 0;
121 zipf->central_directory = NULL;
123 else
125 jcf_dependency_add_file (zipfile, is_system);
126 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
128 free (zipf);
129 close (fd);
130 return NULL;
132 lseek (fd, 0L, SEEK_SET);
133 if (read_zip_archive (zipf) != 0)
135 free (zipf);
136 close (fd);
137 return NULL;
141 SeenZipFiles = zipf;
142 return zipf;
145 /* Returns:
146 0: OK - zipmember found.
147 -1: Not found.
148 -2: Malformed archive.
152 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
153 int is_system)
155 ZipDirectory *zipd;
156 int i, len;
157 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
159 if (zipf == NULL)
160 return -2;
162 if (!zipmember)
163 return 0;
165 len = strlen (zipmember);
167 zipd = (struct ZipDirectory*) zipf->central_directory;
168 for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
170 if (len == zipd->filename_length &&
171 strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
173 JCF_ZERO (jcf);
175 jcf->filename = xstrdup (zipfile);
176 jcf->classname = xstrdup (zipmember);
177 return read_zip_member(jcf, zipd, zipf);
180 return -1;
183 /* Read data from zip archive member. */
186 read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf)
188 jcf->filbuf = jcf_unexpected_eof;
189 jcf->zipd = zipd;
191 if (zipd->compression_method == Z_NO_COMPRESSION)
193 jcf->buffer = XNEWVEC (unsigned char, zipd->size);
194 jcf->buffer_end = jcf->buffer + zipd->size;
195 jcf->read_ptr = jcf->buffer;
196 jcf->read_end = jcf->buffer_end;
197 if (lseek (zipf->fd, zipd->filestart, 0) < 0
198 || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
199 return -2;
201 else
203 char *buffer;
204 z_stream d_stream; /* decompression stream */
205 d_stream.zalloc = (alloc_func) 0;
206 d_stream.zfree = (free_func) 0;
207 d_stream.opaque = (voidpf) 0;
209 jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
210 d_stream.next_out = jcf->buffer;
211 d_stream.avail_out = zipd->uncompressed_size;
212 jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
213 jcf->read_ptr = jcf->buffer;
214 jcf->read_end = jcf->buffer_end;
215 buffer = XNEWVEC (char, zipd->size);
216 d_stream.next_in = (unsigned char *) buffer;
217 d_stream.avail_in = zipd->size;
218 if (lseek (zipf->fd, zipd->filestart, 0) < 0
219 || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
220 return -2;
221 /* Handle NO_HEADER using undocumented zlib feature.
222 This is a very common hack. */
223 inflateInit2 (&d_stream, -MAX_WBITS);
224 inflate (&d_stream, Z_NO_FLUSH);
225 inflateEnd (&d_stream);
226 free (buffer);
229 return 0;
232 const char *
233 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
235 if (jcf)
237 struct stat stat_buf;
238 if (fstat (fd, &stat_buf) != 0
239 || ! S_ISREG (stat_buf.st_mode))
241 perror ("Could not figure length of .class file");
242 return NULL;
244 if (dep_name != NULL)
245 jcf_dependency_add_file (dep_name, 0);
246 JCF_ZERO (jcf);
247 jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
248 jcf->buffer_end = jcf->buffer + stat_buf.st_size;
249 jcf->read_ptr = jcf->buffer;
250 jcf->read_end = jcf->buffer_end;
251 jcf->read_state = NULL;
252 jcf->filename = xstrdup (filename);
253 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
255 perror ("Failed to read .class file");
256 return NULL;
258 close (fd);
259 jcf->filbuf = jcf_unexpected_eof;
261 else
262 close (fd);
263 return filename;
267 const char *
268 find_classfile (char *filename, JCF *jcf, const char *dep_name)
270 int fd = open (filename, O_RDONLY | O_BINARY);
271 if (fd < 0)
272 return NULL;
273 return open_class (filename, jcf, fd, dep_name);
276 /* Returns 1 if the CLASSNAME (really a char *) matches the name
277 stored in TABLE_ENTRY (also a char *). */
279 static int
280 memoized_class_lookup_eq (const void *table_entry, const void *classname)
282 return strcmp ((const char *)classname, (const char *)table_entry) == 0;
285 /* A hash table keeping track of class names that were not found
286 during class lookup. (There is no need to cache the values
287 associated with names that were found; they are saved in
288 IDENTIFIER_CLASS_VALUE.) */
289 static htab_t memoized_class_lookups;
291 /* Returns a freshly malloc'd string with the fully qualified pathname
292 of the .class file for the class CLASSNAME. CLASSNAME must be
293 allocated in permanent storage; this function may retain a pointer
294 to it. Returns NULL on failure. If JCF != NULL, it is suitably
295 initialized. SOURCE_OK is true if we should also look for .java
296 file. */
298 const char *
299 find_class (const char *classname, int classname_length, JCF *jcf)
301 int fd;
302 int i, k, klass = -1;
303 struct stat class_buf;
304 char *dep_file;
305 void *entry;
306 int buflen;
307 char *buffer;
308 hashval_t hash;
310 /* Create the hash table, if it does not already exist. */
311 if (!memoized_class_lookups)
312 memoized_class_lookups = htab_create (37,
313 htab_hash_string,
314 memoized_class_lookup_eq,
315 NULL);
317 /* Loop for this class in the hashtable. If it is present, we've
318 already looked for this class and failed to find it. */
319 hash = htab_hash_string (classname);
320 if (htab_find_with_hash (memoized_class_lookups, classname, hash))
321 return NULL;
323 /* Allocate and zero out the buffer, since we don't explicitly put a
324 null pointer when we're copying it below. */
325 buflen = jcf_path_max_len () + classname_length + 10;
326 buffer = XNEWVAR (char, buflen);
327 memset (buffer, 0, buflen);
329 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
331 const char *path_name = jcf_path_name (entry);
332 if (klass != 0)
334 int dir_len;
336 strcpy (buffer, path_name);
337 i = strlen (buffer);
339 /* This is right because we know that `.zip' entries will have a
340 trailing slash. See jcf-path.c. */
341 dir_len = i - 1;
343 for (k = 0; k < classname_length; k++, i++)
345 char ch = classname[k];
346 buffer[i] = ch == '.' ? '/' : ch;
348 strcpy (buffer+i, ".class");
350 if (jcf_path_is_zipfile (entry))
352 int err_code;
353 JCF _jcf;
354 buffer[dir_len] = '\0';
355 SOURCE_FRONTEND_DEBUG
356 (("Trying [...%s]:%s",
357 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
358 buffer+dir_len+1));
359 if (jcf == NULL)
360 jcf = &_jcf;
361 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
362 jcf_path_is_system (entry));
363 if (err_code == 0)
365 /* Should we check if .zip is out-of-date wrt .java? */
366 buffer[dir_len] = '(';
367 strcpy (buffer+i, ".class)");
368 if (jcf == &_jcf)
369 JCF_FINISH (jcf);
370 return buffer;
372 else
373 continue;
375 klass = stat (buffer, &class_buf);
379 dep_file = buffer;
380 if (!klass)
382 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
383 classname+classname_length-
384 (classname_length <= 30 ?
385 classname_length : 30)));
386 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
387 if (fd >= 0)
388 goto found;
391 free (buffer);
393 /* Remember that this class could not be found so that we do not
394 have to look again. */
395 *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT)
396 = (void *) CONST_CAST (char *, classname);
398 return NULL;
399 found:
401 const char *const tmp = open_class (buffer, jcf, fd, dep_file);
402 jcf->classname = xstrdup (classname);
403 return tmp;
407 void
408 jcf_print_char (FILE *stream, int ch)
410 switch (ch)
412 case '\'':
413 case '\\':
414 case '\"':
415 fprintf (stream, "\\%c", ch);
416 break;
417 case '\n':
418 fprintf (stream, "\\n");
419 break;
420 case '\t':
421 fprintf (stream, "\\t");
422 break;
423 case '\r':
424 fprintf (stream, "\\r");
425 break;
426 default:
427 if (ch >= ' ' && ch < 127)
428 putc (ch, stream);
429 else if (ch < 256)
430 fprintf (stream, "\\%03x", ch);
431 else
432 fprintf (stream, "\\u%04x", ch);
436 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
438 void
439 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
441 const unsigned char * limit = str + length;
442 while (str < limit)
444 int ch = UTF8_GET (str, limit);
445 if (ch < 0)
447 fprintf (stream, "\\<invalid>");
448 return;
450 jcf_print_char (stream, ch);
454 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
456 void
457 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
458 int in_char, int out_char)
460 const unsigned char *limit = str + length;
461 while (str < limit)
463 int ch = UTF8_GET (str, limit);
464 if (ch < 0)
466 fprintf (stream, "\\<invalid>");
467 return;
469 jcf_print_char (stream, ch == in_char ? out_char : ch);
473 /* Check that all the cross-references in the constant pool are
474 valid. Returns 0 on success.
475 Otherwise, returns the index of the (first) invalid entry.
476 Only checks internal consistency, but does not check that
477 any classes, fields, or methods are valid.*/
480 verify_constant_pool (JCF *jcf)
482 int i, n;
483 for (i = 1; i < JPOOL_SIZE (jcf); i++)
485 switch (JPOOL_TAG (jcf, i))
487 case CONSTANT_NameAndType:
488 n = JPOOL_USHORT2 (jcf, i);
489 if (n <= 0 || n >= JPOOL_SIZE(jcf)
490 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
491 return i;
492 /* ... fall through ... */
493 case CONSTANT_Class:
494 case CONSTANT_String:
495 n = JPOOL_USHORT1 (jcf, i);
496 if (n <= 0 || n >= JPOOL_SIZE(jcf)
497 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
498 return i;
499 break;
500 case CONSTANT_Fieldref:
501 case CONSTANT_Methodref:
502 case CONSTANT_InterfaceMethodref:
503 n = JPOOL_USHORT1 (jcf, i);
504 if (n <= 0 || n >= JPOOL_SIZE(jcf)
505 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
506 return i;
507 n = JPOOL_USHORT2 (jcf, i);
508 if (n <= 0 || n >= JPOOL_SIZE(jcf)
509 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
510 return i;
511 break;
512 case CONSTANT_Long:
513 case CONSTANT_Double:
514 i++;
515 break;
516 case CONSTANT_Float:
517 case CONSTANT_Integer:
518 case CONSTANT_Utf8:
519 case CONSTANT_Unicode:
520 break;
521 default:
522 return i;
525 return 0;
528 void
529 format_uint (char *buffer, uint64 value, int base)
531 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
532 char buf[WRITE_BUF_SIZE];
533 char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
534 int chars_written;
535 int i;
537 /* Now do the actual conversion, placing the result at the *end* of buf. */
538 /* Note this code does not pretend to be optimized. */
539 do {
540 int digit = value % base;
541 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
542 *--buf_ptr = digit_chars[digit];
543 value /= base;
544 } while (value != 0);
546 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
547 for (i = 0; i < chars_written; i++)
548 buffer[i] = *buf_ptr++;
549 buffer[i] = 0;
552 void
553 format_int (char *buffer, jlong value, int base)
555 uint64 abs_value;
556 if (value < 0)
558 abs_value = -(uint64)value;
559 *buffer++ = '-';
561 else
562 abs_value = (uint64) value;
563 format_uint (buffer, abs_value, base);