1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996, 97-98, 1999 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. */
30 #include "java-tree.h"
32 /* DOS brain-damage */
34 #define O_BINARY 0 /* MS-DOS brain-damage */
38 DEFUN(jcf_unexpected_eof
, (jcf
, count
),
39 JCF
*jcf AND
int count ATTRIBUTE_UNUSED
)
42 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
44 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
49 DEFUN(jcf_trim_old_input
, (jcf
),
52 int count
= jcf
->read_ptr
- jcf
->buffer
;
55 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
56 jcf
->read_ptr
-= count
;
57 jcf
->read_end
-= count
;
62 DEFUN(jcf_filbuf_from_stdio
, (jcf
, count
),
63 JCF
*jcf AND
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
= jcf
->buffer
== NULL
? ALLOC (new_size
)
73 : REALLOC (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
;
82 if ((int) fread (jcf
->read_end
, 1, count
, file
) != count
)
83 jcf_unexpected_eof (jcf
, count
);
84 jcf
->read_end
+= count
;
90 struct ZipFileCache
*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.
98 DEFUN(opendir_in_zip
, (zipfile
, is_system
),
99 const char *zipfile AND
int is_system
)
101 struct ZipFileCache
* zipf
;
104 for (zipf
= SeenZipFiles
; zipf
!= NULL
; zipf
= zipf
->next
)
106 if (strcmp (zipf
->name
, zipfile
) == 0)
110 zipf
= ALLOC (sizeof (struct ZipFileCache
) + strlen (zipfile
) + 1);
111 zipf
->next
= SeenZipFiles
;
112 zipf
->name
= (char*)(zipf
+1);
113 strcpy (zipf
->name
, zipfile
);
115 fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
119 /* A missing zip file is not considered an error.
120 We may want to re-consider that. FIXME. */
122 zipf
->z
.dir_size
= 0;
123 zipf
->z
.central_directory
= NULL
;
127 jcf_dependency_add_file (zipfile
, is_system
);
128 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
130 lseek (fd
, 0L, SEEK_SET
);
131 if (read_zip_archive (&zipf
->z
) != 0)
138 0: OK - zipmember found.
140 -2: Malformed archive.
144 DEFUN(open_in_zip
, (jcf
, zipfile
, zipmember
, is_system
),
145 JCF
*jcf AND
const char *zipfile AND
const char *zipmember
150 ZipFile
*zipf
= opendir_in_zip (zipfile
, is_system
);
158 len
= strlen (zipmember
);
160 zipd
= (struct ZipDirectory
*) zipf
->central_directory
;
161 for (i
= 0; i
< zipf
->count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
163 if (len
== zipd
->filename_length
&&
164 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
167 jcf
->buffer
= ALLOC (zipd
->size
);
168 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
169 jcf
->read_ptr
= jcf
->buffer
;
170 jcf
->read_end
= jcf
->buffer_end
;
171 jcf
->filbuf
= jcf_unexpected_eof
;
172 jcf
->filename
= xstrdup (zipfile
);
173 jcf
->classname
= xstrdup (zipmember
);
174 jcf
->zipd
= (void *)zipd
;
175 if (lseek (zipf
->fd
, zipd
->filestart
, 0) < 0
176 || read (zipf
->fd
, jcf
->buffer
, zipd
->size
) != zipd
->size
)
186 DEFUN(open_class
, (filename
, jcf
, stream
, dep_name
),
187 char *filename AND JCF
*jcf AND
FILE* stream AND
const char *dep_name
)
191 if (dep_name
!= NULL
)
192 jcf_dependency_add_file (dep_name
, 0);
195 jcf
->buffer_end
= NULL
;
196 jcf
->read_ptr
= NULL
;
197 jcf
->read_end
= NULL
;
198 jcf
->read_state
= stream
;
199 jcf
->filbuf
= jcf_filbuf_from_stdio
;
207 DEFUN(open_class
, (filename
, jcf
, fd
, dep_name
),
208 char *filename AND JCF
*jcf AND
int fd AND
const char *dep_name
)
212 struct stat stat_buf
;
213 if (fstat (fd
, &stat_buf
) != 0
214 || ! S_ISREG (stat_buf
.st_mode
))
216 perror ("Could not figure length of .class file");
219 if (dep_name
!= NULL
)
220 jcf_dependency_add_file (dep_name
, 0);
222 jcf
->buffer
= ALLOC (stat_buf
.st_size
);
223 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
224 jcf
->read_ptr
= jcf
->buffer
;
225 jcf
->read_end
= jcf
->buffer_end
;
226 jcf
->read_state
= NULL
;
227 jcf
->filename
= filename
;
228 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
230 perror ("Failed to read .class file");
234 jcf
->filbuf
= jcf_unexpected_eof
;
244 DEFUN(find_classfile
, (filename
, jcf
, dep_name
),
245 char *filename AND JCF
*jcf AND
const char *dep_name
)
248 FILE *stream
= fopen (filename
, "rb");
251 return open_class (arg
, jcf
, stream
, dep_name
);
253 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
256 return open_class (filename
, jcf
, fd
, dep_name
);
260 /* Returns a freshly malloc'd string with the fully qualified pathname
261 of the .class file for the class CLASSNAME. Returns NULL on
262 failure. If JCF != NULL, it is suitably initialized.
263 SOURCE_OK is true if we should also look for .java file. */
266 DEFUN(find_class
, (classname
, classname_length
, jcf
, source_ok
),
267 const char *classname AND
int classname_length AND JCF
*jcf AND
int source_ok
)
275 int i
, k
, java
= -1, class = -1;
276 struct stat java_buf
, class_buf
;
281 /* Allocate and zero out the buffer, since we don't explicitly put a
282 null pointer when we're copying it below. */
283 int buflen
= jcf_path_max_len () + classname_length
+ 10;
284 char *buffer
= (char *) ALLOC (buflen
);
285 bzero (buffer
, buflen
);
287 java_buffer
= (char *) alloca (buflen
);
289 jcf
->java_source
= jcf
->outofsynch
= 0;
291 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
293 const char *path_name
= jcf_path_name (entry
);
298 strcpy (buffer
, path_name
);
301 /* This is right because we know that `.zip' entries will have a
302 trailing slash. See jcf-path.c. */
305 for (k
= 0; k
< classname_length
; k
++, i
++)
307 char ch
= classname
[k
];
308 buffer
[i
] = ch
== '.' ? '/' : ch
;
310 strcpy (buffer
+i
, ".class");
312 if (jcf_path_is_zipfile (entry
))
316 buffer
[dir_len
] = '\0';
317 SOURCE_FRONTEND_DEBUG
318 (("Trying [...%s]:%s",
319 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
323 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
324 jcf_path_is_system (entry
));
327 /* Should we check if .zip is out-of-date wrt .java? */
328 buffer
[dir_len
] = '(';
329 strcpy (buffer
+i
, ".class)");
337 class = stat (buffer
, &class_buf
);
342 /* Compute name of .java file. */
344 strcpy (java_buffer
, path_name
);
345 l
= strlen (java_buffer
);
346 for (m
= 0; m
< classname_length
; ++m
)
347 java_buffer
[m
+ l
] = (classname
[m
] == '.' ? '/' : classname
[m
]);
348 strcpy (java_buffer
+ m
+ l
, ".java");
349 java
= stat (java_buffer
, &java_buf
);
355 if (! java
&& ! class && java_buf
.st_mtime
>= class_buf
.st_mtime
)
359 dep_file
= java_buffer
;
365 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
366 stream
= fopen (buffer
, "rb");
370 /* Give .java a try, if necessary */
373 strcpy (buffer
, java_buffer
);
374 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
375 stream
= fopen (buffer
, "r");
378 jcf
->java_source
= 1;
385 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
386 fd
= open (buffer
, O_RDONLY
| O_BINARY
);
390 /* Give .java a try, if necessary */
393 strcpy (buffer
, java_buffer
);
394 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
395 fd
= open (buffer
, O_RDONLY
);
398 jcf
->java_source
= 1;
408 if (jcf
->java_source
)
409 return NULL
; /* FIXME */
411 return open_class (buffer
, jcf
, stream
, dep_file
);
413 if (jcf
->java_source
)
415 JCF_ZERO (jcf
); /* JCF_FINISH relies on this */
416 jcf
->java_source
= 1;
417 jcf
->filename
= xstrdup (buffer
);
418 close (fd
); /* We use STDIO for source file */
421 buffer
= open_class (buffer
, jcf
, fd
, dep_file
);
422 jcf
->classname
= (char *) ALLOC (classname_length
+ 1);
423 strncpy (jcf
->classname
, classname
, classname_length
+ 1);
424 jcf
->classname
= xstrdup (classname
);
430 DEFUN(jcf_print_char
, (stream
, ch
),
431 FILE *stream AND
int ch
)
438 fprintf (stream
, "\\%c", ch
);
441 fprintf (stream
, "\\n");
444 fprintf (stream
, "\\t");
447 fprintf (stream
, "\\r");
450 if (ch
>= ' ' && ch
< 127)
453 fprintf (stream
, "\\%03x", ch
);
455 fprintf (stream
, "\\u%04x", ch
);
459 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
462 DEFUN(jcf_print_utf8
, (stream
, str
, length
),
463 FILE *stream AND
register const unsigned char *str AND
int length
)
465 const unsigned char * limit
= str
+ length
;
468 int ch
= UTF8_GET (str
, limit
);
471 fprintf (stream
, "\\<invalid>");
474 jcf_print_char (stream
, ch
);
478 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
481 DEFUN(jcf_print_utf8_replace
, (stream
, str
, length
, in_char
, out_char
),
482 FILE *stream AND
const unsigned char *str AND
int length
483 AND
int in_char AND
int out_char
)
486 int i
;/* FIXME - actually handle Unicode! */
487 for (i
= 0; i
< length
; i
++)
490 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
494 /* Check that all the cross-references in the constant pool are
495 valid. Returns 0 on success.
496 Otherwise, returns the index of the (first) invalid entry. */
499 DEFUN(verify_constant_pool
, (jcf
),
503 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
505 switch (JPOOL_TAG (jcf
, i
))
507 case CONSTANT_NameAndType
:
508 n
= JPOOL_USHORT2 (jcf
, i
);
509 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
510 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
512 /* ... fall through ... */
514 case CONSTANT_String
:
515 n
= JPOOL_USHORT1 (jcf
, i
);
516 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
517 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
520 case CONSTANT_Fieldref
:
521 case CONSTANT_Methodref
:
522 case CONSTANT_InterfaceMethodref
:
523 n
= JPOOL_USHORT1 (jcf
, i
);
524 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
525 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
527 n
= JPOOL_USHORT2 (jcf
, i
);
528 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
529 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
533 case CONSTANT_Double
:
537 case CONSTANT_Integer
:
539 case CONSTANT_Unicode
:
549 DEFUN(format_uint
, (buffer
, value
, base
),
550 char *buffer AND uint64 value AND
int base
)
552 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
553 char buf
[WRITE_BUF_SIZE
];
554 register char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
558 /* Now do the actual conversion, placing the result at the *end* of buf. */
559 /* Note this code does not pretend to be optimized. */
561 int digit
= value
% base
;
562 static char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
563 *--buf_ptr
= digit_chars
[digit
];
565 } while (value
!= 0);
567 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
568 for (i
= 0; i
< chars_written
; i
++)
569 buffer
[i
] = *buf_ptr
++;
574 DEFUN(format_int
, (buffer
, value
, base
),
575 char *buffer AND jlong value AND
int base
)
580 abs_value
= -(uint64
)value
;
584 abs_value
= (uint64
) value
;
585 format_uint (buffer
, abs_value
, base
);