OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [gcc/] [java/] [jcf-io.c] - Blame information for rev 767

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 715 jeremybenn
/* Utility routines for finding and reading Java(TM) .class files.
2
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
3
   2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
4
 
5
This file is part of GCC.
6
 
7
GCC is free software; you can redistribute it and/or modify
8
it under the terms of the GNU General Public License as published by
9
the Free Software Foundation; either version 3, or (at your option)
10
any later version.
11
 
12
GCC is distributed in the hope that it will be useful,
13
but WITHOUT ANY WARRANTY; without even the implied warranty of
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with GCC; see the file COPYING3.  If not see
19
<http://www.gnu.org/licenses/>.
20
 
21
Java and all Java-based marks are trademarks or registered trademarks
22
of Sun Microsystems, Inc. in the United States and other countries.
23
The Free Software Foundation is independent of Sun Microsystems, Inc.  */
24
 
25
/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
26
 
27
#include "config.h"
28
#include "system.h"
29
#include "coretypes.h"
30
 
31
#include "jcf.h"
32
#include "tree.h"
33
#include "java-tree.h"
34
#include "hashtab.h"
35
#include <dirent.h>
36
 
37
#include "zlib.h"
38
 
39
int
40
jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
41
{
42
  if (jcf->filename)
43
    fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
44
  else
45
    fprintf (stderr, "Premature end of .class file <stdin>.\n");
46
  exit (-1);
47
}
48
 
49
void
50
jcf_trim_old_input (JCF *jcf)
51
{
52
  int count = jcf->read_ptr - jcf->buffer;
53
  if (count > 0)
54
    {
55
      memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
56
      jcf->read_ptr -= count;
57
      jcf->read_end -= count;
58
    }
59
}
60
 
61
int
62
jcf_filbuf_from_stdio (JCF *jcf, int count)
63
{
64
  FILE *file = (FILE*) (jcf->read_state);
65
  if (count > jcf->buffer_end - jcf->read_ptr)
66
    {
67
      JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
68
      JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
69
      JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
70
      JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
71
      unsigned char *new_buffer
72
        = jcf->buffer == NULL ? XNEWVAR (unsigned char, new_size)
73
        : XRESIZEVAR (unsigned char, 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;
78
    }
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;
86
}
87
 
88
#include "zipfile.h"
89
 
90
struct ZipFile *SeenZipFiles = NULL;
91
 
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.
95
*/
96
 
97
ZipFile *
98
opendir_in_zip (const char *zipfile, int is_system)
99
{
100
  struct ZipFile* zipf;
101
  char magic [4];
102
  int fd;
103
  for (zipf = SeenZipFiles;  zipf != NULL;  zipf = zipf->next)
104
    {
105
      if (strcmp (zipf->name, zipfile) == 0)
106
        return zipf;
107
    }
108
 
109
  zipf = XNEWVAR (struct ZipFile, sizeof (struct ZipFile) + strlen (zipfile) + 1);
110
  zipf->next = SeenZipFiles;
111
  zipf->name = (char*)(zipf+1);
112
  strcpy (zipf->name, zipfile);
113
  fd = open (zipfile, O_RDONLY | O_BINARY);
114
  zipf->fd = fd;
115
  if (fd < 0)
116
    {
117
      /* A missing zip file is not considered an error.
118
       We may want to re-consider that.  FIXME. */
119
      zipf->count = 0;
120
      zipf->dir_size = 0;
121
      zipf->central_directory = NULL;
122
    }
123
  else
124
    {
125
      jcf_dependency_add_file (zipfile, is_system);
126
      if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
127
        {
128
          free (zipf);
129
          close (fd);
130
          return NULL;
131
        }
132
      lseek (fd, 0L, SEEK_SET);
133
      if (read_zip_archive (zipf) != 0)
134
        {
135
          free (zipf);
136
          close (fd);
137
          return NULL;
138
        }
139
    }
140
 
141
  SeenZipFiles = zipf;
142
  return zipf;
143
}
144
 
145
/* Returns:
146
   0:  OK - zipmember found.
147
   -1: Not found.
148
   -2: Malformed archive.
149
*/
150
 
151
int
152
open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
153
             int is_system)
