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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [gcc/] [java/] [jcf-io.c] - Blame information for rev 12

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 12 jlechner
/* Utility routines for finding and reading Java(TM) .class files.
2
   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005
3
   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 2, 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 COPYING.  If not, write to
19
the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20
Boston, MA 02110-1301, USA.
21
 
22
Java and all Java-based marks are trademarks or registered trademarks
23
of Sun Microsystems, Inc. in the United States and other countries.
24
The Free Software Foundation is independent of Sun Microsystems, Inc.  */
25
 
26
/* Written by Per Bothner <bothner@cygnus.com>, February 1996. */
27
 
28
#include "config.h"
29
#include "system.h"
30
#include "coretypes.h"
31
#include "tm.h"
32
 
33
#include "jcf.h"
34
#include "tree.h"
35
#include "toplev.h"
36
#include "java-tree.h"
37
#include "hashtab.h"
38
#if JCF_USE_SCANDIR
39
#include <dirent.h>
40
#include <fnmatch.h>
41
#endif
42
 
43
#include "zlib.h"
44
 
45
/* DOS brain-damage */
46
#ifndef O_BINARY
47
#define O_BINARY 0 /* MS-DOS brain-damage */
48
#endif
49
 
50
int
51
jcf_unexpected_eof (JCF *jcf, int count ATTRIBUTE_UNUSED)
52
{
53
  if (jcf->filename)
54
    fprintf (stderr, "Premature end of .class file %s.\n", jcf->filename);
55
  else
56
    fprintf (stderr, "Premature end of .class file <stdin>.\n");
57
  exit (-1);
58
}
59
 
60
void
61
jcf_trim_old_input (JCF *jcf)
62
{
63
  int count = jcf->read_ptr - jcf->buffer;
64
  if (count > 0)
65
    {
66
      memmove (jcf->buffer, jcf->read_ptr, jcf->read_end - jcf->read_ptr);
67
      jcf->read_ptr -= count;
68
      jcf->read_end -= count;
69
    }
70
}
71
 
72
int
73
jcf_filbuf_from_stdio (JCF *jcf, int count)
74
{
75
  FILE *file = (FILE*) (jcf->read_state);
76
  if (count > jcf->buffer_end - jcf->read_ptr)
77
    {
78
      JCF_u4 old_read_ptr = jcf->read_ptr - jcf->buffer;
79
      JCF_u4 old_read_end = jcf->read_end - jcf->buffer;
80
      JCF_u4 old_size = jcf->buffer_end - jcf->buffer;
81
      JCF_u4 new_size = (old_size == 0 ? 2000 : 2 * old_size) + count;
82
      unsigned char *new_buffer = jcf->buffer == NULL ? ALLOC (new_size)
83
        : REALLOC (jcf->buffer, new_size);
84
      jcf->buffer = new_buffer;
85
      jcf->buffer_end = new_buffer + new_size;
86
      jcf->read_ptr = new_buffer + old_read_ptr;
87
      jcf->read_end = new_buffer + old_read_end;
88
    }
89
  count -= jcf->read_end - jcf->read_ptr;
90
  if (count <= 0)
91
    return 0;
92
  if ((int) fread (jcf->read_end, 1, count, file) != count)
93
    jcf_unexpected_eof (jcf, count);
94
  jcf->read_end += count;
95
  return 0;
96
}
97
 
98
#include "zipfile.h"
99
 
100
struct ZipFile *SeenZipFiles = NULL;
101
 
102
/* Open a zip file with the given name, and cache directory and file
103
   descriptor.  If the file is missing, treat it as an empty archive.
104
   Return NULL if the .zip file is malformed.
105
*/
106
 
