Daily bump.
[official-gcc.git] / gcc / java / jcf-io.c
blob87d194279b40cb50efd81f0f2195253a161f673e
1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996-2015 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 "alias.h"
32 #include "tree.h"
33 #include "options.h"
34 #include "java-tree.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 memset (&d_stream, 0, sizeof (d_stream));
207 jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
208 d_stream.next_out = jcf->buffer;
209 d_stream.avail_out = zipd->uncompressed_size;
210 jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
211 jcf->read_ptr = jcf->buffer;
212 jcf->read_end = jcf->buffer_end;
213 buffer = XNEWVEC (char, zipd->size);
214 d_stream.next_in = (unsigned char *) buffer;
215 d_stream.avail_in = zipd->size;
216 if (lseek (zipf->fd, zipd->filestart, 0) < 0
217 || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
218 return -2;
219 /* Handle NO_HEADER using undocumented zlib feature.
220 This is a very common hack. */
221 inflateInit2 (&d_stream, -MAX_WBITS);
222 inflate (&d_stream, Z_NO_FLUSH);
223 inflateEnd (&d_stream);
224 free (buffer);
227 return 0;
230 const char *
231 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
233 if (jcf)
235 struct stat stat_buf;
236 if (fstat (fd, &stat_buf) != 0
237 || ! S_ISREG (stat_buf.st_mode))
239 perror ("Could not figure length of .class file");
240 return NULL;
242 if (dep_name != NULL)
243 jcf_dependency_add_file (dep_name, 0);
244 JCF_ZERO (jcf);
245 jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
246 jcf->buffer_end = jcf->buffer + stat_buf.st_size;
247 jcf->read_ptr = jcf->buffer;
248 jcf->read_end = jcf->buffer_end;
249 jcf->read_state = NULL;
250 jcf->filename = xstrdup (filename);
251 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
253 perror ("Failed to read .class file");
254 return NULL;
256 close (fd);
257 jcf->filbuf = jcf_unexpected_eof;
259 else
260 close (fd);
261 return filename;
265 const char *
266 find_classfile (char *filename, JCF *jcf, const char *dep_name)
268 int fd = open (filename, O_RDONLY | O_BINARY);
269 if (fd < 0)
270 return NULL;
271 return open_class (filename, jcf, fd, dep_name);
274 /* A hash table keeping track of class names that were not found
275 during class lookup. (There is no need to cache the values
276 associated with names that were found; they are saved in
277 IDENTIFIER_CLASS_VALUE.) */
278 static hash_table<nofree_string_hash> *memoized_class_lookups;
280 /* Returns a freshly malloc'd string with the fully qualified pathname
281 of the .class file for the class CLASSNAME. CLASSNAME must be
282 allocated in permanent storage; this function may retain a pointer
283 to it. Returns NULL on failure. If JCF != NULL, it is suitably
284 initialized. SOURCE_OK is true if we should also look for .java
285 file. */
287 const char *
288 find_class (const char *classname, int classname_length, JCF *jcf)
290 int fd;
291 int i, k, klass = -1;
292 struct stat class_buf;
293 char *dep_file;
294 void *entry;
295 int buflen;
296 char *buffer;
297 hashval_t hash;
299 /* Create the hash table, if it does not already exist. */
300 if (!memoized_class_lookups)
301 memoized_class_lookups = new hash_table<nofree_string_hash> (37);
303 /* Loop for this class in the hashtable. If it is present, we've
304 already looked for this class and failed to find it. */
305 hash = nofree_string_hash::hash (classname);
306 if (memoized_class_lookups->find_with_hash (classname, hash))
307 return NULL;
309 /* Allocate and zero out the buffer, since we don't explicitly put a
310 null pointer when we're copying it below. */
311 buflen = jcf_path_max_len () + classname_length + 10;
312 buffer = XNEWVAR (char, buflen);
313 memset (buffer, 0, buflen);
315 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
317 const char *path_name = jcf_path_name (entry);
318 if (klass != 0)
320 int dir_len;
322 strcpy (buffer, path_name);
323 i = strlen (buffer);
325 /* This is right because we know that `.zip' entries will have a
326 trailing slash. See jcf-path.c. */
327 dir_len = i - 1;
329 for (k = 0; k < classname_length; k++, i++)
331 char ch = classname[k];
332 buffer[i] = ch == '.' ? '/' : ch;
334 strcpy (buffer+i, ".class");
336 if (jcf_path_is_zipfile (entry))
338 int err_code;
339 JCF _jcf;
340 buffer[dir_len] = '\0';
341 SOURCE_FRONTEND_DEBUG
342 (("Trying [...%s]:%s",
343 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
344 buffer+dir_len+1));
345 if (jcf == NULL)
346 jcf = &_jcf;
347 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
348 jcf_path_is_system (entry));
349 if (err_code == 0)
351 /* Should we check if .zip is out-of-date wrt .java? */
352 buffer[dir_len] = '(';
353 strcpy (buffer+i, ".class)");
354 if (jcf == &_jcf)
355 JCF_FINISH (jcf);
356 return buffer;
358 else
359 continue;
361 klass = stat (buffer, &class_buf);
365 dep_file = buffer;
366 if (!klass)
368 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
369 classname+classname_length-
370 (classname_length <= 30 ?
371 classname_length : 30)));
372 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
373 if (fd >= 0)
374 goto found;
377 free (buffer);
379 /* Remember that this class could not be found so that we do not
380 have to look again. */
381 *memoized_class_lookups->find_slot_with_hash (classname, hash, INSERT)
382 = classname;
384 return NULL;
385 found:
387 const char *const tmp = open_class (buffer, jcf, fd, dep_file);
388 jcf->classname = xstrdup (classname);
389 return tmp;
393 void
394 jcf_print_char (FILE *stream, int ch)
396 switch (ch)
398 case '\'':
399 case '\\':
400 case '\"':
401 fprintf (stream, "\\%c", ch);
402 break;
403 case '\n':
404 fprintf (stream, "\\n");
405 break;
406 case '\t':
407 fprintf (stream, "\\t");
408 break;
409 case '\r':
410 fprintf (stream, "\\r");
411 break;
412 default:
413 if (ch >= ' ' && ch < 127)
414 putc (ch, stream);
415 else if (ch < 256)
416 fprintf (stream, "\\%03x", ch);
417 else
418 fprintf (stream, "\\u%04x", ch);
422 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
424 void
425 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
427 const unsigned char * limit = str + length;
428 while (str < limit)
430 int ch = UTF8_GET (str, limit);
431 if (ch < 0)
433 fprintf (stream, "\\<invalid>");
434 return;
436 jcf_print_char (stream, ch);
440 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
442 void
443 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
444 int in_char, int out_char)
446 const unsigned char *limit = str + length;
447 while (str < limit)
449 int ch = UTF8_GET (str, limit);
450 if (ch < 0)
452 fprintf (stream, "\\<invalid>");
453 return;
455 jcf_print_char (stream, ch == in_char ? out_char : ch);
459 /* Check that all the cross-references in the constant pool are
460 valid. Returns 0 on success.
461 Otherwise, returns the index of the (first) invalid entry.
462 Only checks internal consistency, but does not check that
463 any classes, fields, or methods are valid.*/
466 verify_constant_pool (JCF *jcf)
468 int i, n;
469 for (i = 1; i < JPOOL_SIZE (jcf); i++)
471 switch (JPOOL_TAG (jcf, i))
473 case CONSTANT_NameAndType:
474 n = JPOOL_USHORT2 (jcf, i);
475 if (n <= 0 || n >= JPOOL_SIZE(jcf)
476 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
477 return i;
478 /* ... fall through ... */
479 case CONSTANT_Class:
480 case CONSTANT_String:
481 n = JPOOL_USHORT1 (jcf, i);
482 if (n <= 0 || n >= JPOOL_SIZE(jcf)
483 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
484 return i;
485 break;
486 case CONSTANT_Fieldref:
487 case CONSTANT_Methodref:
488 case CONSTANT_InterfaceMethodref:
489 n = JPOOL_USHORT1 (jcf, i);
490 if (n <= 0 || n >= JPOOL_SIZE(jcf)
491 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
492 return i;
493 n = JPOOL_USHORT2 (jcf, i);
494 if (n <= 0 || n >= JPOOL_SIZE(jcf)
495 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
496 return i;
497 break;
498 case CONSTANT_Long:
499 case CONSTANT_Double:
500 i++;
501 break;
502 case CONSTANT_Float:
503 case CONSTANT_Integer:
504 case CONSTANT_Utf8:
505 case CONSTANT_Unicode:
506 break;
507 case CONSTANT_MethodHandle:
508 n = JPOOL_USHORT1 (jcf, i);
509 if (n < 1 || n > 9)
510 return i;
511 n = JPOOL_USHORT2 (jcf, i);
512 if (n <= 0 || n >= JPOOL_SIZE(jcf))
513 return i;
514 break;
515 case CONSTANT_MethodType:
516 n = JPOOL_USHORT1 (jcf, i);
517 if (n <= 0 || n >= JPOOL_SIZE(jcf)
518 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
519 return i;
520 break;
521 case CONSTANT_InvokeDynamic:
522 n = JPOOL_USHORT2 (jcf, i);
523 if (n <= 0 || n >= JPOOL_SIZE(jcf)
524 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
525 return i;
526 break;
527 default:
528 return i;
531 return 0;
534 void
535 format_uint (char *buffer, uint64 value, int base)
537 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
538 char buf[WRITE_BUF_SIZE];
539 char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
540 int chars_written;
541 int i;
543 /* Now do the actual conversion, placing the result at the *end* of buf. */
544 /* Note this code does not pretend to be optimized. */
545 do {
546 int digit = value % base;
547 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
548 *--buf_ptr = digit_chars[digit];
549 value /= base;
550 } while (value != 0);
552 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
553 for (i = 0; i < chars_written; i++)
554 buffer[i] = *buf_ptr++;
555 buffer[i] = 0;
558 void
559 format_int (char *buffer, jlong value, int base)
561 uint64 abs_value;
562 if (value < 0)
564 abs_value = -(uint64)value;
565 *buffer++ = '-';
567 else
568 abs_value = (uint64) value;
569 format_uint (buffer, abs_value, base);