154
{
155
  ZipDirectory *zipd;
156
  int i, len;
157
  ZipFile *zipf = opendir_in_zip (zipfile, is_system);
158
 
159
  if (zipf == NULL)
160
    return -2;
161
 
162
  if (!zipmember)
163
    return 0;
164
 
165
  len = strlen (zipmember);
166
 
167
  zipd = (struct ZipDirectory*) zipf->central_directory;
168
  for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
169
    {
170
      if (len == zipd->filename_length &&
171
          strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
172
        {
173
          JCF_ZERO (jcf);
174
 
175
          jcf->filename = xstrdup (zipfile);
176
          jcf->classname = xstrdup (zipmember);
177
          return read_zip_member(jcf, zipd, zipf);
178
        }
179
    }
180
  return -1;
181
}
182
 
183
/* Read data from zip archive member. */
184
 
185
int
186
read_zip_member (JCF *jcf,  ZipDirectory *zipd, ZipFile *zipf)
187
{
188
  jcf->filbuf = jcf_unexpected_eof;
189
  jcf->zipd = zipd;
190
 
191
  if (zipd->compression_method == Z_NO_COMPRESSION)
192
    {
193
      jcf->buffer = XNEWVEC (unsigned char, zipd->size);
194
      jcf->buffer_end = jcf->buffer + zipd->size;
195
      jcf->read_ptr = jcf->buffer;
196
      jcf->read_end = jcf->buffer_end;
197
      if (lseek (zipf->fd, zipd->filestart, 0) < 0
198
          || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
199
        return -2;
200
    }
201
  else
202
    {
203
      char *buffer;
204
      z_stream d_stream; /* decompression stream */
205
      d_stream.zalloc = (alloc_func) 0;
206
      d_stream.zfree = (free_func) 0;
207
      d_stream.opaque = (voidpf) 0;
208
 
209
      jcf->buffer = XNEWVEC (unsigned char, zipd->uncompressed_size);
210
      d_stream.next_out = jcf->buffer;
211
      d_stream.avail_out = zipd->uncompressed_size;
212
      jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
213
      jcf->read_ptr = jcf->buffer;
214
      jcf->read_end = jcf->buffer_end;
215
      buffer = XNEWVEC (char, zipd->size);
216
      d_stream.next_in = (unsigned char *) buffer;
217
      d_stream.avail_in = zipd->size;
218
      if (lseek (zipf->fd, zipd->filestart, 0) < 0
219
          || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
220
        return -2;
221
      /* Handle NO_HEADER using undocumented zlib feature.
222
         This is a very common hack.  */
223
      inflateInit2 (&d_stream, -MAX_WBITS);
224
      inflate (&d_stream, Z_NO_FLUSH);
225
      inflateEnd (&d_stream);
226
      free (buffer);
227
    }
228
 
229
  return 0;
230
}
231
 
232
const char *
233
open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
234
{
235
  if (jcf)
236
    {
237
      struct stat stat_buf;
238
      if (fstat (fd, &stat_buf) != 0
239
          || ! S_ISREG (stat_buf.st_mode))
240
        {
241
          perror ("Could not figure length of .class file");
242
          return NULL;
243
        }
244
      if (dep_name != NULL)
245
        jcf_dependency_add_file (dep_name, 0);
246
      JCF_ZERO (jcf);
247
      jcf->buffer = XNEWVEC (unsigned char, stat_buf.st_size);
248
      jcf->buffer_end = jcf->buffer + stat_buf.st_size;
249
      jcf->read_ptr = jcf->buffer;
250
      jcf->read_end = jcf->buffer_end;
251
      jcf->read_state = NULL;
252
      jcf->filename = xstrdup (filename);
253
      if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
254
        {
255
          perror ("Failed to read .class file");
256
          return NULL;
257
        }
258
      close (fd);
259
      jcf->filbuf = jcf_unexpected_eof;
260
    }
261
  else
262
    close (fd);
263
  return filename;
264
}
265
 
266
 
267
const char *
268
find_classfile (char *filename, JCF *jcf, const char *dep_name)
269
{
270
  int fd = open (filename, O_RDONLY | O_BINARY);
271
  if (fd < 0)
272
    return NULL;
273
  return open_class (filename, jcf, fd, dep_name);
274
}
275
 
276
/* Returns 1 if the CLASSNAME (really a char *) matches the name
277
   stored in TABLE_ENTRY (also a char *).  */
278
 
279
static int
280
memoized_class_lookup_eq (const void *table_entry, const void *classname)
281
{
282
  return strcmp ((const char *)classname, (const char *)table_entry) == 0;
283
}
284
 
285
/* A hash table keeping track of class names that were not found
286
   during class lookup.  (There is no need to cache the values
287
   associated with names that were found; they are saved in
288
   IDENTIFIER_CLASS_VALUE.)  */
289
static htab_t memoized_class_lookups;
290
 
291
/* Returns a freshly malloc'd string with the fully qualified pathname
292
   of the .class file for the class CLASSNAME.  CLASSNAME must be
293
   allocated in permanent storage; this function may retain a pointer
294
   to it.  Returns NULL on failure.  If JCF != NULL, it is suitably
295
   initialized.  SOURCE_OK is true if we should also look for .java
296
   file. */
297
 
298
const char *
299
find_class (const char *classname, int classname_length, JCF *jcf)
300
{
301
  int fd;
302
  int i, k, klass = -1;
303
  struct stat class_buf;
304
  char *dep_file;
305
  void *entry;
306
  int buflen;
307
  char *buffer;
308
  hashval_t hash;
309
 
310
  /* Create the hash table, if it does not already exist.  */
311
  if (!memoized_class_lookups)
312
    memoized_class_lookups = htab_create (37,
313
                                          htab_hash_string,
314
                                          memoized_class_lookup_eq,
315
                                          NULL);
316
 
317
  /* Loop for this class in the hashtable.  If it is present, we've
318
     already looked for this class and failed to find it.  */
319
  hash = htab_hash_string (classname);
320
  if (htab_find_with_hash (memoized_class_lookups, classname, hash))
321
    return NULL;
322
 
323
  /* Allocate and zero out the buffer, since we don't explicitly put a
324
     null pointer when we're copying it below.  */
325
  buflen = jcf_path_max_len () + classname_length + 10;
326
  buffer = XNEWVAR (char, buflen);
327
  memset (buffer, 0, buflen);
328
 
329
  for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
330
    {
331
      const char *path_name = jcf_path_name (entry);
332
      if (klass != 0)
333
        {
334
          int dir_len;
335
 
336
          strcpy (buffer, path_name);
337
          i = strlen (buffer);
338
 
339
          /* This is right because we know that `.zip' entries will have a
340
             trailing slash.  See jcf-path.c.  */
341
          dir_len = i - 1;
342
 
343
          for (k = 0; k < classname_length; k++, i++)
344
            {
345
              char ch = classname[k];
346
              buffer[i] = ch == '.' ? '/' : ch;
347
            }
348
          strcpy (buffer+i, ".class");
349
 
350
          if (jcf_path_is_zipfile (entry))
351
            {
352
              int err_code;
353
              JCF _jcf;
354
              buffer[dir_len] = '\0';
355
              SOURCE_FRONTEND_DEBUG
356
                (("Trying [...%s]:%s",
357
                  &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
358
                  buffer+dir_len+1));
359
              if (jcf == NULL)
360
                jcf = &_jcf;
361
              err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
362
                                      jcf_path_is_system (entry));
363
              if (err_code == 0)
364
                {
365
                  /* Should we check if .zip is out-of-date wrt .java? */
366
                  buffer[dir_len] = '(';
367
                  strcpy (buffer+i, ".class)");
368
                  if (jcf == &_jcf)
369
                    JCF_FINISH (jcf);
370
                  return buffer;
371
                }
372
              else
373
                continue;
374
            }
375
          klass = stat (buffer, &class_buf);
376
        }
377
    }
378
 
379
  dep_file = buffer;
380
  if (!klass)
381
    {
382
      SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
383
                              classname+classname_length-
384
                              (classname_length <= 30 ?
385
                               classname_length : 30)));
386
      fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
387
      if (fd >= 0)
388
        goto found;
389
    }
390
 
391
  free (buffer);
392
 
393
  /* Remember that this class could not be found so that we do not
394
     have to look again.  */
395
  *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT)