107
ZipFile *
108
opendir_in_zip (const char *zipfile, int is_system)
109
{
110
  struct ZipFile* zipf;
111
  char magic [4];
112
  int fd;
113
  for (zipf = SeenZipFiles;  zipf != NULL;  zipf = zipf->next)
114
    {
115
      if (strcmp (zipf->name, zipfile) == 0)
116
        return zipf;
117
    }
118
 
119
  zipf = ALLOC (sizeof (struct ZipFile) + strlen (zipfile) + 1);
120
  zipf->next = SeenZipFiles;
121
  zipf->name = (char*)(zipf+1);
122
  strcpy (zipf->name, zipfile);
123
  fd = open (zipfile, O_RDONLY | O_BINARY);
124
  zipf->fd = fd;
125
  if (fd < 0)
126
    {
127
      /* A missing zip file is not considered an error.
128
       We may want to re-consider that.  FIXME. */
129
      zipf->count = 0;
130
      zipf->dir_size = 0;
131
      zipf->central_directory = NULL;
132
    }
133
  else
134
    {
135
      jcf_dependency_add_file (zipfile, is_system);
136
      if (read (fd, magic, 4) != 4 || GET_u4 (magic) != (JCF_u4)ZIPMAGIC)
137
        return NULL;
138
      lseek (fd, 0L, SEEK_SET);
139
      if (read_zip_archive (zipf) != 0)
140
        return NULL;
141
    }
142
 
143
  SeenZipFiles = zipf;
144
  return zipf;
145
}
146
 
147
/* Returns:
148
   0:  OK - zipmember found.
149
   -1: Not found.
150
   -2: Malformed archive.
151
*/
152
 
153
int
154
open_in_zip (JCF *jcf, const char *zipfile, const char *zipmember,
155
             int is_system)
156
{
157
  ZipDirectory *zipd;
158
  int i, len;
159
  ZipFile *zipf = opendir_in_zip (zipfile, is_system);
160
 
161
  if (zipf == NULL)
162
    return -2;
163
 
164
  if (!zipmember)
165
    return 0;
166
 
167
  len = strlen (zipmember);
168
 
169
  zipd = (struct ZipDirectory*) zipf->central_directory;
170
  for (i = 0; i < zipf->count; i++, zipd = ZIPDIR_NEXT (zipd))
171
    {
172
      if (len == zipd->filename_length &&
173
          strncmp (ZIPDIR_FILENAME (zipd), zipmember, len) == 0)
174
        {
175
          JCF_ZERO (jcf);
176
 
177
          jcf->filename = xstrdup (zipfile);
178
          jcf->classname = xstrdup (zipmember);
179
          return read_zip_member(jcf, zipd, zipf);
180
        }
181
    }
182
  return -1;
183
}
184
 
185
/* Read data from zip archive member. */
186
 
187
int
188
read_zip_member (JCF *jcf,  ZipDirectory *zipd, ZipFile *zipf)
189
{
190
  jcf->filbuf = jcf_unexpected_eof;
191
  jcf->zipd = (void *)zipd;
192
 
193
  if (zipd->compression_method == Z_NO_COMPRESSION)
194
    {
195
      jcf->buffer = ALLOC (zipd->size);
196
      jcf->buffer_end = jcf->buffer + zipd->size;
197
      jcf->read_ptr = jcf->buffer;
198
      jcf->read_end = jcf->buffer_end;
199
      if (lseek (zipf->fd, zipd->filestart, 0) < 0
200
          || read (zipf->fd, jcf->buffer, zipd->size) != (long) zipd->size)
201
        return -2;
202
    }
203
  else
204
    {
205
      char *buffer;
206
      z_stream d_stream; /* decompression stream */
207
      d_stream.zalloc = (alloc_func) 0;
208
      d_stream.zfree = (free_func) 0;
209
      d_stream.opaque = (voidpf) 0;
210
 
211
      jcf->buffer = ALLOC (zipd->uncompressed_size);
212
      d_stream.next_out = jcf->buffer;
213
      d_stream.avail_out = zipd->uncompressed_size;
214
      jcf->buffer_end = jcf->buffer + zipd->uncompressed_size;
215
      jcf->read_ptr = jcf->buffer;
216
      jcf->read_end = jcf->buffer_end;
217
      buffer = ALLOC (zipd->size);
218
      d_stream.next_in = (unsigned char *) buffer;
219
      d_stream.avail_in = zipd->size;
220
      if (lseek (zipf->fd, zipd->filestart, 0) < 0
221
          || read (zipf->fd, buffer, zipd->size) != (long) zipd->size)
222
        return -2;
223
      /* Handle NO_HEADER using undocumented zlib feature.
224
         This is a very common hack.  */
225
      inflateInit2 (&d_stream, -MAX_WBITS);
226
      inflate (&d_stream, Z_NO_FLUSH);
227
      inflateEnd (&d_stream);
228
      FREE (buffer);
229
    }
230
 
231
  return 0;
232
}
233
 
