1 /* Utility routines for finding and reading Java(TM) .class files.
2 Copyright (C) 1996, 1998 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. */
32 /* This is true if the user specified a `.java' file on the command
33 line. Otherwise it is 0. FIXME: this is temporary, until our
34 .java parser is fully working. */
35 int saw_java_source
= 0;
37 /* DOS brain-damage */
39 #define O_BINARY 0 /* MS-DOS brain-damage */
43 DEFUN(jcf_unexpected_eof
, (jcf
, count
),
44 JCF
*jcf AND
int count
)
47 fprintf (stderr
, "Premature end of .class file %s.\n", jcf
->filename
);
49 fprintf (stderr
, "Premature end of .class file <stdin>.\n");
54 DEFUN(jcf_trim_old_input
, (jcf
),
57 int count
= jcf
->read_ptr
- jcf
->buffer
;
60 memmove (jcf
->buffer
, jcf
->read_ptr
, jcf
->read_end
- jcf
->read_ptr
);
61 jcf
->read_ptr
-= count
;
62 jcf
->read_end
-= count
;
67 DEFUN(jcf_filbuf_from_stdio
, (jcf
, count
),
68 JCF
*jcf AND
int count
)
70 FILE *file
= (FILE*) (jcf
->read_state
);
71 if (count
> jcf
->buffer_end
- jcf
->read_ptr
)
73 JCF_u4 old_read_ptr
= jcf
->read_ptr
- jcf
->buffer
;
74 JCF_u4 old_read_end
= jcf
->read_end
- jcf
->buffer
;
75 JCF_u4 old_size
= jcf
->buffer_end
- jcf
->buffer
;
76 JCF_u4 new_size
= (old_size
== 0 ? 2000 : 2 * old_size
) + count
;
77 unsigned char *new_buffer
= jcf
->buffer
== NULL
? ALLOC (new_size
)
78 : REALLOC (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
;
87 if (fread (jcf
->read_end
, 1, count
, file
) != count
)
88 jcf_unexpected_eof (jcf
, count
);
89 jcf
->read_end
+= count
;
95 struct ZipFileCache
*SeenZipFiles
= NULL
;
98 DEFUN(open_in_zip
, (jcf
, zipfile
, zipmember
),
99 JCF
*jcf AND
const char *zipfile AND
const char *zipmember
102 struct ZipFileCache
* zipf
;
105 for (zipf
= SeenZipFiles
; ; zipf
= zipf
->next
)
110 int fd
= open (zipfile
, O_RDONLY
| O_BINARY
);
111 jcf_dependency_add_file (zipfile
, is_system
);
112 if (read (fd
, magic
, 4) != 4 || GET_u4 (magic
) != (JCF_u4
)ZIPMAGIC
)
114 lseek (fd
, 0L, SEEK_SET
);
115 zipf
= ALLOC (sizeof (struct ZipFileCache
) + strlen (zipfile
) + 1);
116 zipf
->next
= SeenZipFiles
;
117 zipf
->name
= (char*)(zipf
+1);
118 strcpy (zipf
->name
, zipfile
);
123 /* A missing zip file is not considered an error. */
125 zipf
->z
.dir_size
= 0;
126 zipf
->z
.central_directory
= NULL
;
131 if (read_zip_archive (&zipf
->z
) != 0)
132 return -2; /* This however should be an error - FIXME */
136 if (strcmp (zipf
->name
, zipfile
) == 0)
143 len
= strlen (zipmember
);
145 zipd
= (struct ZipDirectory
*) zipf
->z
.central_directory
;
146 for (i
= 0; i
< zipf
->z
.count
; i
++, zipd
= ZIPDIR_NEXT (zipd
))
148 if (len
== zipd
->filename_length
&&
149 strncmp (ZIPDIR_FILENAME (zipd
), zipmember
, len
) == 0)
152 jcf
->buffer
= ALLOC (zipd
->size
);
153 jcf
->buffer_end
= jcf
->buffer
+ zipd
->size
;
154 jcf
->read_ptr
= jcf
->buffer
;
155 jcf
->read_end
= jcf
->buffer_end
;
156 jcf
->filbuf
= jcf_unexpected_eof
;
157 jcf
->filename
= strdup (zipfile
);
158 jcf
->classname
= strdup (zipmember
);
159 jcf
->zipd
= (void *)zipd
;
160 if (lseek (zipf
->z
.fd
, zipd
->filestart
, 0) < 0
161 || read (zipf
->z
.fd
, jcf
->buffer
, zipd
->size
) != zipd
->size
)
171 DEFUN(open_class
, (filename
, jcf
, stream
, dep_name
),
172 char *filename AND JCF
*jcf AND
FILE* stream AND
char *dep_name
)
176 if (dep_name
!= NULL
)
177 jcf_dependency_add_file (dep_name
, 0);
180 jcf
->buffer_end
= NULL
;
181 jcf
->read_ptr
= NULL
;
182 jcf
->read_end
= NULL
;
183 jcf
->read_state
= stream
;
184 jcf
->filbuf
= jcf_filbuf_from_stdio
;
192 DEFUN(open_class
, (filename
, jcf
, fd
, dep_name
),
193 char *filename AND JCF
*jcf AND
int fd AND
char *dep_name
)
197 struct stat stat_buf
;
198 if (fstat (fd
, &stat_buf
) != 0
199 || ! S_ISREG (stat_buf
.st_mode
))
201 perror ("Could not figure length of .class file");
204 if (dep_name
!= NULL
)
205 jcf_dependency_add_file (dep_name
, 0);
207 jcf
->buffer
= ALLOC (stat_buf
.st_size
);
208 jcf
->buffer_end
= jcf
->buffer
+ stat_buf
.st_size
;
209 jcf
->read_ptr
= jcf
->buffer
;
210 jcf
->read_end
= jcf
->buffer_end
;
211 jcf
->read_state
= NULL
;
212 jcf
->filename
= filename
;
213 if (read (fd
, jcf
->buffer
, stat_buf
.st_size
) != stat_buf
.st_size
)
215 perror ("Failed to read .class file");
219 jcf
->filbuf
= jcf_unexpected_eof
;
229 DEFUN(find_classfile
, (filename
, jcf
, dep_name
),
230 char *filename AND JCF
*jcf AND
char *dep_name
)
233 FILE *stream
= fopen (filename
, "rb");
236 return open_class (arg
, jcf
, stream
, dep_name
);
238 int fd
= open (filename
, O_RDONLY
| O_BINARY
);
241 return open_class (filename
, jcf
, fd
, dep_name
);
245 /* Returns a freshly malloc'd string with the fully qualified pathname
246 of the .class file for the class CLASSNAME. Returns NULL on
247 failure. If JCF != NULL, it is suitably initialized. With
248 DO_CLASS_FILE set to 1, search a .class/.java file named after
249 CLASSNAME, otherwise, search a ZIP directory entry named after
253 DEFUN(find_class
, (classname
, classname_length
, jcf
, do_class_file
),
254 const char *classname AND
int classname_length AND JCF
*jcf AND
int do_class_file
)
262 int i
, k
, java
, class;
263 struct stat java_buf
, class_buf
;
265 void *entry
, *java_entry
;
268 /* Allocate and zero out the buffer, since we don't explicitly put a
269 null pointer when we're copying it below. */
270 int buflen
= jcf_path_max_len () + classname_length
+ 10;
271 char *buffer
= (char *) ALLOC (buflen
);
272 bzero (buffer
, buflen
);
274 java_buffer
= (char *) alloca (buflen
);
276 jcf
->java_source
= jcf
->outofsynch
= 0;
278 for (entry
= jcf_path_start (); entry
!= NULL
; entry
= jcf_path_next (entry
))
282 strcpy (buffer
, jcf_path_name (entry
));
287 for (k
= 0; k
< classname_length
; k
++, i
++)
289 char ch
= classname
[k
];
290 buffer
[i
] = ch
== '.' ? '/' : ch
;
293 strcpy (buffer
+i
, ".class");
295 if (jcf_path_is_zipfile (entry
))
300 strcpy (buffer
+i
, "/");
301 buffer
[dir_len
] = '\0';
303 SOURCE_FRONTEND_DEBUG
304 (("Trying [...%s]:%s",
305 &buffer
[dir_len
-(dir_len
> 15 ? 15 : dir_len
)],
309 err_code
= open_in_zip (jcf
, buffer
, buffer
+dir_len
+1,
310 jcf_path_is_system (entry
));
314 jcf
->seen_in_zip
= 1;
317 buffer
[dir_len
] = '(';
318 strcpy (buffer
+i
, ".class)");
328 /* If we do directories, do them here */
331 struct stat dir_buff
;
333 buffer
[i
] = '\0'; /* Was previously unterminated here. */
334 if (!(dir
= stat (buffer
, &dir_buff
)))
336 jcf
->seen_in_zip
= 0;
341 class = stat (buffer
, &class_buf
);
342 /* This is a little odd: if we didn't find the class file, we
343 can just skip to the next iteration. However, if this is the
344 last iteration, then we want to search for the .java file as
345 well. It was a little easier to implement this with two
346 loops, as opposed to checking for each type of file each time
348 if (class && jcf_path_next (entry
))
351 /* Check for out of synch .class/.java files. */
353 for (java_entry
= jcf_path_start ();
354 java
&& java_entry
!= NULL
;
355 java_entry
= jcf_path_next (java_entry
))
359 if (jcf_path_is_zipfile (java_entry
))
362 /* Compute name of .java file. */
363 strcpy (java_buffer
, jcf_path_name (java_entry
));
364 l
= strlen (java_buffer
);
365 for (m
= 0; m
< classname_length
; ++m
)
367 java_buffer
[m
+ l
] = (classname
[m
] == '.'
371 strcpy (java_buffer
+ m
+ l
, ".java");
373 /* FIXME: until the `.java' parser is fully working, we only
374 look for a .java file when one was mentioned on the
375 command line. This lets us test the .java parser fairly
376 easily, without compromising our ability to use the
377 .class parser without fear. */
379 java
= stat (java_buffer
, &java_buf
);
382 if (! java
&& ! class && java_buf
.st_mtime
>= class_buf
.st_mtime
)
386 dep_file
= java_buffer
;
392 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
393 stream
= fopen (buffer
, "rb");
397 /* Give .java a try, if necessary */
400 strcpy (buffer
, java_buffer
);
401 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
402 stream
= fopen (buffer
, "r");
405 jcf
->java_source
= 1;
412 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
413 fd
= open (buffer
, O_RDONLY
| O_BINARY
);
417 /* Give .java a try, if necessary */
420 strcpy (buffer
, java_buffer
);
421 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer
));
422 fd
= open (buffer
, O_RDONLY
);
425 jcf
->java_source
= 1;
435 if (jcf
->java_source
)
436 return NULL
; /* FIXME */
438 return open_class (buffer
, jcf
, stream
, dep_file
);
440 if (jcf
->java_source
)
442 JCF_ZERO (jcf
); /* JCF_FINISH relies on this */
443 jcf
->java_source
= 1;
444 jcf
->filename
= (char *) strdup (buffer
);
445 close (fd
); /* We use STDIO for source file */
447 else if (do_class_file
)
448 buffer
= open_class (buffer
, jcf
, fd
, dep_file
);
449 jcf
->classname
= (char *) ALLOC (classname_length
+ 1);
450 strncpy (jcf
->classname
, classname
, classname_length
+ 1);
451 jcf
->classname
= (char *) strdup (classname
);
457 DEFUN(jcf_print_char
, (stream
, ch
),
458 FILE *stream AND
int ch
)
465 fprintf (stream
, "\\%c", ch
);
468 fprintf (stream
, "\\n");
471 fprintf (stream
, "\\t");
474 fprintf (stream
, "\\r");
477 if (ch
>= ' ' && ch
< 127)
480 fprintf (stream
, "\\%03x", ch
);
482 fprintf (stream
, "\\u%04x", ch
);
486 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
489 DEFUN(jcf_print_utf8
, (stream
, str
, length
),
490 FILE *stream AND
register unsigned char *str AND
int length
)
492 unsigned char* limit
= str
+ length
;
495 int ch
= UTF8_GET (str
, limit
);
498 fprintf (stream
, "\\<invalid>");
501 jcf_print_char (stream
, ch
);
505 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
508 DEFUN(jcf_print_utf8_replace
, (stream
, str
, length
, in_char
, out_char
),
509 FILE *stream AND
unsigned char *str AND
int length
510 AND
int in_char AND
int out_char
)
513 int i
;/* FIXME - actually handle Unicode! */
514 for (i
= 0; i
< length
; i
++)
517 jcf_print_char (stream
, ch
== in_char
? out_char
: ch
);
521 /* Check that all the cross-references in the constant pool are
522 valid. Returns 0 on success.
523 Otherwise, returns the index of the (first) invalid entry. */
526 DEFUN(verify_constant_pool
, (jcf
),
530 for (i
= 1; i
< JPOOL_SIZE (jcf
); i
++)
532 switch (JPOOL_TAG (jcf
, i
))
534 case CONSTANT_NameAndType
:
535 n
= JPOOL_USHORT2 (jcf
, i
);
536 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
537 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
539 /* ... fall through ... */
541 case CONSTANT_String
:
542 n
= JPOOL_USHORT1 (jcf
, i
);
543 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
544 || JPOOL_TAG (jcf
, n
) != CONSTANT_Utf8
)
547 case CONSTANT_Fieldref
:
548 case CONSTANT_Methodref
:
549 case CONSTANT_InterfaceMethodref
:
550 n
= JPOOL_USHORT1 (jcf
, i
);
551 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
552 || JPOOL_TAG (jcf
, n
) != CONSTANT_Class
)
554 n
= JPOOL_USHORT2 (jcf
, i
);
555 if (n
<= 0 || n
>= JPOOL_SIZE(jcf
)
556 || JPOOL_TAG (jcf
, n
) != CONSTANT_NameAndType
)
560 case CONSTANT_Double
:
564 case CONSTANT_Integer
:
566 case CONSTANT_Unicode
:
576 DEFUN(format_uint
, (buffer
, value
, base
),
577 char *buffer AND uint64 value AND
int base
)
579 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
580 char buf
[WRITE_BUF_SIZE
];
581 register char *buf_ptr
= buf
+WRITE_BUF_SIZE
; /* End of buf. */
585 /* Now do the actual conversion, placing the result at the *end* of buf. */
586 /* Note this code does not pretend to be optimized. */
588 int digit
= value
% base
;
589 static char digit_chars
[] = "0123456789abcdefghijklmnopqrstuvwxyz";
590 *--buf_ptr
= digit_chars
[digit
];
592 } while (value
!= 0);
594 chars_written
= buf
+WRITE_BUF_SIZE
- buf_ptr
;
595 for (i
= 0; i
< chars_written
; i
++)
596 buffer
[i
] = *buf_ptr
++;
601 DEFUN(format_int
, (buffer
, value
, base
),
602 char *buffer AND jlong value AND
int base
)
607 abs_value
= -(uint64
)value
;
611 abs_value
= (uint64
) value
;
612 format_uint (buffer
, abs_value
, base
);