396
    = (void *) CONST_CAST (char *, classname);
397
 
398
  return NULL;
399
 found:
400
  {
401
    const char *const tmp = open_class (buffer, jcf, fd, dep_file);
402
    jcf->classname = xstrdup (classname);
403
    return tmp;
404
  }
405
}
406
 
407
void
408
jcf_print_char (FILE *stream, int ch)
409
{
410
  switch (ch)
411
    {
412
    case '\'':
413
    case '\\':
414
    case '\"':
415
      fprintf (stream, "\\%c", ch);
416
      break;
417
    case '\n':
418
      fprintf (stream, "\\n");
419
      break;
420
    case '\t':
421
      fprintf (stream, "\\t");
422
      break;
423
    case '\r':
424
      fprintf (stream, "\\r");
425
      break;
426
    default:
427
      if (ch >= ' ' && ch < 127)
428
        putc (ch, stream);
429
      else if (ch < 256)
430
        fprintf (stream, "\\%03x", ch);
431
      else
432
        fprintf (stream, "\\u%04x", ch);
433
    }
434
}
435
 
436
/* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
437
 
438
void
439
jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
440
{
441
  const unsigned char * limit = str + length;
442
  while (str < limit)
443
    {
444
      int ch = UTF8_GET (str, limit);
445
      if (ch < 0)
446
        {
447
          fprintf (stream, "\\<invalid>");
448
          return;
449
        }
450
      jcf_print_char (stream, ch);
451
    }
452
}
453
 
454
/* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
455
 
456
void
457
jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
458
                        int in_char, int out_char)
459
{
460
  const unsigned char *limit = str + length;
461
  while (str < limit)
462
    {
463
      int ch = UTF8_GET (str, limit);
464
      if (ch < 0)
465
        {
466
          fprintf (stream, "\\<invalid>");
467
          return;
468
        }
469
      jcf_print_char (stream, ch == in_char ? out_char : ch);
470
    }
471
}
472
 
473
/* Check that all the cross-references in the constant pool are
474
   valid.  Returns 0 on success.
475
   Otherwise, returns the index of the (first) invalid entry.
476
   Only checks internal consistency, but does not check that
477
   any classes, fields, or methods are valid.*/