234
const char *
235
open_class (const char *filename, JCF *jcf, int fd, const char *dep_name)
236
{
237
  if (jcf)
238
    {
239
      struct stat stat_buf;
240
      if (fstat (fd, &stat_buf) != 0
241
          || ! S_ISREG (stat_buf.st_mode))
242
        {
243
          perror ("Could not figure length of .class file");
244
          return NULL;
245
        }
246
      if (dep_name != NULL)
247
        jcf_dependency_add_file (dep_name, 0);
248
      JCF_ZERO (jcf);
249
      jcf->buffer = ALLOC (stat_buf.st_size);
250
      jcf->buffer_end = jcf->buffer + stat_buf.st_size;
251
      jcf->read_ptr = jcf->buffer;
252
      jcf->read_end = jcf->buffer_end;
253
      jcf->read_state = NULL;
254
      jcf->filename = filename;
255
      if (read (fd, jcf->buffer, stat_buf.st_size) != stat_buf.st_size)
256
        {
257
          perror ("Failed to read .class file");
258
          return NULL;
259
        }
260
      close (fd);
261
      jcf->filbuf = jcf_unexpected_eof;
262
    }
263
  else
264
    close (fd);
265
  return filename;
266
}
267
 
268
 
269
const char *
270
find_classfile (char *filename, JCF *jcf, const char *dep_name)
271
{
272
  int fd = open (filename, O_RDONLY | O_BINARY);
273
  if (fd < 0)
274
    return NULL;
275
  return open_class (filename, jcf, fd, dep_name);
276
}
277
 
278
#if JCF_USE_SCANDIR
279
 
280
/* A comparison function (as for qsort) that compares KEY (a char *
281
   giving the basename of a file) with the name stored in ENTRY (a
282
   dirent **).  */
283
 
284
static int
285
compare_path (const void *key, const void *entry)
286
{
287
  return strcmp ((const char *) key,
288
                 (*((const struct dirent **) entry))->d_name);
289
}
290
 
291
/* Returns nonzero if ENTRY names a .java or .class file.  */
292
 
293
static int
294
java_or_class_file (const struct dirent *entry)
295
{
296
  const char *base = lbasename (entry->d_name);
297
  return (fnmatch ("*.java", base, 0) == 0 ||
298
          fnmatch ("*.class", base, 0) == 0);
299
}
300
 
301
/* Information about the files present in a particular directory.  */
302
typedef struct memoized_dirlist_entry
303
{
304
  /* The name of the directory.  */
305
  const char *dir;
306
  /* The number of .java and .class files present, or -1 if we could
307
     not, for some reason, obtain the list.  */
308
  int num_files;
309
  /* The .java and .class files in the directory, in alphabetical
310
     order.  */
311
  struct dirent **files;
312
} memoized_dirlist_entry;
313
 
314
/* A hash function for a memoized_dirlist_entry.  */
315
static hashval_t
316
memoized_dirlist_hash (const void *entry)
317
{
318
  const memoized_dirlist_entry *mde = (const memoized_dirlist_entry *) entry;
319
  return htab_hash_string (mde->dir);
320
}
321
 
322
/* Returns true if ENTRY (a memoized_dirlist_entry *) corresponds to
323
   the directory given by KEY (a char *) giving the directory
324
   name.  */
