Remove outermost loop parameter.
[official-gcc/graphite-test-results.git] / gcc / java / jcf-io.c
blob1c455da2101bf3b8d005cc18b501c8e854e07dff
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 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 /* DOS brain-damage */
40 #ifndef O_BINARY
41 #define O_BINARY 0 /* MS-DOS brain-damage */
42 #endif
44 int
45 jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
47 if (jcf->filename)
48 fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
49 else
50 fprintf (stderr, "Premature end of .class file <stdin>.\n");
51 exit (-1);
54 void
55 jcf_trim_old_input (JCF *jcf)
57 int count = jcf->read_ptr - jcf->buffer;
58 if (count > 0)
60 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
61 jcf->read_ptr -= count;
62 jcf->read_end -= count;
66 int
67 jcf_filbuf_from_stdio (JCF *jcf, int count)
69 FILE *file = (FILE*) (jcf->read_state);
70 if (count > jcf->buffer_end - jcf->read_ptr)
72 JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
73 JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
74 JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
75 JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
76 unsigned char *new_buffer
77 = jcf->buffer == NULL ? XNEWVAR (unsigned char, new_size)
78 : XRESIZEVAR (unsigned char, jcf->buffer, new_size);
79 jcf->buffer = new_buffer;
80 jcf->buffer_end = new_buffer + new_size;
81 jcf->read_ptr = new_buffer + old_read_ptr;
82 jcf->read_end = new_buffer + old_read_end;
84 count -= jcf->read_end - jcf->read_ptr;
85 if (count <= 0)
86 return 0;
87 if ((int) fread (jcf->read_end, 1, count, file) != count)
88 jcf_unexpected_eof (jcf, count);
89 jcf->read_end += count;
90 return 0;
93 #include "zipfile.h"
95 struct ZipFile *SeenZipFiles = NULL;
97 /* Open a zip file with the given name, and cache directory and file
98 descriptor. If the file is missing, treat it as an empty archive.
99 Return NULL if the .zip file is malformed.
102 ZipFile *
103 opendir_in_zip (const char *zipfile, int is_system)
105 struct ZipFile* zipf;
106 char magic [4];
107 int fd;
108 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
110 if (strcmp (zipf->name, zipfile) == 0)
111 return zipf;
114 zipf = XNEWVAR (struct ZipFile, sizeof (struct ZipFile) + strlen (zipfile) + 1);
115 zipf->next = SeenZipFiles;
116 zipf->name = (char*)(zipf+1);
117 strcpy (zipf->name, zipfile);
118 fd = open (zipfile, O_RDONLY | O_BINARY);
119 zipf->fd = fd;
120 if (fd < 0)
122 /* A missing zip file is not considered an error.
123 We may want to re-consider that. FIXME. */
124 zipf->count = 0;
125 zipf->dir_size = 0;
126 zipf->central_directory = NULL;
128 else
130 jcf_dependency_add_file (zipfile, is_system);
131 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
133 free (zipf);
134 close (fd);
135 return NULL;
137 lseek (fd, 0L, SEEK_SET);
138 if (read_zip_archive (zipf) != 0)
140 free (zipf);
141 close (fd);
142 return NULL;
146 SeenZipFiles = zipf;
147 return zipf;
150 /* Returns:
151 0: OK - zipmember found.
152 -1: Not found.
153 -2: Malformed archive.
157 open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
158 int is_system)
160 ZipDirectory *zipd;
161 int i, len;
162 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
164 if (zipf == NULL)
165 return -2;
167 if (!zipmember)
168 return 0;
170 len = strlen (zipmember);
172 zipd = (struct ZipDirectory*) zipf->central_directory;
173 for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
175 if (len == zipd->filename_length &&
176 strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
178 JCF_ZERO (jcf);
180 jcf->filename = xstrdup (zipfile);
181 jcf->classname = xstrdup (zipmember);
182 return read_zip_member(jcf, zipd, zipf);
185 return -1;
188 /* Read data from zip archive member. */
191 read_zip_member (JCF *jcf, ZipDirectory *zipd, ZipFile *zipf)
193 jcf->filbuf = jcf_unexpected_eof;
194 jcf->zipd = zipd;
196 if (zipd->compression_method == Z_NO_COMPRESSION)
198 jcf->buffer = XNEWVEC (unsigned char, zipd->size);
199 jcf->buffer_end = jcf->buffer + zipd->size;
200 jcf->read_ptr = jcf->buffer;
201 jcf->read_end = jcf->buffer_end;
202 if (lseek (zipf->fd, zipd->filestart, 0) < 0
203 || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
204 return -2;
206 else
208 char *buffer;
209 z_stream d_stream; /* decompression stream */
210 d_stream.zalloc = (alloc_func) 0;
211 d_stream.zfree = (free_func) 0;
212 d_stream.opaque = (voidpf) 0;
214 jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
215 d_stream.next_out = jcf->buffer;
216 d_stream.avail_out = zipd->uncompressed_size;
217 jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
218 jcf->read_ptr = jcf->buffer;
219 jcf->read_end = jcf->buffer_end;
220 buffer = XNEWVEC (char, zipd->size);
221 d_stream.next_in = (unsigned char *) buffer;
222 d_stream.avail_in = zipd->size;
223 if (lseek (zipf->fd, zipd->filestart, 0) < 0
224 || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
225 return -2;
226 /* Handle NO_HEADER using undocumented zlib feature.
227 This is a very common hack. */
228 inflateInit2 (&d_stream, -MAX_WBITS);
229 inflate (&d_stream, Z_NO_FLUSH);
230 inflateEnd (&d_stream);
231 free (buffer);
234 return 0;
237 const char *
238 open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
240 if (jcf)
242 struct stat stat_buf;
243 if (fstat (fd, &stat_buf) != 0
244 || ! S_ISREG (stat_buf.st_mode))
246 perror ("Could not figure length of .class file");
247 return NULL;
249 if (dep_name != NULL)
250 jcf_dependency_add_file (dep_name, 0);
251 JCF_ZERO (jcf);
252 jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
253 jcf->buffer_end = jcf->buffer + stat_buf.st_size;
254 jcf->read_ptr = jcf->buffer;
255 jcf->read_end = jcf->buffer_end;
256 jcf->read_state = NULL;
257 jcf->filename = xstrdup (filename);
258 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
260 perror ("Failed to read .class file");
261 return NULL;
263 close (fd);
264 jcf->filbuf = jcf_unexpected_eof;
266 else
267 close (fd);
268 return filename;
272 const char *
273 find_classfile (char *filename, JCF *jcf, const char *dep_name)
275 int fd = open (filename, O_RDONLY | O_BINARY);
276 if (fd < 0)
277 return NULL;
278 return open_class (filename, jcf, fd, dep_name);
281 /* Returns 1 if the CLASSNAME (really a char *) matches the name
282 stored in TABLE_ENTRY (also a char *). */
284 static int
285 memoized_class_lookup_eq (const void *table_entry, const void *classname)
287 return strcmp ((const char *)classname, (const char *)table_entry) == 0;
290 /* A hash table keeping track of class names that were not found
291 during class lookup. (There is no need to cache the values
292 associated with names that were found; they are saved in
293 IDENTIFIER_CLASS_VALUE.) */
294 static htab_t memoized_class_lookups;
296 /* Returns a freshly malloc'd string with the fully qualified pathname
297 of the .class file for the class CLASSNAME. CLASSNAME must be
298 allocated in permanent storage; this function may retain a pointer
299 to it. Returns NULL on failure. If JCF != NULL, it is suitably
300 initialized. SOURCE_OK is true if we should also look for .java
301 file. */
303 const char *
304 find_class (const char *classname, int classname_length, JCF *jcf)
306 int fd;
307 int i, k, klass = -1;
308 struct stat class_buf;
309 char *dep_file;
310 void *entry;
311 int buflen;
312 char *buffer;
313 hashval_t hash;
315 /* Create the hash table, if it does not already exist. */
316 if (!memoized_class_lookups)
317 memoized_class_lookups = htab_create (37,
318 htab_hash_string,
319 memoized_class_lookup_eq,
320 NULL);
322 /* Loop for this class in the hashtable. If it is present, we've
323 already looked for this class and failed to find it. */
324 hash = htab_hash_string (classname);
325 if (htab_find_with_hash (memoized_class_lookups, classname, hash))
326 return NULL;
328 /* Allocate and zero out the buffer, since we don't explicitly put a
329 null pointer when we're copying it below. */
330 buflen = jcf_path_max_len () + classname_length + 10;
331 buffer = XNEWVAR (char, buflen);
332 memset (buffer, 0, buflen);
334 for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
336 const char *path_name = jcf_path_name (entry);
337 if (klass != 0)
339 int dir_len;
341 strcpy (buffer, path_name);
342 i = strlen (buffer);
344 /* This is right because we know that `.zip' entries will have a
345 trailing slash. See jcf-path.c. */
346 dir_len = i - 1;
348 for (k = 0; k < classname_length; k++, i++)
350 char ch = classname[k];
351 buffer[i] = ch == '.' ? '/' : ch;
353 strcpy (buffer+i, ".class");
355 if (jcf_path_is_zipfile (entry))
357 int err_code;
358 JCF _jcf;
359 buffer[dir_len] = '\0';
360 SOURCE_FRONTEND_DEBUG
361 (("Trying [...%s]:%s",
362 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
363 buffer+dir_len+1));
364 if (jcf == NULL)
365 jcf = &_jcf;
366 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
367 jcf_path_is_system (entry));
368 if (err_code == 0)
370 /* Should we check if .zip is out-of-date wrt .java? */
371 buffer[dir_len] = '(';
372 strcpy (buffer+i, ".class)");
373 if (jcf == &_jcf)
374 JCF_FINISH (jcf);
375 return buffer;
377 else
378 continue;
380 klass = stat (buffer, &class_buf);
384 dep_file = buffer;
385 if (!klass)
387 SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
388 classname+classname_length-
389 (classname_length <= 30 ?
390 classname_length : 30)));
391 fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
392 if (fd >= 0)
393 goto found;
396 free (buffer);
398 /* Remember that this class could not be found so that we do not
399 have to look again. */
400 *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT)
401 = (void *) CONST_CAST (char *, classname);
403 return NULL;
404 found:
406 const char *const tmp = open_class (buffer, jcf, fd, dep_file);
407 jcf->classname = xstrdup (classname);
408 return tmp;
412 void
413 jcf_print_char (FILE *stream, int ch)
415 switch (ch)
417 case '\'':
418 case '\\':
419 case '\"':
420 fprintf (stream, "\\%c", ch);
421 break;
422 case '\n':
423 fprintf (stream, "\\n");
424 break;
425 case '\t':
426 fprintf (stream, "\\t");
427 break;
428 case '\r':
429 fprintf (stream, "\\r");
430 break;
431 default:
432 if (ch >= ' ' && ch < 127)
433 putc (ch, stream);
434 else if (ch < 256)
435 fprintf (stream, "\\%03x", ch);
436 else
437 fprintf (stream, "\\u%04x", ch);
441 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
443 void
444 jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
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);
459 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
461 void
462 jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
463 int in_char, int out_char)
465 const unsigned char *limit = str + length;
466 while (str < limit)
468 int ch = UTF8_GET (str, limit);
469 if (ch < 0)
471 fprintf (stream, "\\<invalid>");
472 return;
474 jcf_print_char (stream, ch == in_char ? out_char : ch);
478 /* Check that all the cross-references in the constant pool are
479 valid. Returns 0 on success.
480 Otherwise, returns the index of the (first) invalid entry.
481 Only checks internal consistency, but does not check that
482 any classes, fields, or methods are valid.*/
485 verify_constant_pool (JCF *jcf)
487 int i, n;
488 for (i = 1; i < JPOOL_SIZE (jcf); i++)
490 switch (JPOOL_TAG (jcf, i))
492 case CONSTANT_NameAndType:
493 n = JPOOL_USHORT2 (jcf, i);
494 if (n <= 0 || n >= JPOOL_SIZE(jcf)
495 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
496 return i;
497 /* ... fall through ... */
498 case CONSTANT_Class:
499 case CONSTANT_String:
500 n = JPOOL_USHORT1 (jcf, i);
501 if (n <= 0 || n >= JPOOL_SIZE(jcf)
502 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
503 return i;
504 break;
505 case CONSTANT_Fieldref:
506 case CONSTANT_Methodref:
507 case CONSTANT_InterfaceMethodref:
508 n = JPOOL_USHORT1 (jcf, i);
509 if (n <= 0 || n >= JPOOL_SIZE(jcf)
510 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
511 return i;
512 n = JPOOL_USHORT2 (jcf, i);
513 if (n <= 0 || n >= JPOOL_SIZE(jcf)
514 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
515 return i;
516 break;
517 case CONSTANT_Long:
518 case CONSTANT_Double:
519 i++;
520 break;
521 case CONSTANT_Float:
522 case CONSTANT_Integer:
523 case CONSTANT_Utf8:
524 case CONSTANT_Unicode:
525 break;
526 default:
527 return i;
530 return 0;
533 void
534 format_uint (char *buffer, uint64 value, int base)
536 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
537 char buf[WRITE_BUF_SIZE];
538 char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
539 int chars_written;
540 int i;
542 /* Now do the actual conversion, placing the result at the *end* of buf. */
543 /* Note this code does not pretend to be optimized. */
544 do {
545 int digit = value % base;
546 static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
547 *--buf_ptr = digit_chars[digit];
548 value /= base;
549 } while (value != 0);
551 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
552 for (i = 0; i < chars_written; i++)
553 buffer[i] = *buf_ptr++;
554 buffer[i] = 0;
557 void
558 format_int (char *buffer, jlong value, int base)
560 uint64 abs_value;
561 if (value < 0)
563 abs_value = -(uint64)value;
564 *buffer++ = '-';
566 else
567 abs_value = (uint64) value;
568 format_uint (buffer, abs_value, base);