* tree.c (walk_tree): Don't recurse into DECL_INITIAL or DECL_SIZE
[official-gcc.git] / gcc / java / jcf-io.c
blob2d43a513e8eee4739f9bc4ff9f20c584f693477a
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)
7 any later version.
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. */
25 #include "config.h"
26 #include "system.h"
28 #include "jcf.h"
29 #include "tree.h"
30 #include "java-tree.h"
32 /* DOS brain-damage */
33 #ifndef O_BINARY
34 #define O_BINARY 0 /* MS-DOS brain-damage */
35 #endif
37 int
38 DEFUN(jcf_unexpected_eof, (jcf, count),
39 JCF *jcf AND int count ATTRIBUTE_UNUSED)
41 if (jcf->filename)
42 fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
43 else
44 fprintf (stderr, "Premature end of .class file <stdin>.\n");
45 exit (-1);
48 void
49 DEFUN(jcf_trim_old_input, (jcf),
50 JCF *jcf)
52 int count = jcf->read_ptr - jcf->buffer;
53 if (count > 0)
55 memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
56 jcf->read_ptr -= count;
57 jcf->read_end -= count;
61 int
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;
80 if (count <= 0)
81 return 0;
82 if ((int) fread (jcf->read_end, 1, count, file) != count)
83 jcf_unexpected_eof (jcf, count);
84 jcf->read_end += count;
85 return 0;
88 #include "zipfile.h"
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.
97 ZipFile *
98 DEFUN(opendir_in_zip, (zipfile, is_system),
99 const char *zipfile AND int is_system)
101 struct ZipFileCache* zipf;
102 char magic [4];
103 int fd;
104 for (zipf = SeenZipFiles; zipf != NULL; zipf = zipf->next)
106 if (strcmp (zipf->name, zipfile) == 0)
107 return &zipf->z;
110 zipf = ALLOC (sizeof (struct ZipFileCache) + strlen (zipfile) + 1);
111 zipf->next = SeenZipFiles;
112 zipf->name = (char*)(zipf+1);
113 strcpy (zipf->name, zipfile);
114 SeenZipFiles = zipf;
115 fd = open (zipfile, O_RDONLY | O_BINARY);
116 zipf->z.fd = fd;
117 if (fd < 0)
119 /* A missing zip file is not considered an error.
120 We may want to re-consider that. FIXME. */
121 zipf->z.count = 0;
122 zipf->z.dir_size = 0;
123 zipf->z.central_directory = NULL;
125 else
127 jcf_dependency_add_file (zipfile, is_system);
128 if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
129 return NULL;
130 lseek (fd, 0L, SEEK_SET);
131 if (read_zip_archive (&zipf->z) != 0)
132 return NULL;
134 return &zipf->z;
137 /* Returns:
138 0: OK - zipmember found.
139 -1: Not 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
146 AND int is_system)
148 ZipDirectory *zipd;
149 int i, len;
150 ZipFile *zipf = opendir_in_zip (zipfile, is_system);
152 if (zipf == NULL)
153 return -2;
155 if (!zipmember)
156 return 0;
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)
166 JCF_ZERO (jcf);
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)
177 return -2;
178 return 0;
181 return -1;
184 #if JCF_USE_STDIO
185 char*
186 DEFUN(open_class, (filename, jcf, stream, dep_name),
187 char *filename AND JCF *jcf AND FILE* stream AND const char *dep_name)
189 if (jcf)
191 if (dep_name != NULL)
192 jcf_dependency_add_file (dep_name, 0);
193 JCF_ZERO (jcf);
194 jcf->buffer = NULL;
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;
201 else
202 fclose (stream);
203 return filename;
205 #else
206 char*
207 DEFUN(open_class, (filename, jcf, fd, dep_name),
208 char *filename AND JCF *jcf AND int fd AND const char *dep_name)
210 if (jcf)
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");
217 return NULL;
219 if (dep_name != NULL)
220 jcf_dependency_add_file (dep_name, 0);
221 JCF_ZERO (jcf);
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");
231 return NULL;
233 close (fd);
234 jcf->filbuf = jcf_unexpected_eof;
236 else
237 close (fd);
238 return filename;
240 #endif
243 const char *
244 DEFUN(find_classfile, (filename, jcf, dep_name),
245 char *filename AND JCF *jcf AND const char *dep_name)
247 #if JCF_USE_STDIO
248 FILE *stream = fopen (filename, "rb");
249 if (stream == NULL)
250 return NULL;
251 return open_class (arg, jcf, stream, dep_name);
252 #else
253 int fd = open (filename, O_RDONLY | O_BINARY);
254 if (fd < 0)
255 return NULL;
256 return open_class (filename, jcf, fd, dep_name);
257 #endif
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. */
265 const char *
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)
270 #if JCF_USE_STDIO
271 FILE *stream;
272 #else
273 int fd;
274 #endif
275 int i, k, java = -1, class = -1;
276 struct stat java_buf, class_buf;
277 char *dep_file;
278 void *entry;
279 char *java_buffer;
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);
294 if (class != 0)
296 int dir_len;
298 strcpy (buffer, path_name);
299 i = strlen (buffer);
301 /* This is right because we know that `.zip' entries will have a
302 trailing slash. See jcf-path.c. */
303 dir_len = i - 1;
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))
314 int err_code;
315 JCF _jcf;
316 buffer[dir_len] = '\0';
317 SOURCE_FRONTEND_DEBUG
318 (("Trying [...%s]:%s",
319 &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
320 buffer+dir_len+1));
321 if (jcf == NULL)
322 jcf = &_jcf;
323 err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
324 jcf_path_is_system (entry));
325 if (err_code == 0)
327 /* Should we check if .zip is out-of-date wrt .java? */
328 buffer[dir_len] = '(';
329 strcpy (buffer+i, ".class)");
330 if (jcf == &_jcf)
331 JCF_FINISH (jcf);
332 return buffer;
334 else
335 continue;
337 class = stat (buffer, &class_buf);
340 if (source_ok)
342 /* Compute name of .java file. */
343 int l, m;
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);
350 if (java == 0)
351 break;
355 if (! java && ! class && java_buf.st_mtime >= class_buf.st_mtime)
356 jcf->outofsynch = 1;
358 if (! java)
359 dep_file = java_buffer;
360 else
361 dep_file = buffer;
362 #if JCF_USE_STDIO
363 if (!class)
365 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
366 stream = fopen (buffer, "rb");
367 if (stream)
368 goto found;
370 /* Give .java a try, if necessary */
371 if (!java)
373 strcpy (buffer, java_buffer);
374 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
375 stream = fopen (buffer, "r");
376 if (stream)
378 jcf->java_source = 1;
379 goto found;
382 #else
383 if (!class)
385 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
386 fd = open (buffer, O_RDONLY | O_BINARY);
387 if (fd >= 0)
388 goto found;
390 /* Give .java a try, if necessary */
391 if (!java)
393 strcpy (buffer, java_buffer);
394 SOURCE_FRONTEND_DEBUG (("Trying %s", buffer));
395 fd = open (buffer, O_RDONLY);
396 if (fd >= 0)
398 jcf->java_source = 1;
399 goto found;
402 #endif
404 free (buffer);
405 return NULL;
406 found:
407 #if JCF_USE_STDIO
408 if (jcf->java_source)
409 return NULL; /* FIXME */
410 else
411 return open_class (buffer, jcf, stream, dep_file);
412 #else
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 */
420 else
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);
425 return buffer;
426 #endif
429 void
430 DEFUN(jcf_print_char, (stream, ch),
431 FILE *stream AND int ch)
433 switch (ch)
435 case '\'':
436 case '\\':
437 case '\"':
438 fprintf (stream, "\\%c", ch);
439 break;
440 case '\n':
441 fprintf (stream, "\\n");
442 break;
443 case '\t':
444 fprintf (stream, "\\t");
445 break;
446 case '\r':
447 fprintf (stream, "\\r");
448 break;
449 default:
450 if (ch >= ' ' && ch < 127)
451 putc (ch, stream);
452 else if (ch < 256)
453 fprintf (stream, "\\%03x", ch);
454 else
455 fprintf (stream, "\\u%04x", ch);
459 /* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
461 void
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;
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);
478 /* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
480 void
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++)
489 int ch = str[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),
500 JCF *jcf)
502 int i, n;
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)
511 return i;
512 /* ... fall through ... */
513 case CONSTANT_Class:
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)
518 return i;
519 break;
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)
526 return i;
527 n = JPOOL_USHORT2 (jcf, i);
528 if (n <= 0 || n >= JPOOL_SIZE(jcf)
529 || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
530 return i;
531 break;
532 case CONSTANT_Long:
533 case CONSTANT_Double:
534 i++;
535 break;
536 case CONSTANT_Float:
537 case CONSTANT_Integer:
538 case CONSTANT_Utf8:
539 case CONSTANT_Unicode:
540 break;
541 default:
542 return i;
545 return 0;
548 void
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. */
555 int chars_written;
556 int i;
558 /* Now do the actual conversion, placing the result at the *end* of buf. */
559 /* Note this code does not pretend to be optimized. */
560 do {
561 int digit = value % base;
562 static char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
563 *--buf_ptr = digit_chars[digit];
564 value /= base;
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++;
570 buffer[i] = 0;
573 void
574 DEFUN(format_int, (buffer, value, base),
575 char *buffer AND jlong value AND int base)
577 uint64 abs_value;
578 if (value < 0)
580 abs_value = -(uint64)value;
581 *buffer++ = '-';
583 else
584 abs_value = (uint64) value;
585 format_uint (buffer, abs_value, base);