325
 
326
static int
327
memoized_dirlist_lookup_eq (const void *entry, const void *key)
328
{
329
  return strcmp ((const char *) key,
330
                 ((const memoized_dirlist_entry *) entry)->dir) == 0;
331
}
332
 
333
/* A hash table mapping directory names to the lists of .java and
334
   .class files in that directory.  */
335
 
336
static htab_t memoized_dirlists;
337
 
338
#endif
339
 
340
/* Like stat, but avoids actually making the stat system call if we
341
   know that it cannot succeed.  FILENAME and BUF are as for stat.  */
342
 
343
static int
344
caching_stat (char *filename, struct stat *buf)
345
{
346
#if JCF_USE_SCANDIR
347
  char *sep;
348
  char origsep = 0;
349
  char *base;
350
  memoized_dirlist_entry *dent;
351
  void **slot;
352
  struct memoized_dirlist_entry temp;
353
 
354
  /* If the hashtable has not already been created, create it now.  */
355
  if (!memoized_dirlists)
356
    memoized_dirlists = htab_create (37,
357
                                     memoized_dirlist_hash,
358
                                     memoized_dirlist_lookup_eq,
359
                                     NULL);
360
 
361
  /* Get the name of the directory.  */
362
  sep = strrchr (filename, DIR_SEPARATOR);
363
#ifdef DIR_SEPARATOR_2
364
  if (! sep)
365
    sep = strrchr (filename, DIR_SEPARATOR_2);
366
#endif
367
  if (sep)
368
    {
369
      origsep = *sep;
370
      *sep = '\0';
371
      base = sep + 1;
372
    }
373
  else
374
    base = filename;
375
 
376
  /* Obtain the entry for this directory from the hash table.  This
377
     approach is ok since we know that the hash function only looks at
378
     the directory name.  */
379
  temp.dir = filename;
380
  temp.num_files = 0;
381
  temp.files = NULL;
382
  slot = htab_find_slot (memoized_dirlists, &temp, INSERT);
383
  if (!*slot)
384
    {
385
      /* We have not already scanned this directory; scan it now.  */
386
      dent = ((memoized_dirlist_entry *)
387
              ALLOC (sizeof (memoized_dirlist_entry)));
388
      dent->dir = xstrdup (filename);
389
      /* Unfortunately, scandir is not fully standardized.  In
390
         particular, the type of the function pointer passed as the
391
         third argument sometimes takes a "const struct dirent *"
392
         parameter, and sometimes just a "struct dirent *".  We cast
393
         to (void *) and use __extension__ so that either way it is
394
         quietly accepted.  FIXME: scandir is not in POSIX.  */
395
      dent->num_files = __extension__ scandir (filename, &dent->files,
396
                                               (void *) java_or_class_file,
397
                                               alphasort);
398
      *slot = dent;
399
    }
400
  else
401
    dent = *((memoized_dirlist_entry **) slot);
402
 
403
  /* Put the separator back.  */
404
  if (sep)
405
    *sep = origsep;
406
 
407
  /* If the file is not in the list, there is no need to stat it; it
408
     does not exist.  */
409
  if (dent->num_files != -1
410
      && !bsearch (base, dent->files, dent->num_files,
411
                   sizeof (struct dirent *), compare_path))
412
    return -1;
413
#endif
414
 
415
  return stat (filename, buf);
416
}
417
 
418
/* Returns 1 if the CLASSNAME (really a char *) matches the name
419
   stored in TABLE_ENTRY (also a char *).  */
420
 
421
static int
422
memoized_class_lookup_eq (const void *table_entry, const void *classname)
423
{
424
  return strcmp ((const char *)classname, (const char *)table_entry) == 0;
425
}
426
 
427
/* A hash table keeping track of class names that were not found
428
   during class lookup.  (There is no need to cache the values
429
   associated with names that were found; they are saved in
430
   IDENTIFIER_CLASS_VALUE.)  */
