gcc/
[official-gcc.git] / gcc / java / jcf-io.c
blobbe251d462f177cf7c5d1ad28745c88e54f16efda
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 "symtab.h"
33 #include "options.h"
34 #include "tree.h"
35 #include "java-tree.h"
36 #include <dirent.h>
38 #include "zlib.h"
40 int
41 jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
43 if (jcf->filename)
44 fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
45 else
46 fprintf (stderr, "Premature end of .class file <stdin>.\n");
47 exit (-1);
50 void
51 jcf_trim_old_input (JCF *jcf)
53 int count = jcf->read_ptr - jcf->buffer;
54 if (count > 0)
56 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
57 jcf->read_ptr -= count;
58 jcf->read_end -= count;
62 int
63 jcf_filbuf_from_stdio (JCF *jcf, int count)
65 FILE *file = (FILE*) (jcf->read_state);
66 if (count > jcf->buffer_end - jcf->read_ptr)
68 JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
69 JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
70 JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
71 JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
72 unsigned char *new_buffer
73 = jcf->buffer == NULL ? XNEWVAR (unsigned char, new_size)
74 : XRESIZEVAR (unsigned char, jcf->buffer, new_size);
75 jcf->buffer = new_buffer;
76 jcf->buffer_end = new_buffer + new_size;
77 jcf->read_ptr = new_buffer + old_read_ptr;
78 jcf->read_end = new_buffer + old_read_end;
80 count -= jcf->read_end - jcf->read_ptr;
81 if (count <= 0)
82 return 0;
83 if ((int) fread (jcf->read_end, 1, count, file) != count)
84 jcf_unexpected_eof (jcf, count);
85 jcf->read_end += count;
86 return 0;
89 #include "zipfile.h"
91 struct ZipFile *SeenZipFiles = NULL;
93 /* Open a zip file with the given name, and cache directory and file
94 descriptor. If the file is missing, treat it as an empty archive.
95 Return NULL if the .zip file is malformed.
98 ZipFile *
99 opendir_in_zip (const char *zipfile, int is_system)
101 struct ZipFile* zipf;
102 char magic [4];
103 int fd;
104 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
106 if (strcmp (zipf->name, zipfile) == 0)
107 return zipf;
110 zipf = XNEWVAR (struct ZipFile, sizeof (struct ZipFile) + strlen (zipfile) + 1);
111 zipf->next = SeenZipFiles;
112 zipf->name = (char*)(zipf+1);
113 strcpy (zipf->name, zipfile);
114 fd = open (zipfile, O_RDONLY | O_BINARY);
115 zipf->fd = fd;
116 if (fd < 0)
118 /* A missing zip file is not considered an error.
119 We may want to re-consider that. FIXME. */
120 zipf->count = 0;
121 zipf->dir_size = 0;
122 zipf->central_directory = NULL;
124 else
126 jcf_dependency_add_file (zipfile, is_system);
127 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
129 free (zipf);
130 close (fd);
131 return NULL;
133 lseek (fd, 0L, SEEK_SET);
134 if (read_zip_archive (zipf) != 0)
136 free (zipf);
137 close (fd);
138 return NULL;
142 SeenZipFiles = zipf;
143 return zipf;
146 /* Returns:
147 0: OK - zipmember found.
148 -1: Not found.
149 -2: Malformed archive.
153 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
154 int is_system)
156 ZipDirectory *zipd;
157 int i, len;
158 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
160 if (zipf == NULL)
161 return -2;
163 if (!zipmember)
164 return 0;
166 len = strlen (zipmember);
168 zipd = (struct ZipDirectory*) zipf->central_directory;
169 for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
171 if (len == zipd->filename_length &&
172 strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
174 JCF_ZERO (jcf);
176 jcf->filename = xstrdup (zipfile);
177 jcf->classname = xstrdup (zipmember);
178 return read_zip_member(jcf, zipd, zipf);
181 return -1;
184 /* Read data from zip archive member. */
187 read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf)
189 jcf->filbuf = jcf_unexpected_eof;
190 jcf->zipd = zipd;
192 if (zipd->compression_method == Z_NO_COMPRESSION)
194 jcf->buffer = XNEWVEC (unsigned char, zipd->size);
195 jcf->buffer_end = jcf->buffer + zipd->size;
196 jcf->read_ptr = jcf->buffer;
197 jcf->read_end = jcf->buffer_end;
198 if (lseek (zipf->fd, zipd->filestart, 0) < 0
199 || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
200 return -2;
202 else
204 char *buffer;
205 z_stream d_stream; /* decompression stream */
206 memset (&d_stream, 0, sizeof (d_stream));
208 jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
209 d_stream.next_out = jcf->buffer;
210 d_stream.avail_out = zipd->uncompressed_size;
211 jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
212 jcf->read_ptr = jcf->buffer;
213 jcf->read_end = jcf->buffer_end;
214 buffer = XNEWVEC (char, zipd->size);
215 d_stream.next_in = (unsigned char *) buffer;
216 d_stream.avail_in = zipd->size;
217 if (lseek (zipf->fd, zipd->filestart, 0) < 0
218 || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
219 return -2;
220 /* Handle NO_HEADER using undocumented zlib feature.
221 This is a very common hack. */
222 inflateInit2 (&d_stream, -MAX_WBITS);
223 inflate (&d_stream, Z_NO_FLUSH);
224 inflateEnd (&d_stream);
225 free (buffer);
228 return 0;
231 const char *
232 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
234 if (jcf)
236 struct stat stat_buf;
237 if (fstat (fd, &stat_buf) != 0
238 || ! S_ISREG (stat_buf.st_mode))
240 perror ("Could not figure length of .class file");
241 return NULL;
243 if (dep_name != NULL)
244 jcf_dependency_add_file (dep_name, 0);
245 JCF_ZERO (jcf);
246 jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
247 jcf->buffer_end = jcf->buffer + stat_buf.st_size;
248 jcf->read_ptr = jcf->buffer;
249 jcf->read_end = jcf->buffer_end;
250 jcf->read_state = NULL;
251 jcf->filename = xstrdup (filename);
252 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
254 perror ("Failed to read .class file");
255 return NULL;
257 close (fd);
258 jcf->filbuf = jcf_unexpected_eof;
260 else
261 close (fd);
262 return filename;
266 const char *
267 find_classfile (char *filename, JCF *jcf, const char *dep_name)
269 int fd = open (filename, O_RDONLY | O_BINARY);
270 if (fd < 0)
271 return NULL;
272 return open_class (filename, jcf, fd, dep_name);
275 /* A hash table keeping track of class names that were not found
276 during class lookup. (There is no need to cache the values
277 associated with names that were found; they are saved in
278 IDENTIFIER_CLASS_VALUE.) */
279 static hash_table<nofree_string_hash> *memoized_class_lookups;
281 /* Returns a freshly malloc'd string with the fully qualified pathname
282 of the .class file for the class CLASSNAME. CLASSNAME must be
283 allocated in permanent storage; this function may retain a pointer
284 to it. Returns NULL on failure. If JCF != NULL, it is suitably
285 initialized. SOURCE_OK is true if we should also look for .java
286 file. */
288 const char *
289 find_class (const char *classname, int classname_length, JCF *jcf)
291 int fd;
292 int i, k, klass = -1;
293 struct stat class_buf;
294 char *dep_file;
295 void *entry;
296 int buflen;
297 char *buffer;
298 hashval_t hash;
300 /* Create the hash table, if it does not already exist. */
301 if (!memoized_class_lookups)
302 memoized_class_lookups = new hash_table<nofree_string_hash> (37);
304 /* Loop for this class in the hashtable. If it is present, we've
305 already looked for this class and failed to find it. */
306 hash = nofree_string_hash::hash (classname);
307 if (memoized_class_lookups->find_with_hash (classname, hash))
308 return NULL;
310 /* Allocate and zero out the buffer, since we don't explicitly put a
311 null pointer when we're copying it below. */
312 buflen = jcf_path_max_len () + classname_length + 10;
313 buffer = XNEWVAR (char, buflen);
314 memset (buffer, 0, buflen);
316 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
318 const char *path_name = jcf_path_name (entry);
319 if (klass != 0)
321 int dir_len;
323 strcpy (buffer, path_name);
324 i = strlen (buffer);
326 /* This is right because we know that `.zip' entries will have a
327 trailing slash. See jcf-path.c. */
328 dir_len = i - 1;
330 for (k = 0; k < classname_length; k++, i++)
332 char ch = classname[k];
333 buffer[i] = ch == '.' ? '/' : ch;
335 strcpy (buffer+i, ".class");
337 if (jcf_path_is_zipfile (entry))
339 int err_code;
340 JCF _jcf;
341 buffer[dir_len] = '\0';
342 SOURCE_FRONTEND_DEBUG
343 (("Trying [...%s]:%s",
344 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
345 buffer+dir_len+1));
346 if (jcf == NULL)
347 jcf = &_jcf;
348 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
349 jcf_path_is_system (entry));
350 if (err_code == 0)
352 /* Should we check if .zip is out-of-date wrt .java? */
353 buffer[dir_len] = '(';
354 strcpy (buffer+i, ".class)");
355 if (jcf == &_jcf)
356 JCF_FINISH (jcf);
357 return buffer;
359 else
360 continue;
362 klass = stat (buffer, &class_buf);
366 dep_file = buffer;
367 if (!klass)
369 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
370 classname+classname_length-
371 (classname_length <= 30 ?
372 classname_length : 30)));
373 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
374 if (fd >= 0)
375 goto found;
378 free (buffer);
380 /* Remember that this class could not be found so that we do not
381 have to look again. */
382 *memoized_class_lookups->find_slot_with_hash (classname, hash, INSERT)
383 = classname;
385 return NULL;
386 found:
388 const char *const tmp = open_class (buffer, jcf, fd, dep_file);
389 jcf->classname = xstrdup (classname);
390 return tmp;
394 void
395 jcf_print_char (FILE *stream, int ch)
397 switch (ch)
399 case '\'':
400 case '\\':
401 case '\"':
402 fprintf (stream, "\\%c", ch);
403 break;
404 case '\n':
405 fprintf (stream, "\\n");
406 break;
407 case '\t':
408 fprintf (stream, "\\t");
409 break;
410 case '\r':
411 fprintf (stream, "\\r");
412 break;
413 default:
414 if (ch >= ' ' && ch < 127)
415 putc (ch, stream);
416 else if (ch < 256)
417 fprintf (stream, "\\%03x", ch);
418 else
419 fprintf (stream, "\\u%04x", ch);
423 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
425 void
426 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
428 const unsigned char * limit = str + length;
429 while (str < limit)
431 int ch = UTF8_GET (str, limit);
432 if (ch < 0)
434 fprintf (stream, "\\<invalid>");
435 return;
437 jcf_print_char (stream, ch);
441 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
443 void
444 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
445 int in_char, int out_char)
447 const unsigned char *limit = str + length;
448 while (str < limit)
450 int ch = UTF8_GET (str, limit);
451 if (ch < 0)
453 fprintf (stream, "\\<invalid>");
454 return;
456 jcf_print_char (stream, ch == in_char ? out_char : ch);
460 /* Check that all the cross-references in the constant pool are
461 valid. Returns 0 on success.
462 Otherwise, returns the index of the (first) invalid entry.
463 Only checks internal consistency, but does not check that
464 any classes, fields, or methods are valid.*/
467 verify_constant_pool (JCF *jcf)
469 int i, n;
470 for (i = 1; i < JPOOL_SIZE (jcf); i++)
472 switch (JPOOL_TAG (jcf, i))
474 case CONSTANT_NameAndType:
475 n = JPOOL_USHORT2 (jcf, i);
476 if (n <= 0 || n >= JPOOL_SIZE(jcf)
477 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
478 return i;
479 /* ... fall through ... */
480 case CONSTANT_Class:
481 case CONSTANT_String:
482 n = JPOOL_USHORT1 (jcf, i);
483 if (n <= 0 || n >= JPOOL_SIZE(jcf)
484 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
485 return i;
486 break;
487 case CONSTANT_Fieldref:
488 case CONSTANT_Methodref:
489 case CONSTANT_InterfaceMethodref:
490 n = JPOOL_USHORT1 (jcf, i);
491 if (n <= 0 || n >= JPOOL_SIZE(jcf)
492 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
493 return i;
494 n = JPOOL_USHORT2 (jcf, i);
495 if (n <= 0 || n >= JPOOL_SIZE(jcf)
496 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
497 return i;
498 break;
499 case CONSTANT_Long:
500 case CONSTANT_Double:
501 i++;
502 break;
503 case CONSTANT_Float:
504 case CONSTANT_Integer:
505 case CONSTANT_Utf8:
506 case CONSTANT_Unicode:
507 break;
508 case CONSTANT_MethodHandle:
509 n = JPOOL_USHORT1 (jcf, i);
510 if (n < 1 || n > 9)
511 return i;
512 n = JPOOL_USHORT2 (jcf, i);
513 if (n <= 0 || n >= JPOOL_SIZE(jcf))
514 return i;
515 break;
516 case CONSTANT_MethodType:
517 n = JPOOL_USHORT1 (jcf, i);
518 if (n <= 0 || n >= JPOOL_SIZE(jcf)
519 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
520 return i;
521 break;
522 case CONSTANT_InvokeDynamic:
523 n = JPOOL_USHORT2 (jcf, i);
524 if (n <= 0 || n >= JPOOL_SIZE(jcf)
525 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
526 return i;
527 break;
528 default:
529 return i;
532 return 0;
535 void
536 format_uint (char *buffer, uint64 value, int base)
538 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
539 char buf[WRITE_BUF_SIZE];
540 char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
541 int chars_written;
542 int i;
544 /* Now do the actual conversion, placing the result at the *end* of buf. */
545 /* Note this code does not pretend to be optimized. */
546 do {
547 int digit = value % base;
548 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
549 *--buf_ptr = digit_chars[digit];
550 value /= base;
551 } while (value != 0);
553 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
554 for (i = 0; i < chars_written; i++)
555 buffer[i] = *buf_ptr++;
556 buffer[i] = 0;
559 void
560 format_int (char *buffer, jlong value, int base)
562 uint64 abs_value;
563 if (value < 0)
565 abs_value = -(uint64)value;
566 *buffer++ = '-';
568 else
569 abs_value = (uint64) value;
570 format_uint (buffer, abs_value, base);