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

Subversion Repositories openrisc_me

[/] [openrisc/] [trunk/] [gnu-src/] [gcc-4.5.1/] [gcc/] [java/] [jcf-io.c] - Blame information for rev 294

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

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

powered by: WebSVN 2.1.0

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