431
static htab_t memoized_class_lookups;
432
 
433
/* Returns a freshly malloc'd string with the fully qualified pathname
434
   of the .class file for the class CLASSNAME.  CLASSNAME must be
435
   allocated in permanent storage; this function may retain a pointer
436
   to it.  Returns NULL on failure.  If JCF != NULL, it is suitably
437
   initialized.  SOURCE_OK is true if we should also look for .java
438
   file. */
439
 
440
const char *
441
find_class (const char *classname, int classname_length, JCF *jcf,
442
            int source_ok)
443
{
444
  int fd;
445
  int i, k, java = -1, class = -1;
446
  struct stat java_buf, class_buf;
447
  char *dep_file;
448
  void *entry;
449
  char *java_buffer;
450
  int buflen;
451
  char *buffer;
452
  hashval_t hash;
453
 
454
  /* Create the hash table, if it does not already exist.  */
455
  if (!memoized_class_lookups)
456
    memoized_class_lookups = htab_create (37,
457
                                          htab_hash_string,
458
                                          memoized_class_lookup_eq,
459
                                          NULL);
460
 
461
  /* Loop for this class in the hashtable.  If it is present, we've
462
     already looked for this class and failed to find it.  */
463
  hash = htab_hash_string (classname);
464
  if (htab_find_with_hash (memoized_class_lookups, classname, hash))
465
    return NULL;
466
 
467
  /* Allocate and zero out the buffer, since we don't explicitly put a
468
     null pointer when we're copying it below.  */
469
  buflen = jcf_path_max_len () + classname_length + 10;
470
  buffer = ALLOC (buflen);
471
  memset (buffer, 0, buflen);
472
 
473
  java_buffer = alloca (buflen);
474
 
475
  jcf->java_source = 0;
476
 
477
  for (entry = jcf_path_start (); entry != NULL; entry = jcf_path_next (entry))
478
    {
479
      const char *path_name = jcf_path_name (entry);
480
      if (class != 0)
481
        {
482
          int dir_len;
483
 
484
          strcpy (buffer, path_name);
485
          i = strlen (buffer);
486
 
487
          /* This is right because we know that `.zip' entries will have a
488
             trailing slash.  See jcf-path.c.  */
489
          dir_len = i - 1;
490
 
491
          for (k = 0; k < classname_length; k++, i++)
492
            {
493
              char ch = classname[k];
494
              buffer[i] = ch == '.' ? '/' : ch;
495
            }
496
          strcpy (buffer+i, ".class");
497
 
498
          if (jcf_path_is_zipfile (entry))
499
            {
500
              int err_code;
501
              JCF _jcf;
502
              buffer[dir_len] = '\0';
503
              SOURCE_FRONTEND_DEBUG
504
                (("Trying [...%s]:%s",
505
                  &buffer[dir_len-(dir_len > 15 ? 15 : dir_len)],
506
                  buffer+dir_len+1));
507
              if (jcf == NULL)
508
                jcf = &_jcf;
509
              err_code = open_in_zip (jcf, buffer, buffer+dir_len+1,
510
                                      jcf_path_is_system (entry));
511
              if (err_code == 0)
512
                {
513
                  /* Should we check if .zip is out-of-date wrt .java? */
514
                  buffer[dir_len] = '(';
515
                  strcpy (buffer+i, ".class)");
516
                  if (jcf == &_jcf)
517
                    JCF_FINISH (jcf);
518
                  return buffer;
519
                }
520
              else
521
                continue;
522
            }
523
          class = caching_stat(buffer, &class_buf);
524
        }
525
 
526
      if (source_ok)
527
        {
528
          /* Compute name of .java file.  */
529
          int l, m;
530
          strcpy (java_buffer, path_name);
531
          l = strlen (java_buffer);
532
          for (m = 0; m < classname_length; ++m)
533
            java_buffer[m + l] = (classname[m] == '.'
534
                                  ? DIR_SEPARATOR : classname[m]);
535
          strcpy (java_buffer + m + l, ".java");
536
          java = caching_stat (java_buffer, &java_buf);
537
          if (java == 0)
538
            break;
539
        }
540
    }
541
 
542
  /* We preferably pick a class file if we have a chance. If the source
543
     file is newer than the class file, we issue a warning and parse the
544
     source file instead.
545
     There should be a flag to allow people have the class file picked
546
     up no matter what. FIXME. */
547
  if (! java && ! class && java_buf.st_mtime > class_buf.st_mtime)
548
    {
549
      if (flag_newer)
550
        warning (0, "source file for class %qs is newer than its matching class file.  Source file %qs used instead", classname, java_buffer);
551
      class = -1;
552
    }
553
 
554
  if (! java)
555
    dep_file = java_buffer;
556
  else
557
    dep_file = buffer;
558
  if (!class)
559
    {
560
      SOURCE_FRONTEND_DEBUG ((stderr, "[Class selected: %s]\n",
561
                              classname+classname_length-
562
                              (classname_length <= 30 ?
563
                               classname_length : 30)));
564
      fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY | O_BINARY);
565
      if (fd >= 0)
566
        goto found;
567
    }