478
 
479
int
480
verify_constant_pool (JCF *jcf)
481
{
482
  int i, n;
483
  for (i = 1; i < JPOOL_SIZE (jcf); i++)
484
    {
485
      switch (JPOOL_TAG (jcf, i))
486
        {
487
        case CONSTANT_NameAndType:
488
          n = JPOOL_USHORT2 (jcf, i);
489
          if (n <= 0 || n >= JPOOL_SIZE(jcf)
490
              || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
491
            return i;
492
          /* ... fall through ... */
493
        case CONSTANT_Class:
494
        case CONSTANT_String:
495
          n = JPOOL_USHORT1 (jcf, i);
496
          if (n <= 0 || n >= JPOOL_SIZE(jcf)
497
              || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
498
            return i;
499
          break;
500
        case CONSTANT_Fieldref:
501
        case CONSTANT_Methodref:
502
        case CONSTANT_InterfaceMethodref:
503
          n = JPOOL_USHORT1 (jcf, i);
504
          if (n <= 0 || n >= JPOOL_SIZE(jcf)
505
              || JPOOL_TAG (jcf, n) != CONSTANT_Class)
506
            return i;
507
          n = JPOOL_USHORT2 (jcf, i);
508
          if (n <= 0 || n >= JPOOL_SIZE(jcf)
509
              || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
510
            return i;
511
          break;
512
        case CONSTANT_Long:
513
        case CONSTANT_Double:
514
          i++;
515
          break;
516
        case CONSTANT_Float:
517
        case CONSTANT_Integer:
518
        case CONSTANT_Utf8:
519
        case CONSTANT_Unicode:
520
          break;
521
        default:
522
          return i;
523
        }
524
    }
525
  return 0;
526
}
527
 
528
void
529
format_uint (char *buffer, uint64 value, int base)
530
{
531
#define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
532
  char buf[WRITE_BUF_SIZE];
533
  char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
534
  int chars_written;
535
  int i;
536
 
537
  /* Now do the actual conversion, placing the result at the *end* of buf. */
538
  /* Note this code does not pretend to be optimized. */
539
  do {
540
    int digit = value % base;
541
    static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
542
    *--buf_ptr = digit_chars[digit];
543
    value /= base;
544
  } while (value != 0);
545
 
546
  chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
547
  for (i = 0; i < chars_written; i++)
548
    buffer[i] = *buf_ptr++;
549
  buffer[i] = 0;
550
}
551
 
552
void
553
format_int (char *buffer, jlong value, int base)
554
{
555
  uint64 abs_value;
556
  if (value < 0)
557
    {
558
      abs_value = -(uint64)value;
559
      *buffer++ = '-';
560
    }
561
  else
562
    abs_value = (uint64) value;
563
  format_uint (buffer, abs_value, base);
564
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.