1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996, 1997, 1998, 1999, 2000 Free Software Foundation, Inc.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2, or (at your option)
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with GNU CC; see the file COPYING. If not, write to
16 the Free Software Foundation, 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
19 Java and all Java-based marks are trademarks or registered trademarks
20 of Sun Microsystems, Inc. in the United States and other countries.
21 The Free Software Foundation is independent of Sun Microsystems, Inc. */
23 /* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
31 #include "java-tree.h"
35 /* DOS brain-damage */
37 #define O_BINARY 0 /* MS-DOS brain-damage */
41 DEFUN(jcf_unexpected_eof
, (jcf
, count
),
42 JCF
*jcf AND
int count ATTRIBUTE_UNUSED
)
45 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
47 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
52 DEFUN(jcf_trim_old_input
, (jcf
),
55 int count
= jcf
->read_ptr
- jcf
->buffer
;
58 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
59 jcf
->read_ptr
-= count
;
60 jcf
->read_end
-= count
;
65 DEFUN(jcf_filbuf_from_stdio
, (jcf
, count
),
66 JCF
*jcf AND
int count
)
68 FILE *file
= (FILE*) (jcf
->read_state
);
69 if (count
> jcf
->buffer_end
- jcf
->read_ptr
)
71 JCF_u4 old_read_ptr
= jcf
->read_ptr
- jcf
->buffer
;
72 JCF_u4 old_read_end
= jcf
->read_end
- jcf
->buffer
;
73 JCF_u4 old_size
= jcf
->buffer_end
- jcf
->buffer
;
74 JCF_u4 new_size
= (old_size
== 0 ? 2000 : 2 * old_size
) + count
;
75 unsigned char *new_buffer
= jcf
->buffer
== NULL
? ALLOC (new_size
)
76 : REALLOC (jcf
->buffer
, new_size
);
77 jcf
->buffer
= new_buffer
;
78 jcf
->buffer_end
= new_buffer
+ new_size
;
79 jcf
->read_ptr
= new_buffer
+ old_read_ptr
;
80 jcf
->read_end
= new_buffer
+ old_read_end
;
82 count
-= jcf
->read_end
- jcf
->read_ptr
;
85 if ((int) fread (jcf
->read_end
, 1, count
, file
) != count
)
86 jcf_unexpected_eof (jcf
, count
);
87 jcf
->read_end
+= count
;
93 struct ZipFile
*SeenZipFiles
= NULL
;
95 /* Open a zip file with the given name, and cache directory and file
96 descriptor. If the file is missing, treat it as an empty archive.
97 Return NULL if the .zip file is malformed.
101 DEFUN(opendir_in_zip
, (zipfile
, is_system
),
102 const char *zipfile AND
int is_system
)
104 struct ZipFile
* zipf
;
107 for (zipf
= SeenZipFiles
; zipf
!= NULL
; zipf
= zipf
->next
)
109 if (strcmp (zipf
->name
, zipfile
) == 0)
113 zipf
= ALLOC (sizeof (struct ZipFile
) + strlen (zipfile
) + 1);
114 zipf
->next
= SeenZipFiles
;
115 zipf
->name
= (char*)(zipf
+1);
116 strcpy (zipf
->name
, zipfile
);
118 fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
122 /* A missing zip file is not considered an error.
123 We may want to re-consider that. FIXME. */
126 zipf
->central_directory
= NULL
;
130 jcf_dependency_add_file (zipfile
, is_system
);
131 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
133 lseek (fd
, 0L, SEEK_SET
);
134 if (read_zip_archive (zipf
) != 0)
141 0: OK - zipmember found.
143 -2: Malformed archive.
147 DEFUN(open_in_zip
, (jcf
, zipfile
, zipmember
, is_system
),
148 JCF
*jcf AND
const char *zipfile AND
const char *zipmember
153 ZipFile
*zipf
= opendir_in_zip (zipfile
, is_system
);
161 len
= strlen (zipmember
);
163 zipd
= (struct ZipDirectory
*) zipf
->central_directory
;
164 for (i
= 0; i
< zipf
->count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
166 if (len
== zipd
->filename_length
&&
167 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
171 jcf
->filename
= xstrdup (zipfile
);
172 jcf
->classname
= xstrdup (zipmember
);
173 return read_zip_member(jcf
, zipd
, zipf
);
179 /* Read data from zip archive member. */
182 DEFUN(read_zip_member
, (jcf
, zipd
, zipf
),
183 JCF
*jcf AND ZipDirectory
*zipd AND ZipFile
*zipf
)
185 jcf
->filbuf
= jcf_unexpected_eof
;
186 jcf
->zipd
= (void *)zipd
;
188 if (zipd
->compression_method
== Z_NO_COMPRESSION
)
190 jcf
->buffer
= ALLOC (zipd
->size
);
191 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
192 jcf
->read_ptr
= jcf
->buffer
;
193 jcf
->read_end
= jcf
->buffer_end
;
194 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
195 || read (zipf
->fd
, jcf
->buffer
, zipd
->size
) != (long) zipd
->size
)
201 z_stream d_stream
; /* decompression stream */
202 d_stream
.zalloc
= (alloc_func
) 0;
203 d_stream
.zfree
= (free_func
) 0;
204 d_stream
.opaque
= (voidpf
) 0;
206 jcf
->buffer
= ALLOC (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
= ALLOC (zipd
->size
);
213 d_stream
.next_in
= 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
)
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
);
231 DEFUN(open_class
, (filename
, jcf
, stream
, dep_name
),
232 const char *filename AND JCF
*jcf AND
FILE* stream
233 AND
const char *dep_name
)
237 if (dep_name
!= NULL
)
238 jcf_dependency_add_file (dep_name
, 0);
241 jcf
->buffer_end
= NULL
;
242 jcf
->read_ptr
= NULL
;
243 jcf
->read_end
= NULL
;
244 jcf
->read_state
= stream
;
245 jcf
->filename
= filename
;
246 jcf
->filbuf
= jcf_filbuf_from_stdio
;
254 DEFUN(open_class
, (filename
, jcf
, fd
, dep_name
),
255 const char *filename AND JCF
*jcf AND
int fd AND
const char *dep_name
)
259 struct stat stat_buf
;
260 if (fstat (fd
, &stat_buf
) != 0
261 || ! S_ISREG (stat_buf
.st_mode
))
263 perror ("Could not figure length of .class file");
266 if (dep_name
!= NULL
)
267 jcf_dependency_add_file (dep_name
, 0);
269 jcf
->buffer
= ALLOC (stat_buf
.st_size
);
270 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
271 jcf
->read_ptr
= jcf
->buffer
;
272 jcf
->read_end
= jcf
->buffer_end
;
273 jcf
->read_state
= NULL
;
274 jcf
->filename
= filename
;
275 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
277 perror ("Failed to read .class file");
281 jcf
->filbuf
= jcf_unexpected_eof
;
291 DEFUN(find_classfile
, (filename
, jcf
, dep_name
),
292 char *filename AND JCF
*jcf AND
const char *dep_name
)
295 FILE *stream
= fopen (filename
, "rb");
298 return open_class (arg
, jcf
, stream
, dep_name
);
300 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
303 return open_class (filename
, jcf
, fd
, dep_name
);
307 /* Returns a freshly malloc'd string with the fully qualified pathname
308 of the .class file for the class CLASSNAME. Returns NULL on
309 failure. If JCF != NULL, it is suitably initialized.
310 SOURCE_OK is true if we should also look for .java file. */
313 DEFUN(find_class
, (classname
, classname_length
, jcf
, source_ok
),
314 const char *classname AND
int classname_length AND JCF
*jcf AND
int source_ok
)
322 int i
, k
, java
= -1, class = -1;
323 struct stat java_buf
, class_buf
;
328 /* Allocate and zero out the buffer, since we don't explicitly put a
329 null pointer when we're copying it below. */
330 int buflen
= jcf_path_max_len () + classname_length
+ 10;
331 char *buffer
= (char *) ALLOC (buflen
);
332 memset (buffer
, 0, buflen
);
334 java_buffer
= (char *) alloca (buflen
);
336 jcf
->java_source
= 0;
338 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
340 const char *path_name
= jcf_path_name (entry
);
345 strcpy (buffer
, path_name
);
348 /* This is right because we know that `.zip' entries will have a
349 trailing slash. See jcf-path.c. */
352 for (k
= 0; k
< classname_length
; k
++, i
++)
354 char ch
= classname
[k
];
355 buffer
[i
] = ch
== '.' ? '/' : ch
;
357 strcpy (buffer
+i
, ".class");
359 if (jcf_path_is_zipfile (entry
))
363 buffer
[dir_len
] = '\0';
364 SOURCE_FRONTEND_DEBUG
365 (("Trying [...%s]:%s",
366 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
370 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
371 jcf_path_is_system (entry
));
374 /* Should we check if .zip is out-of-date wrt .java? */
375 buffer
[dir_len
] = '(';
376 strcpy (buffer
+i
, ".class)");
384 class = stat (buffer
, &class_buf
);
389 /* Compute name of .java file. */
391 strcpy (java_buffer
, path_name
);
392 l
= strlen (java_buffer
);
393 for (m
= 0; m
< classname_length
; ++m
)
394 java_buffer
[m
+ l
] = (classname
[m
] == '.' ? '/' : classname
[m
]);
395 strcpy (java_buffer
+ m
+ l
, ".java");
396 java
= stat (java_buffer
, &java_buf
);
402 /* We preferably pick a class file if we have a chance. If the source
403 file is newer than the class file, we issue a warning and parse the
405 There should be a flag to allow people have the class file picked
406 up no matter what. FIXME. */
407 if (! java
&& ! class && java_buf
.st_mtime
> class_buf
.st_mtime
)
410 warning ("source file for class `%s' is newer than its matching class file. Source file `%s' used instead", classname
, java_buffer
);
415 dep_file
= java_buffer
;
421 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
422 stream
= fopen (buffer
, "rb");
426 /* Give .java a try, if necessary */
429 strcpy (buffer
, java_buffer
);
430 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
431 stream
= fopen (buffer
, "r");
434 jcf
->java_source
= 1;
441 SOURCE_FRONTEND_DEBUG ((stderr
, "[Class selected: %s]\n",
442 classname
+classname_length
-
443 (classname_length
<= 30 ?
444 classname_length
: 30)));
445 fd
= open (buffer
, O_RDONLY
| O_BINARY
);
449 /* Give .java a try, if necessary */
452 strcpy (buffer
, java_buffer
);
453 SOURCE_FRONTEND_DEBUG ((stderr
, "[Source selected: %s]\n",
454 classname
+classname_length
-
455 (classname_length
<= 30 ?
456 classname_length
: 30)));
457 fd
= open (buffer
, O_RDONLY
);
460 jcf
->java_source
= 1;
470 if (jcf
->java_source
)
471 return NULL
; /* FIXME */
473 return open_class (buffer
, jcf
, stream
, dep_file
);
475 if (jcf
->java_source
)
477 JCF_ZERO (jcf
); /* JCF_FINISH relies on this */
478 jcf
->java_source
= 1;
479 jcf
->filename
= xstrdup (buffer
);
480 close (fd
); /* We use STDIO for source file */
483 buffer
= (char *) open_class (buffer
, jcf
, fd
, dep_file
);
484 jcf
->classname
= xstrdup (classname
);
490 DEFUN(jcf_print_char
, (stream
, ch
),
491 FILE *stream AND
int ch
)
498 fprintf (stream
, "\\%c", ch
);
501 fprintf (stream
, "\\n");
504 fprintf (stream
, "\\t");
507 fprintf (stream
, "\\r");
510 if (ch
>= ' ' && ch
< 127)
513 fprintf (stream
, "\\%03x", ch
);
515 fprintf (stream
, "\\u%04x", ch
);
519 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
522 DEFUN(jcf_print_utf8
, (stream
, str
, length
),
523 FILE *stream AND
register const unsigned char *str AND
int length
)
525 const unsigned char * limit
= str
+ length
;
528 int ch
= UTF8_GET (str
, limit
);
531 fprintf (stream
, "\\<invalid>");
534 jcf_print_char (stream
, ch
);
538 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
541 DEFUN(jcf_print_utf8_replace
, (stream
, str
, length
, in_char
, out_char
),
542 FILE *stream AND
const unsigned char *str AND
int length
543 AND
int in_char AND
int out_char
)
545 const unsigned char *limit
= str
+ length
;
548 int ch
= UTF8_GET (str
, limit
);
551 fprintf (stream
, "\\<invalid>");
554 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
558 /* Check that all the cross-references in the constant pool are
559 valid. Returns 0 on success.
560 Otherwise, returns the index of the (first) invalid entry.
561 Only checks internal consistency, but does not check that
562 any classes, fields, or methods are valid.*/
565 DEFUN(verify_constant_pool
, (jcf
),
569 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
571 switch (JPOOL_TAG (jcf
, i
))
573 case CONSTANT_NameAndType
:
574 n
= JPOOL_USHORT2 (jcf
, i
);
575 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
576 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
578 /* ... fall through ... */
580 case CONSTANT_String
:
581 n
= JPOOL_USHORT1 (jcf
, i
);
582 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
583 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
586 case CONSTANT_Fieldref
:
587 case CONSTANT_Methodref
:
588 case CONSTANT_InterfaceMethodref
:
589 n
= JPOOL_USHORT1 (jcf
, i
);
590 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
591 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
593 n
= JPOOL_USHORT2 (jcf
, i
);
594 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
595 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
599 case CONSTANT_Double
:
603 case CONSTANT_Integer
:
605 case CONSTANT_Unicode
:
615 DEFUN(format_uint
, (buffer
, value
, base
),
616 char *buffer AND uint64 value AND
int base
)
618 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
619 char buf
[WRITE_BUF_SIZE
];
620 register char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
624 /* Now do the actual conversion, placing the result at the *end* of buf. */
625 /* Note this code does not pretend to be optimized. */
627 int digit
= value
% base
;
628 static const char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
629 *--buf_ptr
= digit_chars
[digit
];
631 } while (value
!= 0);
633 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
634 for (i
= 0; i
< chars_written
; i
++)
635 buffer
[i
] = *buf_ptr
++;
640 DEFUN(format_int
, (buffer
, value
, base
),
641 char *buffer AND jlong value AND
int base
)
646 abs_value
= -(uint64
)value
;
650 abs_value
= (uint64
) value
;
651 format_uint (buffer
, abs_value
, base
);