568
  /* Give .java a try, if necessary */
569
  if (!java)
570
    {
571
      strcpy (buffer, java_buffer);
572
      SOURCE_FRONTEND_DEBUG ((stderr, "[Source selected: %s]\n",
573
                              classname+classname_length-
574
                              (classname_length <= 30 ?
575
                               classname_length : 30)));
576
      fd = JCF_OPEN_EXACT_CASE (buffer, O_RDONLY);
577
      if (fd >= 0)
578
        {
579
          jcf->java_source = 1;
580
          goto found;
581
        }
582
    }
583
 
584
  free (buffer);
585
 
586
  /* Remember that this class could not be found so that we do not
587
     have to look again.  */
588
  *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT)
589
    = (void *) classname;
590
 
591
  return NULL;
592
 found:
593
  if (jcf->java_source)
594
    {
595
      JCF_ZERO (jcf);           /* JCF_FINISH relies on this */
596
      jcf->java_source = 1;
597
      jcf->filename = xstrdup (buffer);
598
      close (fd);               /* We use STDIO for source file */
599
    }
600
  else
601
    buffer = (char *) open_class (buffer, jcf, fd, dep_file);
602
  jcf->classname = xstrdup (classname);
603
  return buffer;
604
}
605
 
606
void
607
jcf_print_char (FILE *stream, int ch)
608
{
609
  switch (ch)
610
    {
611
    case '\'':
612
    case '\\':
613
    case '\"':
614
      fprintf (stream, "\\%c", ch);
615
      break;
616
    case '\n':
617
      fprintf (stream, "\\n");
618
      break;
619
    case '\t':
620
      fprintf (stream, "\\t");
621
      break;
622
    case '\r':
623
      fprintf (stream, "\\r");
624
      break;
625
    default:
626
      if (ch >= ' ' && ch < 127)
627
        putc (ch, stream);
628
      else if (ch < 256)
629
        fprintf (stream, "\\%03x", ch);
630
      else
631
        fprintf (stream, "\\u%04x", ch);
632
    }
633
}
634
 
635
/* Print UTF8 string at STR of length LENGTH bytes to STREAM. */
636
 
637
void
638
jcf_print_utf8 (FILE *stream, const unsigned char *str, int length)
639
{
640
  const unsigned char * limit = str + length;
641
  while (str < limit)
642
    {
643
      int ch = UTF8_GET (str, limit);
644
      if (ch < 0)
645
        {
646
          fprintf (stream, "\\<invalid>");
647
          return;
648
        }
649
      jcf_print_char (stream, ch);
650
    }
651
}
652
 
653
/* Same as jcf_print_utf8, but print IN_CHAR as OUT_CHAR. */
654
 
655
void
656
jcf_print_utf8_replace (FILE *stream, const unsigned char *str, int length,
657
                        int in_char, int out_char)
