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. */
28 #define ENABLE_UNZIP 1
34 /* DOS brain-damage */
36 #define O_BINARY 0 /* MS-DOS brain-damage */
42 DEFUN(jcf_unexpected_eof, (jcf, count),
43 JCF *jcf AND int count)
46 fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
48 fprintf (stderr, "Premature end of .class file <stdin>.\n");
53 DEFUN(jcf_trim_old_input, (jcf),
56 int count = jcf->read_ptr - jcf->buffer;
59 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
60 jcf->read_ptr -= count;
61 jcf->read_end -= count;
66 DEFUN(jcf_filbuf_from_stdio, (jcf, count),
67 JCF *jcf AND 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 = jcf->buffer == NULL ? ALLOC (new_size)
77 : REALLOC (jcf->buffer, new_size);
78 jcf->buffer = new_buffer;
79 jcf->buffer_end = new_buffer + new_size;
80 jcf->read_ptr = new_buffer + old_read_ptr;
81 jcf->read_end = new_buffer + old_read_end;
83 count -= jcf->read_end - jcf->read_ptr;
86 if (fread (jcf->read_end, 1, count, file) != count)
87 jcf_unexpected_eof (jcf, count);
88 jcf->read_end += count;
95 struct ZipFileCache *SeenZipFiles = NULL;
98 DEFUN(open_in_zip, (jcf,
100 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, 0); /* FIXME: system file? */
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)
168 #endif /* ENABLE_UNZIP */
172 DEFUN(open_class, (filename, jcf, stream, dep_name),
173 char *filename AND JCF *jcf AND FILE* stream AND char *dep_name)
177 if (dep_name != NULL)
178 jcf_dependency_add_file (dep_name, 0);
181 jcf->buffer_end = NULL;
182 jcf->read_ptr = NULL;
183 jcf->read_end = NULL;
184 jcf->read_state = stream;
185 jcf->filbuf = jcf_filbuf_from_stdio;
193 DEFUN(open_class, (filename, jcf, fd, dep_name),
194 char *filename AND JCF *jcf AND int fd AND char *dep_name)
198 struct stat stat_buf;
199 if (fstat (fd, &stat_buf) != 0
200 || ! S_ISREG (stat_buf.st_mode))
202 perror ("Could not figure length of .class file");
205 if (dep_name != NULL)
206 jcf_dependency_add_file (dep_name, 0);
208 jcf->buffer = ALLOC (stat_buf.st_size);
209 jcf->buffer_end = jcf->buffer + stat_buf.st_size;
210 jcf->read_ptr = jcf->buffer;
211 jcf->read_end = jcf->buffer_end;
212 jcf->read_state = NULL;
213 jcf->filename = filename;
214 if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
216 perror ("Failed to read .class file");
220 jcf->filbuf = jcf_unexpected_eof;
230 DEFUN(find_classfile, (filename, jcf, dep_name),
231 char *filename AND JCF *jcf AND char *dep_name)
234 FILE *stream = fopen (filename, "rb");
237 return open_class (arg, jcf, stream, dep_name);
239 int fd = open (filename, O_RDONLY | O_BINARY);
242 return open_class (filename, jcf, fd, dep_name);
246 /* Returns a freshly malloc'd string with the fully qualified pathname
247 of the .class file for the class CLASSNAME. Returns NULL on
248 failure. If JCF != NULL, it is suitably initialized. With
249 DO_CLASS_FILE set to 1, search a .class/.java file named after
250 CLASSNAME, otherwise, search a ZIP directory entry named after
254 DEFUN(find_class, (classname, classname_length, jcf, do_class_file),
255 const char *classname AND int classname_length AND JCF *jcf AND int do_class_file)
263 int i, j, k, java, class;
264 struct stat java_buf, class_buf;
267 /* A temporary buffer that we grow to be large enough to hold
268 whatever class name we're working on. */
269 static int temp_len = 0;
270 static char *temp_buffer = NULL;
272 /* Allocate and zero out the buffer, since we don't explicitly put a
273 null pointer when we're copying it below. */
274 int buflen = strlen (classpath) + classname_length + 10;
275 char *buffer = (char *) ALLOC (buflen);
276 bzero (buffer, buflen);
278 if (buflen > temp_len)
281 if (temp_buffer == NULL)
282 temp_buffer = (char *) ALLOC (temp_len);
284 temp_buffer = (char *) REALLOC (temp_buffer, temp_len);
287 jcf->java_source = jcf->outofsynch = 0;
288 for (j = 0; classpath[j] != '\0'; )
290 for (i = 0; classpath[j] != ':' && classpath[j] != '\0'; i++, j++)
291 buffer[i] = classpath[j];
292 if (classpath[j] == ':')
294 if (i > 0) /* Empty directory is redundant */
297 if (buffer[i-1] != '/')
300 for (k = 0; k < classname_length; k++, i++)
302 char ch = classname[k];
303 buffer[i] = ch == '.' ? '/' : ch;
306 strcpy (buffer+i, ".class");
309 && buffer[dir_len-4] == '.' && buffer[dir_len-3] == 'z'
310 && buffer[dir_len-2] == 'i' && buffer[dir_len-1] == 'p')
315 strcpy (buffer+i, "/");
316 buffer[dir_len] = '\0';
318 SOURCE_FRONTEND_DEBUG
319 (("Trying [...%s]:%s",
320 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
324 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1);
328 jcf->seen_in_zip = 1;
331 buffer[dir_len] = '(';
332 strcpy (buffer+i, ".class)");
342 /* If we do directories, do them here */
345 struct stat dir_buff;
347 buffer[i] = '\0'; /* Was previously unterminated here. */
348 if (!(dir = stat (buffer, &dir_buff)))
350 jcf->seen_in_zip = 0;
355 /* Check for out of synch .class/.java files */
356 class = stat (buffer, &class_buf);
357 strcpy (buffer+i, ".java");
358 /* Stash the name of the .java file in the temp buffer. */
359 strcpy (temp_buffer, buffer);
360 java = stat (buffer, &java_buf);
361 if ((!java && !class) && java_buf.st_mtime >= class_buf.st_mtime)
365 dep_file = temp_buffer;
371 strcpy (buffer+i, ".class");
372 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
373 stream = fopen (buffer, "rb");
377 /* Give .java a try, if necessary */
380 strcpy (buffer+i, ".java");
381 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
382 stream = fopen (buffer, "r");
385 jcf->java_source = 1;
392 strcpy (buffer+i, ".class");
393 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
394 fd = open (buffer, O_RDONLY | O_BINARY);
398 /* Give .java a try, if necessary */
402 strcpy (buffer+i, ".java");
403 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
404 fd = open (buffer, O_RDONLY | O_BINARY);
407 jcf->java_source = 1;
418 if (jcf->java_source)
419 return NULL; /* FIXME */
421 return open_class (buffer, jcf, stream, dep_file);
423 if (jcf->java_source)
425 JCF_ZERO (jcf); /* JCF_FINISH relies on this */
426 jcf->java_source = 1;
427 jcf->filename = (char *) strdup (buffer);
428 close (fd); /* We use STDIO for source file */
430 else if (do_class_file)
431 buffer = open_class (buffer, jcf, fd, dep_file);
432 jcf->classname = (char *) ALLOC (classname_length + 1);
433 strncpy (jcf->classname, classname, classname_length + 1);
434 jcf->classname = (char *) strdup (classname);
440 DEFUN(jcf_print_char, (stream, ch),
441 FILE *stream AND int ch)
448 fprintf (stream, "\\%c", ch);
451 fprintf (stream, "\\n");
454 fprintf (stream, "\\t");
457 fprintf (stream, "\\r");
460 if (ch >= ' ' && ch < 127)
463 fprintf (stream, "\\%03x", ch);
465 fprintf (stream, "\\u%04x", ch);
469 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
472 DEFUN(jcf_print_utf8, (stream, str, length),
473 FILE *stream AND register unsigned char *str AND int length)
475 unsigned char* limit = str + length;
478 int ch = UTF8_GET (str, limit);
481 fprintf (stream, "\\<invalid>");
484 jcf_print_char (stream, ch);
488 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
491 DEFUN(jcf_print_utf8_replace, (stream, str, length, in_char, out_char),
492 FILE *stream AND unsigned char *str AND int length
493 AND int in_char AND int out_char)
496 int i;/* FIXME - actually handle Unicode! */
497 for (i = 0; i < length; i++)
500 jcf_print_char (stream, ch == in_char ? out_char : ch);
504 /* Check that all the cross-references in the constant pool are
505 valid. Returns 0 on success.
506 Otherwise, returns the index of the (first) invalid entry. */
509 DEFUN(verify_constant_pool, (jcf),
513 for (i = 1; i < JPOOL_SIZE (jcf); i++)
515 switch (JPOOL_TAG (jcf, i))
517 case CONSTANT_NameAndType:
518 n = JPOOL_USHORT2 (jcf, i);
519 if (n <= 0 || n >= JPOOL_SIZE(jcf)
520 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
522 /* ... fall through ... */
524 case CONSTANT_String:
525 n = JPOOL_USHORT1 (jcf, i);
526 if (n <= 0 || n >= JPOOL_SIZE(jcf)
527 || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
530 case CONSTANT_Fieldref:
531 case CONSTANT_Methodref:
532 case CONSTANT_InterfaceMethodref:
533 n = JPOOL_USHORT1 (jcf, i);
534 if (n <= 0 || n >= JPOOL_SIZE(jcf)
535 || JPOOL_TAG (jcf, n) != CONSTANT_Class)
537 n = JPOOL_USHORT2 (jcf, i);
538 if (n <= 0 || n >= JPOOL_SIZE(jcf)
539 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
543 case CONSTANT_Double:
547 case CONSTANT_Integer:
549 case CONSTANT_Unicode:
559 DEFUN(format_uint, (buffer, value, base),
560 char *buffer AND uint64 value AND int base)
562 #define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
563 char buf[WRITE_BUF_SIZE];
564 register char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
568 /* Now do the actual conversion, placing the result at the *end* of buf. */
569 /* Note this code does not pretend to be optimized. */
571 int digit = value % base;
572 static char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
573 *--buf_ptr = digit_chars[digit];
575 } while (value != 0);
577 chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
578 for (i = 0; i < chars_written; i++)
579 buffer[i] = *buf_ptr++;
584 DEFUN(format_int, (buffer, value, base),
585 char *buffer AND jlong value AND int base)
590 abs_value = -(uint64)value;
594 abs_value = (uint64) value;
595 format_uint (buffer, abs_value, base);