]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/java/jcf-io.c
Update Copyright years for files modified in 2011 and/or 2012.
[thirdparty/gcc.git] / gcc / java / jcf-io.c
CommitLineData
377029eb 1/* Utility routines for finding and reading Java(TM) .class files.
7e476713 2 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
71e45bc2 3 2006, 2007, 2008, 2009, 2010, 2012 Free Software Foundation, Inc.
377029eb 4
7d82ed5e 5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify
377029eb 8it under the terms of the GNU General Public License as published by
e4b52719 9the Free Software Foundation; either version 3, or (at your option)
377029eb 10any later version.
11
7d82ed5e 12GCC is distributed in the hope that it will be useful,
377029eb 13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
e4b52719 18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>.
377029eb 20
21Java and all Java-based marks are trademarks or registered trademarks
22of Sun Microsystems, Inc. in the United States and other countries.
23The Free Software Foundation is independent of Sun Microsystems, Inc. */
24
25/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
26
014e6e0c 27#include "config.h"
28#include "system.h"
805e22b2 29#include "coretypes.h"
377029eb 30
377029eb 31#include "jcf.h"
003019ba 32#include "tree.h"
33#include "java-tree.h"
d1455aa3 34#include "hash-table.h"
e98fb73e 35#include <dirent.h>
377029eb 36
fad14b72 37#include "zlib.h"
38
377029eb 39int
e7bf79cf 40jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
377029eb 41{
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);
47}
48
49void
e7bf79cf 50jcf_trim_old_input (JCF *jcf)
377029eb 51{
52 int count = jcf->read_ptr - jcf->buffer;
53 if (count > 0)
54 {
55 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
56 jcf->read_ptr -= count;
57 jcf->read_end -= count;
58 }
59}
60
61int
e7bf79cf 62jcf_filbuf_from_stdio (JCF *jcf, int count)
377029eb 63{
64 FILE *file = (FILE*) (jcf->read_state);
65 if (count > jcf->buffer_end - jcf->read_ptr)
66 {
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;
25a1c410 71 unsigned char *new_buffer
72 = jcf->buffer == NULL ? XNEWVAR (unsigned char, new_size)
73 : XRESIZEVAR (unsigned char, jcf->buffer, new_size);
377029eb 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;
78 }
79 count -= jcf->read_end - jcf->read_ptr;
80 if (count <= 0)
81 return 0;
65c439eb 82 if ((int) fread (jcf->read_end, 1, count, file) != count)
377029eb 83 jcf_unexpected_eof (jcf, count);
84 jcf->read_end += count;
85 return 0;
86}
87
377029eb 88#include "zipfile.h"
89
de9c2bdc 90struct ZipFile *SeenZipFiles = NULL;
377029eb 91
087b842d 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.
95*/
96
97ZipFile *
e7bf79cf 98opendir_in_zip (const char *zipfile, int is_system)
087b842d 99{
de9c2bdc 100 struct ZipFile* zipf;
087b842d 101 char magic [4];
102 int fd;
103 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
104 {
105 if (strcmp (zipf->name, zipfile) == 0)
de9c2bdc 106 return zipf;
087b842d 107 }
108
25a1c410 109 zipf = XNEWVAR (struct ZipFile, sizeof (struct ZipFile) + strlen (zipfile) + 1);
087b842d 110 zipf->next = SeenZipFiles;
111 zipf->name = (char*)(zipf+1);
112 strcpy (zipf->name, zipfile);
087b842d 113 fd = open (zipfile, O_RDONLY | O_BINARY);
de9c2bdc 114 zipf->fd = fd;
087b842d 115 if (fd < 0)
116 {
117 /* A missing zip file is not considered an error.
118 We may want to re-consider that. FIXME. */
de9c2bdc 119 zipf->count = 0;
120 zipf->dir_size = 0;
121 zipf->central_directory = NULL;
087b842d 122 }
123 else
124 {
125 jcf_dependency_add_file (zipfile, is_system);
126 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
c5042950 127 {
128 free (zipf);
129 close (fd);
130 return NULL;
131 }
087b842d 132 lseek (fd, 0L, SEEK_SET);
de9c2bdc 133 if (read_zip_archive (zipf) != 0)
c5042950 134 {
135 free (zipf);
136 close (fd);
137 return NULL;
138 }
087b842d 139 }
440bcc15 140
141 SeenZipFiles = zipf;
de9c2bdc 142 return zipf;
087b842d 143}
144
145/* Returns:
146 0: OK - zipmember found.
147 -1: Not found.
148 -2: Malformed archive.
149*/
150
377029eb 151int
e7bf79cf 152open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
153 int is_system)
377029eb 154{
377029eb 155 ZipDirectory *zipd;
156 int i, len;
087b842d 157 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
158
159 if (zipf == NULL)
160 return -2;
377029eb 161
162 if (!zipmember)
163 return 0;
164
165 len = strlen (zipmember);
166
087b842d 167 zipd = (struct ZipDirectory*) zipf->central_directory;
168 for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
377029eb 169 {
170 if (len == zipd->filename_length &&
171 strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
172 {
173 JCF_ZERO (jcf);
fad14b72 174
1ab1061d 175 jcf->filename = xstrdup (zipfile);
176 jcf->classname = xstrdup (zipmember);
de9c2bdc 177 return read_zip_member(jcf, zipd, zipf);
178 }
179 }
180 return -1;
181}
182
183/* Read data from zip archive member. */
184
185int
e7bf79cf 186read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf)
de9c2bdc 187{
caa8fa37 188 jcf->filbuf = jcf_unexpected_eof;
4c36ffe6 189 jcf->zipd = zipd;
caa8fa37 190
191 if (zipd->compression_method == Z_NO_COMPRESSION)
192 {
4c36ffe6 193 jcf->buffer = XNEWVEC (unsigned char, zipd->size);
caa8fa37 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;
200 }
201 else
202 {
203 char *buffer;
204 z_stream d_stream; /* decompression stream */
45e9f803 205 memset (&d_stream, 0, sizeof (d_stream));
caa8fa37 206
4c36ffe6 207 jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
caa8fa37 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;
4c36ffe6 213 buffer = XNEWVEC (char, zipd->size);
8e452f9c 214 d_stream.next_in = (unsigned char *) buffer;
caa8fa37 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);
4c36ffe6 224 free (buffer);
caa8fa37 225 }
226
227 return 0;
377029eb 228}
377029eb 229
e772a198 230const char *
e7bf79cf 231open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
377029eb 232{
233 if (jcf)
234 {
235 struct stat stat_buf;
236 if (fstat (fd, &stat_buf) != 0
237 || ! S_ISREG (stat_buf.st_mode))
238 {
239 perror ("Could not figure length of .class file");
240 return NULL;
241 }
b76c045f 242 if (dep_name != NULL)
243 jcf_dependency_add_file (dep_name, 0);
377029eb 244 JCF_ZERO (jcf);
4c36ffe6 245 jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
377029eb 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;
20677948 250 jcf->filename = xstrdup (filename);
377029eb 251 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
252 {
253 perror ("Failed to read .class file");
254 return NULL;
255 }
256 close (fd);
257 jcf->filbuf = jcf_unexpected_eof;
258 }
259 else
260 close (fd);
261 return filename;
262}
377029eb 263
264
68ddcc2a 265const char *
e7bf79cf 266find_classfile (char *filename, JCF *jcf, const char *dep_name)
377029eb 267{
377029eb 268 int fd = open (filename, O_RDONLY | O_BINARY);
269 if (fd < 0)
270 return NULL;
b76c045f 271 return open_class (filename, jcf, fd, dep_name);
377029eb 272}
273
e98fb73e 274
d1455aa3 275/* Hash table helper. */
276
277struct charstar_hash : typed_noop_remove <char>
278{
c580da87 279 typedef const char value_type;
280 typedef const char compare_type;
281 static inline hashval_t hash (const value_type *candidate);
282 static inline bool equal (const value_type *existing,
283 const compare_type *candidate);
d1455aa3 284};
285
286inline hashval_t
c580da87 287charstar_hash::hash (const value_type *candidate)
e98fb73e 288{
d1455aa3 289 return htab_hash_string (candidate);
e98fb73e 290}
291
d1455aa3 292inline bool
c580da87 293charstar_hash::equal (const value_type *existing, const compare_type *candidate)
d1455aa3 294{
295 return strcmp (existing, candidate) == 0;
296}
297
298
e98fb73e 299/* A hash table keeping track of class names that were not found
300 during class lookup. (There is no need to cache the values
301 associated with names that were found; they are saved in
302 IDENTIFIER_CLASS_VALUE.) */
d1455aa3 303static hash_table <charstar_hash> memoized_class_lookups;
e98fb73e 304
377029eb 305/* Returns a freshly malloc'd string with the fully qualified pathname
e98fb73e 306 of the .class file for the class CLASSNAME. CLASSNAME must be
307 allocated in permanent storage; this function may retain a pointer
308 to it. Returns NULL on failure. If JCF != NULL, it is suitably
309 initialized. SOURCE_OK is true if we should also look for .java
310 file. */
377029eb 311
68ddcc2a 312const char *
7e476713 313find_class (const char *classname, int classname_length, JCF *jcf)
377029eb 314{
377029eb 315 int fd;
ead29d98 316 int i, k, klass = -1;
7e476713 317 struct stat class_buf;
b76c045f 318 char *dep_file;
087b842d 319 void *entry;
e98fb73e 320 int buflen;
321 char *buffer;
322 hashval_t hash;
323
324 /* Create the hash table, if it does not already exist. */
d1455aa3 325 if (!memoized_class_lookups.is_created ())
326 memoized_class_lookups.create (37);
e98fb73e 327
328 /* Loop for this class in the hashtable. If it is present, we've
329 already looked for this class and failed to find it. */
d1455aa3 330 hash = charstar_hash::hash (classname);
331 if (memoized_class_lookups.find_with_hash (classname, hash))
e98fb73e 332 return NULL;
377029eb 333
334 /* Allocate and zero out the buffer, since we don't explicitly put a
335 null pointer when we're copying it below. */
e98fb73e 336 buflen = jcf_path_max_len () + classname_length + 10;
25a1c410 337 buffer = XNEWVAR (char, buflen);
93d3b7de 338 memset (buffer, 0, buflen);
377029eb 339
bb9b756c 340 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
377029eb 341 {
68ddcc2a 342 const char *path_name = jcf_path_name (entry);
ead29d98 343 if (klass != 0)
087b842d 344 {
345 int dir_len;
bb9b756c 346
087b842d 347 strcpy (buffer, path_name);
348 i = strlen (buffer);
bb9b756c 349
087b842d 350 /* This is right because we know that `.zip' entries will have a
351 trailing slash. See jcf-path.c. */
352 dir_len = i - 1;
bb9b756c 353
087b842d 354 for (k = 0; k < classname_length; k++, i++)
355 {
356 char ch = classname[k];
357 buffer[i] = ch == '.' ? '/' : ch;
358 }
359 strcpy (buffer+i, ".class");
bb9b756c 360
087b842d 361 if (jcf_path_is_zipfile (entry))
377029eb 362 {
087b842d 363 int err_code;
364 JCF _jcf;
365 buffer[dir_len] = '\0';
366 SOURCE_FRONTEND_DEBUG
367 (("Trying [...%s]:%s",
368 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
369 buffer+dir_len+1));
370 if (jcf == NULL)
371 jcf = &_jcf;
372 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
373 jcf_path_is_system (entry));
374 if (err_code == 0)
377029eb 375 {
087b842d 376 /* Should we check if .zip is out-of-date wrt .java? */
bb9b756c 377 buffer[dir_len] = '(';
378 strcpy (buffer+i, ".class)");
087b842d 379 if (jcf == &_jcf)
380 JCF_FINISH (jcf);
381 return buffer;
377029eb 382 }
087b842d 383 else
384 continue;
377029eb 385 }
93608f9d 386 klass = stat (buffer, &class_buf);
bb9b756c 387 }
d1016559 388 }
bb9b756c 389
7e476713 390 dep_file = buffer;
ead29d98 391 if (!klass)
d1016559 392 {
57e0b67f 393 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
394 classname+classname_length-
395 (classname_length <= 30 ?
396 classname_length : 30)));
a1b2d596 397 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
d1016559 398 if (fd >= 0)
399 goto found;
400 }
d1016559 401
377029eb 402 free (buffer);
e98fb73e 403
404 /* Remember that this class could not be found so that we do not
405 have to look again. */
d1455aa3 406 *memoized_class_lookups.find_slot_with_hash (classname, hash, INSERT)
407 = classname;
e98fb73e 408
377029eb 409 return NULL;
410 found:
52d07779 411 {
412 const char *const tmp = open_class (buffer, jcf, fd, dep_file);
413 jcf->classname = xstrdup (classname);
414 return tmp;
415 }
377029eb 416}
417
418void
e7bf79cf 419jcf_print_char (FILE *stream, int ch)
377029eb 420{
421 switch (ch)
422 {
423 case '\'':
424 case '\\':
425 case '\"':
426 fprintf (stream, "\\%c", ch);
427 break;
428 case '\n':
429 fprintf (stream, "\\n");
430 break;
431 case '\t':
432 fprintf (stream, "\\t");
433 break;
434 case '\r':
435 fprintf (stream, "\\r");
436 break;
437 default:
438 if (ch >= ' ' && ch < 127)
439 putc (ch, stream);
440 else if (ch < 256)
441 fprintf (stream, "\\%03x", ch);
442 else
443 fprintf (stream, "\\u%04x", ch);
444 }
445}
446
447/* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
448
449void
fdbb243d 450jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
377029eb 451{
003019ba 452 const unsigned char * limit = str + length;
377029eb 453 while (str < limit)
454 {
455 int ch = UTF8_GET (str, limit);
456 if (ch < 0)
457 {
458 fprintf (stream, "\\<invalid>");
459 return;
460 }
461 jcf_print_char (stream, ch);
462 }
463}
464
465/* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
466
467void
e7bf79cf 468jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
469 int in_char, int out_char)
377029eb 470{
d9f14ffe 471 const unsigned char *limit = str + length;
472 while (str < limit)
377029eb 473 {
d9f14ffe 474 int ch = UTF8_GET (str, limit);
475 if (ch < 0)
476 {
477 fprintf (stream, "\\<invalid>");
478 return;
479 }
377029eb 480 jcf_print_char (stream, ch == in_char ? out_char : ch);
481 }
482}
483
484/* Check that all the cross-references in the constant pool are
485 valid. Returns 0 on success.
9fb34998 486 Otherwise, returns the index of the (first) invalid entry.
487 Only checks internal consistency, but does not check that
488 any classes, fields, or methods are valid.*/
377029eb 489
490int
e7bf79cf 491verify_constant_pool (JCF *jcf)
377029eb 492{
493 int i, n;
494 for (i = 1; i < JPOOL_SIZE (jcf); i++)
495 {
496 switch (JPOOL_TAG (jcf, i))
497 {
498 case CONSTANT_NameAndType:
499 n = JPOOL_USHORT2 (jcf, i);
500 if (n <= 0 || n >= JPOOL_SIZE(jcf)
501 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
502 return i;
503 /* ... fall through ... */
504 case CONSTANT_Class:
505 case CONSTANT_String:
506 n = JPOOL_USHORT1 (jcf, i);
507 if (n <= 0 || n >= JPOOL_SIZE(jcf)
508 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
509 return i;
510 break;
511 case CONSTANT_Fieldref:
512 case CONSTANT_Methodref:
513 case CONSTANT_InterfaceMethodref:
514 n = JPOOL_USHORT1 (jcf, i);
515 if (n <= 0 || n >= JPOOL_SIZE(jcf)
516 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
517 return i;
518 n = JPOOL_USHORT2 (jcf, i);
519 if (n <= 0 || n >= JPOOL_SIZE(jcf)
520 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
521 return i;
522 break;
523 case CONSTANT_Long:
524 case CONSTANT_Double:
525 i++;
526 break;
527 case CONSTANT_Float:
528 case CONSTANT_Integer:
529 case CONSTANT_Utf8:
530 case CONSTANT_Unicode:
531 break;
39101666 532 case CONSTANT_MethodHandle:
533 n = JPOOL_USHORT1 (jcf, i);
534 if (n < 1 || n > 9)
535 return i;
536 n = JPOOL_USHORT2 (jcf, i);
537 if (n <= 0 || n >= JPOOL_SIZE(jcf))
538 return i;
539 break;
540 case CONSTANT_MethodType:
541 n = JPOOL_USHORT1 (jcf, i);
542 if (n <= 0 || n >= JPOOL_SIZE(jcf)
543 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
544 return i;
545 break;
546 case CONSTANT_InvokeDynamic:
547 n = JPOOL_USHORT2 (jcf, i);
548 if (n <= 0 || n >= JPOOL_SIZE(jcf)
549 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
550 return i;
551 break;
377029eb 552 default:
553 return i;
554 }
555 }
556 return 0;
557}
558
559void
e7bf79cf 560format_uint (char *buffer, uint64 value, int base)
377029eb 561{
562#define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
563 char buf[WRITE_BUF_SIZE];
fdbb243d 564 char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
377029eb 565 int chars_written;
566 int i;
567
568 /* Now do the actual conversion, placing the result at the *end* of buf. */
569 /* Note this code does not pretend to be optimized. */
570 do {
571 int digit = value % base;
e99c3a1d 572 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
377029eb 573 *--buf_ptr = digit_chars[digit];
574 value /= base;
575 } while (value != 0);
576
577 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
578 for (i = 0; i < chars_written; i++)
579 buffer[i] = *buf_ptr++;
580 buffer[i] = 0;
581}
582
583void
e7bf79cf 584format_int (char *buffer, jlong value, int base)
377029eb 585{
586 uint64 abs_value;
587 if (value < 0)
588 {
589 abs_value = -(uint64)value;
590 *buffer++ = '-';
591 }
592 else
593 abs_value = (uint64) value;
594 format_uint (buffer, abs_value, base);
595}