658
{
659
  const unsigned char *limit = str + length;
660
  while (str < limit)
661
    {
662
      int ch = UTF8_GET (str, limit);
663
      if (ch < 0)
664
        {
665
          fprintf (stream, "\\<invalid>");
666
          return;
667
        }
668
      jcf_print_char (stream, ch == in_char ? out_char : ch);
669
    }
670
}
671
 
672
/* Check that all the cross-references in the constant pool are
673
   valid.  Returns 0 on success.
674
   Otherwise, returns the index of the (first) invalid entry.
675
   Only checks internal consistency, but does not check that
676
   any classes, fields, or methods are valid.*/
677
 
678
int
679
verify_constant_pool (JCF *jcf)
680
{
681
  int i, n;
682
  for (i = 1; i < JPOOL_SIZE (jcf); i++)
683
    {
684
      switch (JPOOL_TAG (jcf, i))
685
        {
686
        case CONSTANT_NameAndType:
687
          n = JPOOL_USHORT2 (jcf, i);
688
          if (n <= 0 || n >= JPOOL_SIZE(jcf)
689
              || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
690
            return i;
691
          /* ... fall through ... */
692
        case CONSTANT_Class:
693
        case CONSTANT_String:
694
          n = JPOOL_USHORT1 (jcf, i);
695
          if (n <= 0 || n >= JPOOL_SIZE(jcf)
696
              || JPOOL_TAG (jcf, n) != CONSTANT_Utf8)
697
            return i;
698
          break;
699
        case CONSTANT_Fieldref:
700
        case CONSTANT_Methodref:
701
        case CONSTANT_InterfaceMethodref:
702
          n = JPOOL_USHORT1 (jcf, i);
703
          if (n <= 0 || n >= JPOOL_SIZE(jcf)
704
              || JPOOL_TAG (jcf, n) != CONSTANT_Class)
705
            return i;
706
          n = JPOOL_USHORT2 (jcf, i);
707
          if (n <= 0 || n >= JPOOL_SIZE(jcf)
708
              || JPOOL_TAG (jcf, n) != CONSTANT_NameAndType)
709
            return i;
710
          break;
711
        case CONSTANT_Long:
712
        case CONSTANT_Double:
713
          i++;
714
          break;
715
        case CONSTANT_Float:
716
        case CONSTANT_Integer:
717
        case CONSTANT_Utf8:
718
        case CONSTANT_Unicode:
719
          break;
720
        default:
721
          return i;
722
        }
723
    }
724
  return 0;
725
}
726
 
727
void
728
format_uint (char *buffer, uint64 value, int base)
729
{
730
#define WRITE_BUF_SIZE (4 + sizeof(uint64) * 8)
731
  char buf[WRITE_BUF_SIZE];
732
  char *buf_ptr = buf+WRITE_BUF_SIZE; /* End of buf. */
733
  int chars_written;
734
  int i;
735
 
736
  /* Now do the actual conversion, placing the result at the *end* of buf. */
737
  /* Note this code does not pretend to be optimized. */
738
  do {
739
    int digit = value % base;
740
    static const char digit_chars[] = "0123456789abcdefghijklmnopqrstuvwxyz";
741
    *--buf_ptr = digit_chars[digit];
742
    value /= base;
743
  } while (value != 0);
744
 
745
  chars_written = buf+WRITE_BUF_SIZE - buf_ptr;
746
  for (i = 0; i < chars_written; i++)
747
    buffer[i] = *buf_ptr++;
748
  buffer[i] = 0;
749
}
750
 
751
void
752
format_int (char *buffer, jlong value, int base)
753
{
754
  uint64 abs_value;
755
  if (value < 0)
756
    {
757
      abs_value = -(uint64)value;
758
      *buffer++ = '-';
759
    }
760
  else
761
    abs_value = (uint64) value;
762
  format_uint (buffer, abs_value, base);
763
}

powered by: WebSVN 2.1.0

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