2014-11-20 Robert Dewar <dewar@adacore.com>
[official-gcc.git] / gcc / java / jcf-io.c
blob358fc1e47c1dea2226f99e742b2e7449c4b188ac
1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996-2014 Free Software Foundation, Inc.
4 This file is part of GCC.
6 GCC is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
11 GCC is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GCC; see the file COPYING3. If not see
18 <http://www.gnu.org/licenses/>.
20 Java and all Java-based marks are trademarks or registered trademarks
21 of Sun Microsystems, Inc. in the United States and other countries.
22 The Free Software Foundation is independent of Sun Microsystems, Inc. */
24 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
26 #include "config.h"
27 #include "system.h"
28 #include "coretypes.h"
30 #include "jcf.h"
31 #include "tree.h"
32 #include "java-tree.h"
33 #include "hash-table.h"
34 #include <dirent.h>
36 #include "zlib.h"
38 int
39 jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
41 if (jcf->filename)
42 fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
43 else
44 fprintf (stderr, "Premature end of .class file <stdin>.\n");
45 exit (-1);
48 void
49 jcf_trim_old_input (JCF *jcf)
51 int count = jcf->read_ptr - jcf->buffer;
52 if (count > 0)
54 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
55 jcf->read_ptr -= count;
56 jcf->read_end -= count;
60 int
61 jcf_filbuf_from_stdio (JCF *jcf, int count)
63 FILE *file = (FILE*) (jcf->read_state);
64 if (count > jcf->buffer_end - jcf->read_ptr)
66 JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
67 JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
68 JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
69 JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
70 unsigned char *new_buffer
71 = jcf->buffer == NULL ? XNEWVAR (unsigned char, new_size)
72 : XRESIZEVAR (unsigned char, jcf->buffer, new_size);
73 jcf->buffer = new_buffer;
74 jcf->buffer_end = new_buffer + new_size;
75 jcf->read_ptr = new_buffer + old_read_ptr;
76 jcf->read_end = new_buffer + old_read_end;
78 count -= jcf->read_end - jcf->read_ptr;
79 if (count <= 0)
80 return 0;
81 if ((int) fread (jcf->read_end, 1, count, file) != count)
82 jcf_unexpected_eof (jcf, count);
83 jcf->read_end += count;
84 return 0;
87 #include "zipfile.h"
89 struct ZipFile *SeenZipFiles = NULL;
91 /* Open a zip file with the given name, and cache directory and file
92 descriptor. If the file is missing, treat it as an empty archive.
93 Return NULL if the .zip file is malformed.
96 ZipFile *
97 opendir_in_zip (const char *zipfile, int is_system)
99 struct ZipFile* zipf;
100 char magic [4];
101 int fd;
102 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
104 if (strcmp (zipf->name, zipfile) == 0)
105 return zipf;
108 zipf = XNEWVAR (struct ZipFile, sizeof (struct ZipFile) + strlen (zipfile) + 1);
109 zipf->next = SeenZipFiles;
110 zipf->name = (char*)(zipf+1);
111 strcpy (zipf->name, zipfile);
112 fd = open (zipfile, O_RDONLY | O_BINARY);
113 zipf->fd = fd;
114 if (fd < 0)
116 /* A missing zip file is not considered an error.
117 We may want to re-consider that. FIXME. */
118 zipf->count = 0;
119 zipf->dir_size = 0;
120 zipf->central_directory = NULL;
122 else
124 jcf_dependency_add_file (zipfile, is_system);
125 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
127 free (zipf);
128 close (fd);
129 return NULL;
131 lseek (fd, 0L, SEEK_SET);
132 if (read_zip_archive (zipf) != 0)
134 free (zipf);
135 close (fd);
136 return NULL;
140 SeenZipFiles = zipf;
141 return zipf;
144 /* Returns:
145 0: OK - zipmember found.
146 -1: Not found.
147 -2: Malformed archive.
151 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
152 int is_system)
154 ZipDirectory *zipd;
155 int i, len;
156 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
158 if (zipf == NULL)
159 return -2;
161 if (!zipmember)
162 return 0;
164 len = strlen (zipmember);
166 zipd = (struct ZipDirectory*) zipf->central_directory;
167 for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
169 if (len == zipd->filename_length &&
170 strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
172 JCF_ZERO (jcf);
174 jcf->filename = xstrdup (zipfile);
175 jcf->classname = xstrdup (zipmember);
176 return read_zip_member(jcf, zipd, zipf);
179 return -1;
182 /* Read data from zip archive member. */
185 read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf)
187 jcf->filbuf = jcf_unexpected_eof;
188 jcf->zipd = zipd;
190 if (zipd->compression_method == Z_NO_COMPRESSION)
192 jcf->buffer = XNEWVEC (unsigned char, zipd->size);
193 jcf->buffer_end = jcf->buffer + zipd->size;
194 jcf->read_ptr = jcf->buffer;
195 jcf->read_end = jcf->buffer_end;
196 if (lseek (zipf->fd, zipd->filestart, 0) < 0
197 || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
198 return -2;
200 else
202 char *buffer;
203 z_stream d_stream; /* decompression stream */
204 memset (&d_stream, 0, sizeof (d_stream));
206 jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
207 d_stream.next_out = jcf->buffer;
208 d_stream.avail_out = zipd->uncompressed_size;
209 jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
210 jcf->read_ptr = jcf->buffer;
211 jcf->read_end = jcf->buffer_end;
212 buffer = XNEWVEC (char, zipd->size);
213 d_stream.next_in = (unsigned char *) buffer;
214 d_stream.avail_in = zipd->size;
215 if (lseek (zipf->fd, zipd->filestart, 0) < 0
216 || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
217 return -2;
218 /* Handle NO_HEADER using undocumented zlib feature.
219 This is a very common hack. */
220 inflateInit2 (&d_stream, -MAX_WBITS);
221 inflate (&d_stream, Z_NO_FLUSH);
222 inflateEnd (&d_stream);
223 free (buffer);
226 return 0;
229 const char *
230 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
232 if (jcf)
234 struct stat stat_buf;
235 if (fstat (fd, &stat_buf) != 0
236 || ! S_ISREG (stat_buf.st_mode))
238 perror ("Could not figure length of .class file");
239 return NULL;
241 if (dep_name != NULL)
242 jcf_dependency_add_file (dep_name, 0);
243 JCF_ZERO (jcf);
244 jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
245 jcf->buffer_end = jcf->buffer + stat_buf.st_size;
246 jcf->read_ptr = jcf->buffer;
247 jcf->read_end = jcf->buffer_end;
248 jcf->read_state = NULL;
249 jcf->filename = xstrdup (filename);
250 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
252 perror ("Failed to read .class file");
253 return NULL;
255 close (fd);
256 jcf->filbuf = jcf_unexpected_eof;
258 else
259 close (fd);
260 return filename;
264 const char *
265 find_classfile (char *filename, JCF *jcf, const char *dep_name)
267 int fd = open (filename, O_RDONLY | O_BINARY);
268 if (fd < 0)
269 return NULL;
270 return open_class (filename, jcf, fd, dep_name);
274 /* Hash table helper. */
276 struct charstar_hash : typed_noop_remove <char>
278 typedef const char value_type;
279 typedef const char compare_type;
280 static inline hashval_t hash (const value_type *candidate);
281 static inline bool equal (const value_type *existing,
282 const compare_type *candidate);
285 inline hashval_t
286 charstar_hash::hash (const value_type *candidate)
288 return htab_hash_string (candidate);
291 inline bool
292 charstar_hash::equal (const value_type *existing, const compare_type *candidate)
294 return strcmp (existing, candidate) == 0;
298 /* A hash table keeping track of class names that were not found
299 during class lookup. (There is no need to cache the values
300 associated with names that were found; they are saved in
301 IDENTIFIER_CLASS_VALUE.) */
302 static hash_table<charstar_hash> *memoized_class_lookups;
304 /* Returns a freshly malloc'd string with the fully qualified pathname
305 of the .class file for the class CLASSNAME. CLASSNAME must be
306 allocated in permanent storage; this function may retain a pointer
307 to it. Returns NULL on failure. If JCF != NULL, it is suitably
308 initialized. SOURCE_OK is true if we should also look for .java
309 file. */
311 const char *
312 find_class (const char *classname, int classname_length, JCF *jcf)
314 int fd;
315 int i, k, klass = -1;
316 struct stat class_buf;
317 char *dep_file;
318 void *entry;
319 int buflen;
320 char *buffer;
321 hashval_t hash;
323 /* Create the hash table, if it does not already exist. */
324 if (!memoized_class_lookups)
325 memoized_class_lookups = new hash_table<charstar_hash> (37);
327 /* Loop for this class in the hashtable. If it is present, we've
328 already looked for this class and failed to find it. */
329 hash = charstar_hash::hash (classname);
330 if (memoized_class_lookups->find_with_hash (classname, hash))
331 return NULL;
333 /* Allocate and zero out the buffer, since we don't explicitly put a
334 null pointer when we're copying it below. */
335 buflen = jcf_path_max_len () + classname_length + 10;
336 buffer = XNEWVAR (char, buflen);
337 memset (buffer, 0, buflen);
339 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
341 const char *path_name = jcf_path_name (entry);
342 if (klass != 0)
344 int dir_len;
346 strcpy (buffer, path_name);
347 i = strlen (buffer);
349 /* This is right because we know that `.zip' entries will have a
350 trailing slash. See jcf-path.c. */
351 dir_len = i - 1;
353 for (k = 0; k < classname_length; k++, i++)
355 char ch = classname[k];
356 buffer[i] = ch == '.' ? '/' : ch;
358 strcpy (buffer+i, ".class");
360 if (jcf_path_is_zipfile (entry))
362 int err_code;
363 JCF _jcf;
364 buffer[dir_len] = '\0';
365 SOURCE_FRONTEND_DEBUG
366 (("Trying [...%s]:%s",
367 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
368 buffer+dir_len+1));
369 if (jcf == NULL)
370 jcf = &_jcf;
371 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
372 jcf_path_is_system (entry));
373 if (err_code == 0)
375 /* Should we check if .zip is out-of-date wrt .java? */
376 buffer[dir_len] = '(';
377 strcpy (buffer+i, ".class)");
378 if (jcf == &_jcf)
379 JCF_FINISH (jcf);
380 return buffer;
382 else
383 continue;
385 klass = stat (buffer, &class_buf);
389 dep_file = buffer;
390 if (!klass)
392 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
393 classname+classname_length-
394 (classname_length <= 30 ?
395 classname_length : 30)));
396 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
397 if (fd >= 0)
398 goto found;
401 free (buffer);
403 /* Remember that this class could not be found so that we do not
404 have to look again. */
405 *memoized_class_lookups->find_slot_with_hash (classname, hash, INSERT)
406 = classname;
408 return NULL;
409 found:
411 const char *const tmp = open_class (buffer, jcf, fd, dep_file);
412 jcf->classname = xstrdup (classname);
413 return tmp;
417 void
418 jcf_print_char (FILE *stream, int ch)
420 switch (ch)
422 case '\'':
423 case '\\':
424 case '\"':
425 fprintf (stream, "\\%c", ch);
426 break;
427 case '\n':
428 fprintf (stream, "\\n");
429 break;
430 case '\t':
431 fprintf (stream, "\\t");
432 break;
433 case '\r':
434 fprintf (stream, "\\r");
435 break;
436 default:
437 if (ch >= ' ' && ch < 127)
438 putc (ch, stream);
439 else if (ch < 256)
440 fprintf (stream, "\\%03x", ch);
441 else
442 fprintf (stream, "\\u%04x", ch);
446 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
448 void
449 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
451 const unsigned char * limit = str + length;
452 while (str < limit)
454 int ch = UTF8_GET (str, limit);
455 if (ch < 0)
457 fprintf (stream, "\\<invalid>");
458 return;
460 jcf_print_char (stream, ch);
464 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
466 void
467 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
468 int in_char, int out_char)
470 const unsigned char *limit = str + length;
471 while (str < limit)
473 int ch = UTF8_GET (str, limit);
474 if (ch < 0)
476 fprintf (stream, "\\<invalid>");
477 return;
479 jcf_print_char (stream, ch == in_char ? out_char : ch);
483 /* Check that all the cross-references in the constant pool are
484 valid. Returns 0 on success.
485 Otherwise, returns the index of the (first) invalid entry.
486 Only checks internal consistency, but does not check that
487 any classes, fields, or methods are valid.*/
490 verify_constant_pool (JCF *jcf)
492 int i, n;
493 for (i = 1; i < JPOOL_SIZE (jcf); i++)
495 switch (JPOOL_TAG (jcf, i))
497 case CONSTANT_NameAndType:
498 n = JPOOL_USHORT2 (jcf, i);
499 if (n <= 0 || n >= JPOOL_SIZE(jcf)
500 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
501 return i;
502 /* ... fall through ... */
503 case CONSTANT_Class:
504 case CONSTANT_String:
505 n = JPOOL_USHORT1 (jcf, i);
506 if (n <= 0 || n >= JPOOL_SIZE(jcf)
507 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
508 return i;
509 break;
510 case CONSTANT_Fieldref:
511 case CONSTANT_Methodref:
512 case CONSTANT_InterfaceMethodref:
513 n = JPOOL_USHORT1 (jcf, i);
514 if (n <= 0 || n >= JPOOL_SIZE(jcf)
515 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
516 return i;
517 n = JPOOL_USHORT2 (jcf, i);
518 if (n <= 0 || n >= JPOOL_SIZE(jcf)
519 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
520 return i;
521 break;
522 case CONSTANT_Long:
523 case CONSTANT_Double:
524 i++;
525 break;
526 case CONSTANT_Float:
527 case CONSTANT_Integer:
528 case CONSTANT_Utf8:
529 case CONSTANT_Unicode:
530 break;
531 case CONSTANT_MethodHandle:
532 n = JPOOL_USHORT1 (jcf, i);
533 if (n < 1 || n > 9)
534 return i;
535 n = JPOOL_USHORT2 (jcf, i);
536 if (n <= 0 || n >= JPOOL_SIZE(jcf))
537 return i;
538 break;
539 case CONSTANT_MethodType:
540 n = JPOOL_USHORT1 (jcf, i);
541 if (n <= 0 || n >= JPOOL_SIZE(jcf)
542 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
543 return i;
544 break;
545 case CONSTANT_InvokeDynamic:
546 n = JPOOL_USHORT2 (jcf, i);
547 if (n <= 0 || n >= JPOOL_SIZE(jcf)
548 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
549 return i;
550 break;
551 default:
552 return i;
555 return 0;
558 void
559 format_uint (char *buffer, uint64 value, int base)
561 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
562 char buf[WRITE_BUF_SIZE];
563 char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
564 int chars_written;
565 int i;
567 /* Now do the actual conversion, placing the result at the *end* of buf. */
568 /* Note this code does not pretend to be optimized. */
569 do {
570 int digit = value % base;
571 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
572 *--buf_ptr = digit_chars[digit];
573 value /= base;
574 } while (value != 0);
576 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
577 for (i = 0; i < chars_written; i++)
578 buffer[i] = *buf_ptr++;
579 buffer[i] = 0;
582 void
583 format_int (char *buffer, jlong value, int base)
585 uint64 abs_value;
586 if (value < 0)
588 abs_value = -(uint64)value;
589 *buffer++ = '-';
591 else
592 abs_value = (uint64) value;
593 format_uint (buffer, abs_value, base);