jcf-parse.c 60.2 KB
Newer Older
Anthony Green committed
1
/* Parser for Java(TM) .class files.
2
   Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
3
   2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
Anthony Green committed
4

5
This file is part of GCC.
Anthony Green committed
6

7
GCC is free software; you can redistribute it and/or modify
Anthony Green committed
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)
Anthony Green committed
10 11
any later version.

12
GCC is distributed in the hope that it will be useful,
Anthony Green committed
13 14 15 16 17
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
18 19
along with GCC; see the file COPYING3.  If not see
<http://www.gnu.org/licenses/>.
Anthony Green committed
20 21 22 23 24 25 26 27

Java and all Java-based marks are trademarks or registered trademarks
of Sun Microsystems, Inc. in the United States and other countries.
The Free Software Foundation is independent of Sun Microsystems, Inc.  */

/* Written by Per Bothner <bothner@cygnus.com> */

#include "config.h"
28
#include "system.h"
29
#include "coretypes.h"
Anthony Green committed
30 31 32 33 34
#include "tree.h"
#include "obstack.h"
#include "flags.h"
#include "java-except.h"
#include "input.h"
35
#include "javaop.h"
Anthony Green committed
36
#include "java-tree.h"
37
#include "diagnostic-core.h"
38
#include "parse.h"
39
#include "ggc.h"
40
#include "debug.h"
41
#include "cgraph.h"
42
#include "vecprim.h"
43
#include "bitmap.h"
44
#include "target.h"
Anthony Green committed
45

46 47 48 49
#ifdef HAVE_LOCALE_H
#include <locale.h>
#endif

Adrian Bunk committed
50
#ifdef HAVE_LANGINFO_CODESET
51 52 53
#include <langinfo.h>
#endif

Anthony Green committed
54 55 56 57
/* A CONSTANT_Utf8 element is converted to an IDENTIFIER_NODE at parse time. */
#define JPOOL_UTF(JCF, INDEX) CPOOL_UTF(&(JCF)->cpool, INDEX)
#define JPOOL_UTF_LENGTH(JCF, INDEX) IDENTIFIER_LENGTH (JPOOL_UTF (JCF, INDEX))
#define JPOOL_UTF_DATA(JCF, INDEX) \
58
  ((const unsigned char *) IDENTIFIER_POINTER (JPOOL_UTF (JCF, INDEX)))
Anthony Green committed
59 60 61 62 63 64 65
#define HANDLE_CONSTANT_Utf8(JCF, INDEX, LENGTH) \
  do { \
    unsigned char save;  unsigned char *text; \
    JCF_FILL (JCF, (LENGTH)+1); /* Make sure we read 1 byte beyond string. */ \
    text = (JCF)->read_ptr; \
    save = text[LENGTH]; \
    text[LENGTH] = 0; \
66
    (JCF)->cpool.data[INDEX].t = get_identifier ((const char *) text); \
Anthony Green committed
67 68 69 70 71 72 73
    text[LENGTH] = save; \
    JCF_SKIP (JCF, LENGTH); } while (0)

#include "jcf.h"

extern struct obstack temporary_obstack;

74
static GTY(()) tree parse_roots[2];
75

76
/* The FIELD_DECL for the current field.  */
77
#define current_field parse_roots[0]
Anthony Green committed
78

79
/* The METHOD_DECL for the current method.  */
80
#define current_method parse_roots[1]
Anthony Green committed
81

82 83 84
/* Line 0 in current file, if compiling from bytecode. */
static location_t file_start_location;

85
/* The Java archive that provides main_class;  the main input file. */
86
static GTY(()) struct JCF * main_jcf;
87

88 89 90
/* A list of all the class DECLs seen so far.  */
static GTY(()) VEC(tree,gc) *all_class_list;

91
/* The number of source files passed to us by -fsource-filename and an
92 93 94 95
   array of pointers to each name.  Used by find_sourcefile().  */
static int num_files = 0;
static char **filenames;

96 97
static struct ZipFile *localToFile;

98 99 100 101 102
/* A map of byte offsets in the reflection data that are fields which
   need renumbering.  */
bitmap field_offsets;
bitmap_obstack bit_obstack;

103
/* Declarations of some functions used here.  */
104
static void handle_innerclass_attribute (int count, JCF *, int len);
105
static tree give_name_to_class (JCF *jcf, int index);
106 107
static char *compute_class_name (struct ZipDirectory *zdir);
static int classify_zip_file (struct ZipDirectory *zdir);
108 109 110
static void parse_zip_file_entries (void);
static void process_zip_dir (FILE *);
static void parse_class_file (void);
111
static void handle_deprecated (void);
112 113 114
static void set_source_filename (JCF *, int);
static void jcf_parse (struct JCF*);
static void load_inner_classes (tree);
115 116
static void handle_annotation (JCF *jcf, int level);
static void java_layout_seen_class_methods (void);
117

118 119 120 121 122 123 124 125 126 127 128 129 130
/* Handle "Deprecated" attribute.  */
static void
handle_deprecated (void)
{
  if (current_field != NULL_TREE)
    FIELD_DEPRECATED (current_field) = 1;
  else if (current_method != NULL_TREE)
    METHOD_DEPRECATED (current_method) = 1;
  else if (current_class != NULL_TREE)
    CLASS_DEPRECATED (TYPE_NAME (current_class)) = 1;
  else
    {
      /* Shouldn't happen.  */
131
      gcc_unreachable ();
132 133 134
    }
}

135 136 137 138 139 140 141 142 143 144 145


/* Reverse a string.  */
static char *
reverse (const char *s)
{
  if (s == NULL)
    return NULL;
  else
    {
      int len = strlen (s);
146
      char *d = XNEWVAR (char, len + 1);
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
      const char *sp;
      char *dp;
      
      d[len] = 0;
      for (dp = &d[0], sp = &s[len-1]; sp >= s; dp++, sp--)
	*dp = *sp;

      return d;
    }
}

/* Compare two strings for qsort().  */
static int
cmpstringp (const void *p1, const void *p2)
{
  /* The arguments to this function are "pointers to
     pointers to char", but strcmp() arguments are "pointers
     to char", hence the following cast plus dereference */

166
  return strcmp(*(const char *const*) p1, *(const char *const*) p2);
167 168 169 170 171 172 173 174 175 176 177 178
}

/* Create an array of strings, one for each source file that we've
   seen.  fsource_filename can either be the name of a single .java
   file or a file that contains a list of filenames separated by
   newlines.  */
void 
java_read_sourcefilenames (const char *fsource_filename)
{
  if (fsource_filename 
      && filenames == 0
      && strlen (fsource_filename) > strlen (".java")
Kai Tietz committed
179 180 181
      && filename_cmp ((fsource_filename
		       + strlen (fsource_filename)
		       - strlen (".java")),
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213
		 ".java") != 0)
    {
/*       fsource_filename isn't a .java file but a list of filenames
       separated by newlines */
      FILE *finput = fopen (fsource_filename, "r");
      int len = 0;
      int longest_line = 0;

      gcc_assert (finput);

      /* Find out how many files there are, and how long the filenames are.  */
      while (! feof (finput))
	{
	  int ch = getc (finput);
	  if (ch == '\n')
	    {
	      num_files++;
	      if (len > longest_line)
		longest_line = len;
	      len = 0;
	      continue;
	    }
	  if (ch == EOF)
	    break;
	  len++;
	}

      rewind (finput);

      /* Read the filenames.  Put a pointer to each filename into the
	 array FILENAMES.  */
      {
214
	char *linebuf = (char *) alloca (longest_line + 1);
215 216 217
	int i = 0;
	int charpos;

218
	filenames = XNEWVEC (char *, num_files);
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

	charpos = 0;
	for (;;)
	  {
	    int ch = getc (finput);
	    if (ch == EOF)
	      break;
	    if (ch == '\n')
	      {
		linebuf[charpos] = 0;
		gcc_assert (i < num_files);		
		/* ???  Perhaps we should use lrealpath() here.  Doing
		   so would tidy up things like /../ but the rest of
		   gcc seems to assume relative pathnames, not
		   absolute pathnames.  */
/* 		realname = lrealpath (linebuf); */
		filenames[i++] = reverse (linebuf);
		charpos = 0;
		continue;
	      }
	    gcc_assert (charpos < longest_line);
	    linebuf[charpos++] = ch;
	  }

	if (num_files > 1)
	  qsort (filenames, num_files, sizeof (char *), cmpstringp);
      }
      fclose (finput);
    }
  else
    {
250
      filenames = XNEWVEC (char *, 1);      
251 252 253 254 255 256 257 258
      filenames[0] = reverse (fsource_filename);
      num_files = 1;
    }
}

/* Given a relative pathname such as foo/bar.java, attempt to find a
   longer pathname with the same suffix.  

259
   This is a best guess heuristic; with some weird class hierarchies we
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
   may fail to pick the correct source file.  For example, if we have
   the filenames foo/bar.java and also foo/foo/bar.java, we do not
   have enough information to know which one is the right match for
   foo/bar.java.  */

static const char *
find_sourcefile (const char *name)
{
  int i = 0, j = num_files-1;
  char *found = NULL;
  
  if (filenames)
    {
      char *revname = reverse (name);

      do
	{
	  int k = (i+j) / 2;
	  int cmp = strncmp (revname, filenames[k], strlen (revname));
	  if (cmp == 0)
	    {
	      /*  OK, so we found one.  But is it a unique match?  */
	      if ((k > i
		   && strncmp (revname, filenames[k-1], strlen (revname)) == 0)
		  || (k < j
		      && (strncmp (revname, filenames[k+1], strlen (revname)) 
			  == 0)))
		;
	      else
		found = filenames[k];
	      break;
	    }
	  if (cmp > 0)
	    i = k+1;
	  else
	    j = k-1;
	}
      while (i <= j);

      free (revname);
    }

  if (found && strlen (found) > strlen (name))
    return reverse (found);
  else
    return name;
}



Anthony Green committed
310 311
/* Handle "SourceFile" attribute. */

312
static void
313
set_source_filename (JCF *jcf, int index)
Anthony Green committed
314 315
{
  tree sfname_id = get_name_constant (jcf, index);
Zack Weinberg committed
316
  const char *sfname = IDENTIFIER_POINTER (sfname_id);
317 318 319
  const char *old_filename = input_filename;
  int new_len = IDENTIFIER_LENGTH (sfname_id);
  if (old_filename != NULL)
Anthony Green committed
320
    {
321
      int old_len = strlen (old_filename);
Anthony Green committed
322 323 324
      /* Use the current input_filename (derived from the class name)
	 if it has a directory prefix, but otherwise matches sfname. */
      if (old_len > new_len
Kai Tietz committed
325
	  && filename_cmp (sfname, old_filename + old_len - new_len) == 0
326 327
	  && (old_filename[old_len - new_len - 1] == '/'
	      || old_filename[old_len - new_len - 1] == '\\'))
328
	return;
Anthony Green committed
329
    }
330 331 332 333
  if (strchr (sfname, '/') == NULL && strchr (sfname, '\\') == NULL)
    {
      const char *class_name
	= IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class)));
334
      const char *dot = strrchr (class_name, '.');
335 336
      if (dot != NULL)
	{
337 338
	  /* Length of prefix, not counting final dot. */
	  int i = dot - class_name;
339
	  /* Concatenate current package prefix with new sfname. */
340
	  char *buf = XNEWVEC (char, i + new_len + 2); /* Space for '.' and '\0'. */
341 342 343
	  strcpy (buf + i + 1, sfname);
	  /* Copy package from class_name, replacing '.' by DIR_SEPARATOR.
	     Note we start at the end with the final package dot. */
344 345
	  for (; i >= 0;  i--)
	    {
346 347 348 349
	      char c = class_name[i];
	      if (c == '.')
		c = DIR_SEPARATOR;
	      buf[i] = c;
350 351
	    }
	  sfname_id = get_identifier (buf);
352
	  free (buf);
353 354 355 356
	  sfname = IDENTIFIER_POINTER (sfname_id);
	}
    }
      
357
  sfname = find_sourcefile (sfname);
358
  ORDINARY_MAP_FILE_NAME (LINEMAPS_LAST_ORDINARY_MAP (line_table)) = sfname;
359
  if (current_class == main_class) main_input_filename = sfname;
Anthony Green committed
360 361
}

362 363 364 365 366 367



/* Annotation handling.  

   The technique we use here is to copy the annotation data directly
368
   from the input class file into the output file.  We don't decode the
369
   data at all, merely rewriting constant indexes whenever we come
370
   across them: this is necessary because the constant pool in the
371
   output file isn't the same as the constant pool in the input.
372 373 374 375

   The main advantage of this technique is that the resulting
   annotation data is pointer-free, so it doesn't have to be relocated
   at startup time.  As a consequence of this, annotations have no
376
   performance impact unless they are used.  Also, this representation
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
   is very dense.  */


/* Expand TYPE_REFLECTION_DATA by DELTA bytes.  Return the address of
   the start of the newly allocated region.  */

static unsigned char*
annotation_grow (int delta)
{
  unsigned char **data = &TYPE_REFLECTION_DATA (current_class);
  long *datasize = &TYPE_REFLECTION_DATASIZE (current_class);
  long len = *datasize;

  if (*data == NULL)
    {
392
      *data = XNEWVAR (unsigned char, delta);
393 394 395 396 397
    }
  else
    {
      int newlen = *datasize + delta;
      if (floor_log2 (newlen) != floor_log2 (*datasize))
398
	*data = XRESIZEVAR (unsigned char, *data,  2 << (floor_log2 (newlen)));
399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498
    }
  *datasize += delta;
  return *data + len;
}

/* annotation_rewrite_TYPE.  Rewrite various int types at p.  Use Java
   byte order (i.e. big endian.)  */

static void
annotation_rewrite_byte (unsigned int n, unsigned char *p)
{
  p[0] = n;
}

static void
annotation_rewrite_short (unsigned int n, unsigned char *p)
{
  p[0] = n>>8;
  p[1] = n;
}

static void
annotation_rewrite_int (unsigned int n, unsigned char *p)
{
  p[0] = n>>24;
  p[1] = n>>16;
  p[2] = n>>8;
  p[3] = n;
}

/* Read a 16-bit unsigned int in Java byte order (i.e. big
   endian.)  */

static uint16
annotation_read_short (unsigned char *p)
{
  uint16 tmp = p[0];
  tmp = (tmp << 8) | p[1];
  return tmp;
}

/* annotation_write_TYPE.  Rewrite various int types, appending them
   to TYPE_REFLECTION_DATA.  Use Java byte order (i.e. big
   endian.)  */

static void
annotation_write_byte (unsigned int n)
{
  annotation_rewrite_byte (n, annotation_grow (1));
}

static void
annotation_write_short (unsigned int n)
{
  annotation_rewrite_short (n, annotation_grow (2));
}

static void
annotation_write_int (unsigned int n)
{
  annotation_rewrite_int (n, annotation_grow (4));
}

/* Create a 64-bit constant in the constant pool.

   This is used for both integer and floating-point types.  As a
   consequence, it will not work if the target floating-point format
   is anything other than IEEE-754.  While this is arguably a bug, the
   runtime library makes exactly the same assumption and it's unlikely
   that Java will ever run on a non-IEEE machine.  */

static int 
handle_long_constant (JCF *jcf, CPool *cpool, enum cpool_tag kind,
		    int index, bool big_endian)
{
  /* If we're on a 64-bit platform we can fit a long or double
     into the same space as a jword.  */
  if (POINTER_SIZE >= 64)
    index = find_constant1 (cpool, kind, JPOOL_LONG (jcf, index));

  /* In a compiled program the constant pool is in native word
     order.  How weird is that???  */
  else if (big_endian)
    index = find_constant2 (cpool, kind,
			    JPOOL_INT (jcf, index), 
			    JPOOL_INT (jcf, index+1));
  else
    index = find_constant2 (cpool, kind,
			    JPOOL_INT (jcf, index+1), 
			    JPOOL_INT (jcf, index));
  
  return index;
}

/* Given a class file and an index into its constant pool, create an
   entry in the outgoing constant pool for the same item.  */

static uint16
handle_constant (JCF *jcf, int index, enum cpool_tag purpose)
{
499
  unsigned int kind;
500 501 502 503 504 505 506 507
  CPool *cpool = cpool_for_class (output_class);
  
  if (index == 0)
    return 0;

  if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, index))
    error ("<constant pool index %d not in range>", index);
  
508
  kind = JPOOL_TAG (jcf, index);
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555

  if ((kind & ~CONSTANT_ResolvedFlag) != purpose)
    {
      if (purpose == CONSTANT_Class
	  && kind == CONSTANT_Utf8)
	;
      else
	error ("<constant pool index %d unexpected type", index);
    }

  switch (kind)
    {
    case CONSTANT_Class:
    case CONSTANT_ResolvedClass:
      {
	/* For some reason I know not the what of, class names in
	   annotations are UTF-8 strings in the constant pool but
	   class names in EnclosingMethod attributes are real class
	   references.  Set CONSTANT_LazyFlag here so that the VM
	   doesn't attempt to resolve them at class initialization
	   time.  */
	tree resolved_class, class_name;
	resolved_class = get_class_constant (jcf, index);
	class_name = build_internal_class_name (resolved_class);
	index = alloc_name_constant (CONSTANT_Class | CONSTANT_LazyFlag,
				     (unmangle_classname 
				      (IDENTIFIER_POINTER(class_name),
				       IDENTIFIER_LENGTH(class_name))));
	break;
      }
    case CONSTANT_Utf8:
      {
	tree utf8 = get_constant (jcf, index);
	if (purpose == CONSTANT_Class)
	  /* Create a constant pool entry for a type signature.  This
	     one has '.' rather than '/' because it isn't going into a
	     class file, it's going into a compiled object.
	     
	     This has to match the logic in
	     _Jv_ClassReader::prepare_pool_entry().  */
	  utf8 = unmangle_classname (IDENTIFIER_POINTER(utf8),
				     IDENTIFIER_LENGTH(utf8));
	index = alloc_name_constant (kind, utf8);
      }
      break;

    case CONSTANT_Long:
556
      index = handle_long_constant (jcf, cpool, CONSTANT_Long, index,
557
				    targetm.words_big_endian ());
558 559 560
      break;
      
    case CONSTANT_Double:
561
      index = handle_long_constant (jcf, cpool, CONSTANT_Double, index,
562
				    targetm.float_words_big_endian ());
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
      break;

    case CONSTANT_Float:
    case CONSTANT_Integer:
      index = find_constant1 (cpool, kind, JPOOL_INT (jcf, index));
      break;
      
    case CONSTANT_NameAndType:
      {
	uint16 name = JPOOL_USHORT1 (jcf, index);
	uint16 sig = JPOOL_USHORT2 (jcf, index);
	uint32 name_index = handle_constant (jcf, name, CONSTANT_Utf8);
	uint32 sig_index = handle_constant (jcf, sig, CONSTANT_Class);
	jword new_index = (name_index << 16) | sig_index;
	index = find_constant1 (cpool, kind, new_index);
      }
      break;

    default:
      abort ();
    }
  
  return index;
}

/* Read an element_value structure from an annotation in JCF.  Return
   the constant pool index for the resulting constant pool entry.  */

static int
handle_element_value (JCF *jcf, int level)
{
  uint8 tag = JCF_readu (jcf);
  int index = 0;

  annotation_write_byte (tag);
  switch (tag)
    {
    case 'B':
    case 'C':
    case 'S':
    case 'Z':
    case 'I':
      {
	uint16 cindex = JCF_readu2 (jcf);
	index = handle_constant (jcf, cindex,
				 CONSTANT_Integer);
	annotation_write_short (index);
      }
      break;
    case 'D':
      {
	uint16 cindex = JCF_readu2 (jcf);
	index = handle_constant (jcf, cindex,
				 CONSTANT_Double);
	annotation_write_short (index);
      }
      break;
    case 'F':
      {
	uint16 cindex = JCF_readu2 (jcf);
	index = handle_constant (jcf, cindex,
				 CONSTANT_Float);
	annotation_write_short (index);
      }
      break;
    case 'J':
      {
	uint16 cindex = JCF_readu2 (jcf);
	index = handle_constant (jcf, cindex,
				 CONSTANT_Long);
	annotation_write_short (index);
      }
      break;
    case 's':
      {
	uint16 cindex = JCF_readu2 (jcf);
	/* Despite what the JVM spec says, compilers generate a Utf8
	   constant here, not a String.  */
	index = handle_constant (jcf, cindex,
				 CONSTANT_Utf8);
	annotation_write_short (index);
      }
      break;

    case 'e':
      {
	uint16 type_name_index = JCF_readu2 (jcf);
	uint16 const_name_index = JCF_readu2 (jcf);
	index = handle_constant (jcf, type_name_index,
				 CONSTANT_Class);
	annotation_write_short (index);
	index = handle_constant (jcf, const_name_index,
				 CONSTANT_Utf8);
	annotation_write_short (index);
     }
      break;
    case 'c':
      {
	uint16 class_info_index = JCF_readu2 (jcf);
	index = handle_constant (jcf, class_info_index,
				 CONSTANT_Class);
	annotation_write_short (index);
      }
      break;
    case '@':
      {
	handle_annotation (jcf, level + 1);
      }
      break;
    case '[':
      {
	uint16 n_array_elts = JCF_readu2 (jcf);
	annotation_write_short (n_array_elts);
	while (n_array_elts--)
	  handle_element_value (jcf, level + 1);
      }
      break;
    default:
      abort();
      break;
    }
  return index;
}

/* Read an annotation structure from JCF.  Write it to the
   reflection_data field of the outgoing class.  */

static void
handle_annotation (JCF *jcf, int level)
{
  uint16 type_index = JCF_readu2 (jcf);
  uint16 npairs = JCF_readu2 (jcf);
  int index = handle_constant (jcf, type_index,
			       CONSTANT_Class);
  annotation_write_short (index);
  annotation_write_short (npairs);
  while (npairs--)
    {
      uint16 name_index = JCF_readu2 (jcf);
      index = handle_constant (jcf, name_index,
			       CONSTANT_Utf8);
      annotation_write_short (index);
      handle_element_value (jcf, level + 2);
    }
}

/* Read an annotation count from JCF, and write the following
710
   annotations to the reflection_data field of the outgoing class.  */
711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746

static void
handle_annotations (JCF *jcf, int level)
{
  uint16 num = JCF_readu2 (jcf);
  annotation_write_short (num);
  while (num--)
    handle_annotation (jcf, level);
}

/* As handle_annotations(), but perform a sanity check that we write
   the same number of bytes that we were expecting.  */

static void
handle_annotation_attribute (int ATTRIBUTE_UNUSED index, JCF *jcf, 
			     long length)
{
  long old_datasize = TYPE_REFLECTION_DATASIZE (current_class);

  handle_annotations (jcf, 0);

  gcc_assert (old_datasize + length
	      == TYPE_REFLECTION_DATASIZE (current_class));
}

/* gcj permutes its fields array after generating annotation_data, so
   we have to fixup field indexes for fields that have moved.  Given
   ARG, a VEC_int, fixup the field indexes in the reflection_data of
   the outgoing class.  We use field_offsets to tell us where the
   fixups must go.  */

void
rewrite_reflection_indexes (void *arg)
{
  bitmap_iterator bi;
  unsigned int offset;
747
  VEC(int, heap) *map = (VEC(int, heap) *) arg;
748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
  unsigned char *data = TYPE_REFLECTION_DATA (current_class);

  if (map)
    {
      EXECUTE_IF_SET_IN_BITMAP (field_offsets, 0, offset, bi)
	{
	  uint16 index = annotation_read_short (data + offset);
	  annotation_rewrite_short 
	    (VEC_index (int, map, index), data + offset);
	}
    }
}

/* Read the RuntimeVisibleAnnotations from JCF and write them to the
   reflection_data of the outgoing class.  */

static void
handle_member_annotations (int member_index, JCF *jcf, 
			   const unsigned char *name ATTRIBUTE_UNUSED, 
			   long len, jv_attr_type member_type)
{
  int new_len = len + 1;
  annotation_write_byte (member_type);
  if (member_type != JV_CLASS_ATTR)
    new_len += 2;
  annotation_write_int (new_len);
  annotation_write_byte (JV_ANNOTATIONS_KIND);
  if (member_type == JV_FIELD_ATTR)
    bitmap_set_bit (field_offsets, TYPE_REFLECTION_DATASIZE (current_class));
  if (member_type != JV_CLASS_ATTR)
    annotation_write_short (member_index);
  handle_annotation_attribute (member_index, jcf, len);
}

/* Read the RuntimeVisibleParameterAnnotations from JCF and write them
   to the reflection_data of the outgoing class.  */

static void
handle_parameter_annotations (int member_index, JCF *jcf, 
			      const unsigned char *name ATTRIBUTE_UNUSED, 
			      long len, jv_attr_type member_type)
{
  int new_len = len + 1;
  uint8 num;
  annotation_write_byte (member_type);
  if (member_type != JV_CLASS_ATTR)
    new_len += 2;
  annotation_write_int (new_len);
  annotation_write_byte (JV_PARAMETER_ANNOTATIONS_KIND);
  if (member_type != JV_CLASS_ATTR)
    annotation_write_short (member_index);
  num = JCF_readu (jcf);
  annotation_write_byte (num);
  while (num--)
    handle_annotations (jcf, 0);
}


/* Read the AnnotationDefault data from JCF and write them to the
   reflection_data of the outgoing class.  */

static void
handle_default_annotation (int member_index, JCF *jcf, 
			   const unsigned char *name ATTRIBUTE_UNUSED, 
			   long len, jv_attr_type member_type)
{
  int new_len = len + 1;
  annotation_write_byte (member_type);
  if (member_type != JV_CLASS_ATTR)
    new_len += 2;
  annotation_write_int (new_len);
  annotation_write_byte (JV_ANNOTATION_DEFAULT_KIND);
  if (member_type != JV_CLASS_ATTR)
    annotation_write_short (member_index);
  handle_element_value (jcf, 0);
}

/* As above, for the EnclosingMethod attribute.  */

static void
handle_enclosingmethod_attribute (int member_index, JCF *jcf, 
			   const unsigned char *name ATTRIBUTE_UNUSED, 
			   long len, jv_attr_type member_type)
{
  int new_len = len + 1;
  uint16 index;
  annotation_write_byte (member_type);
  if (member_type != JV_CLASS_ATTR)
    new_len += 2;
  annotation_write_int (new_len);
  annotation_write_byte (JV_ENCLOSING_METHOD_KIND);
  if (member_type != JV_CLASS_ATTR)
    annotation_write_short (member_index);

  index = JCF_readu2 (jcf);
  index = handle_constant (jcf, index, CONSTANT_Class);
  annotation_write_short (index);

  index = JCF_readu2 (jcf);
  index = handle_constant (jcf, index, CONSTANT_NameAndType);
  annotation_write_short (index);
}

/* As above, for the Signature attribute.  */

static void
handle_signature_attribute (int member_index, JCF *jcf, 
			   const unsigned char *name ATTRIBUTE_UNUSED, 
			   long len, jv_attr_type member_type)
{
  int new_len = len + 1;
  uint16 index;
  annotation_write_byte (member_type);
  if (member_type != JV_CLASS_ATTR)
    new_len += 2;
  annotation_write_int (new_len);
  annotation_write_byte (JV_SIGNATURE_KIND);
  if (member_type != JV_CLASS_ATTR)
    annotation_write_short (member_index);

  index = JCF_readu2 (jcf);
  index = handle_constant (jcf, index, CONSTANT_Utf8);
  annotation_write_short (index);
}
  


Anthony Green committed
875 876 877 878
#define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)

#define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
{ tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
879
  output_class = current_class = give_name_to_class (jcf, THIS); \
Anthony Green committed
880 881 882 883 884 885 886 887 888
  set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}

#define HANDLE_CLASS_INTERFACE(INDEX) \
  add_interface (current_class, get_class_constant (jcf, INDEX))

#define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
{ int sig_index = SIGNATURE; \
  current_field = add_field (current_class, get_name_constant (jcf, NAME), \
			     parse_signature (jcf, sig_index), ACCESS_FLAGS); \
889 890 891 892
 set_java_signature (TREE_TYPE (current_field), JPOOL_UTF (jcf, sig_index)); \
 if ((ACCESS_FLAGS) & ACC_FINAL) \
   MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (current_field); \
}
Anthony Green committed
893 894 895 896 897 898

#define HANDLE_END_FIELDS() \
  (current_field = NULL_TREE)

#define HANDLE_CONSTANTVALUE(INDEX) \
{ tree constant;  int index = INDEX; \
899
  if (JPOOL_TAG (jcf, index) == CONSTANT_String) { \
Anthony Green committed
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914
    tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); \
    constant = build_utf8_ref (name); \
  } \
  else \
    constant = get_constant (jcf, index); \
  set_constant_value (current_field, constant); }

#define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
 (current_method = add_method (current_class, ACCESS_FLAGS, \
			       get_name_constant (jcf, NAME), \
			       get_name_constant (jcf, SIGNATURE)), \
  DECL_LOCALVARIABLES_OFFSET (current_method) = 0, \
  DECL_LINENUMBERS_OFFSET (current_method) = 0)

#define HANDLE_END_METHODS() \
915
{ current_method = NULL_TREE; }
Anthony Green committed
916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932

#define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
{ DECL_MAX_STACK (current_method) = (MAX_STACK); \
  DECL_MAX_LOCALS (current_method) = (MAX_LOCALS); \
  DECL_CODE_LENGTH (current_method) = (CODE_LENGTH); \
  DECL_CODE_OFFSET (current_method) = JCF_TELL (jcf); }

#define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
{ int n = (COUNT); \
  DECL_LOCALVARIABLES_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
  JCF_SKIP (jcf, n * 10); }

#define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
{ int n = (COUNT); \
  DECL_LINENUMBERS_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
  JCF_SKIP (jcf, n * 4); }

933 934 935
#define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
{ \
  int n = COUNT; \
936 937
  VEC (tree,gc) *v = VEC_alloc (tree, gc, n); \
  gcc_assert (DECL_FUNCTION_THROWS (current_method) == NULL); \
938 939 940
  while (--n >= 0) \
    { \
      tree thrown_class = get_class_constant (jcf, JCF_readu2 (jcf)); \
941
      VEC_quick_push (tree, v, thrown_class); \
942
    } \
943
  DECL_FUNCTION_THROWS (current_method) = v; \
944 945
}

946 947
#define HANDLE_DEPRECATED_ATTRIBUTE()  handle_deprecated ()

948 949
/* Link seen inner classes to their outer context and register the
   inner class to its outer context. They will be later loaded.  */
950
#define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
951
  handle_innerclass_attribute (COUNT, jcf, attribute_length)
952 953 954

#define HANDLE_SYNTHETIC_ATTRIBUTE()					\
{									\
955 956 957
  /* Irrelevant decls should have been nullified by the END macros.	\
     DECL_ARTIFICIAL on fields is used for something else (See		\
     PUSH_FIELD in java-tree.h) */					\
958 959
  if (current_method)							\
    DECL_ARTIFICIAL (current_method) = 1;				\
960 961 962
  else if (current_field)						\
    FIELD_SYNTHETIC (current_field) = 1;				\
  else									\
Andrew Haley committed
963
    TYPE_SYNTHETIC (current_class) = 1;					\
964 965
}

966 967 968 969 970 971
#define HANDLE_GCJCOMPILED_ATTRIBUTE()		\
{ 						\
  if (current_class == object_type_node)	\
    jcf->right_zip = 1;				\
}

972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
#define HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE()			\
{									\
  handle_member_annotations (index, jcf, name_data, attribute_length, attr_type); \
}

#define HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE()	\
{							\
  JCF_SKIP(jcf, attribute_length);			\
}

#define HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE()		\
{									\
  handle_parameter_annotations (index, jcf, name_data, attribute_length, attr_type); \
}

#define HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE()	\
{								\
  JCF_SKIP(jcf, attribute_length);				\
}

#define HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE()				\
{									\
  handle_default_annotation (index, jcf, name_data, attribute_length, attr_type); \
}

#define HANDLE_ENCLOSINGMETHOD_ATTRIBUTE()				\
{									\
  handle_enclosingmethod_attribute (index, jcf, name_data,		\
				    attribute_length, attr_type);	\
}

#define HANDLE_SIGNATURE_ATTRIBUTE()				\
{								\
  handle_signature_attribute (index, jcf, name_data,		\
			      attribute_length, attr_type);	\
}

Anthony Green committed
1009 1010 1011
#include "jcf-reader.c"

tree
1012
parse_signature (JCF *jcf, int sig_index)
Anthony Green committed
1013
{
1014 1015 1016 1017 1018 1019
  gcc_assert (sig_index > 0
	      && sig_index < JPOOL_SIZE (jcf)
	      && JPOOL_TAG (jcf, sig_index) == CONSTANT_Utf8);

  return parse_signature_string (JPOOL_UTF_DATA (jcf, sig_index),
				 JPOOL_UTF_LENGTH (jcf, sig_index));
Anthony Green committed
1020 1021 1022
}

tree
1023
get_constant (JCF *jcf, int index)
Anthony Green committed
1024 1025 1026 1027 1028 1029 1030
{
  tree value;
  int tag;
  if (index <= 0 || index >= JPOOL_SIZE(jcf))
    goto bad;
  tag = JPOOL_TAG (jcf, index);
  if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
1031
    return jcf->cpool.data[index].t;
Anthony Green committed
1032 1033 1034 1035 1036
  switch (tag)
    {
    case CONSTANT_Integer:
      {
	jint num = JPOOL_INT(jcf, index);
1037
	value = build_int_cst (int_type_node, num);
Anthony Green committed
1038 1039 1040 1041
	break;
      }
    case CONSTANT_Long:
      {
1042 1043 1044 1045 1046 1047 1048 1049 1050
	unsigned HOST_WIDE_INT num;
	double_int val;

	num = JPOOL_UINT (jcf, index);
	val = double_int_lshift (uhwi_to_double_int (num), 32, 64, false);
	num = JPOOL_UINT (jcf, index + 1);
	val = double_int_ior (val, uhwi_to_double_int (num));

	value = double_int_to_tree (long_type_node, val);
Anthony Green committed
1051 1052
	break;
      }
1053

Anthony Green committed
1054
    case CONSTANT_Float:
1055 1056 1057 1058 1059 1060 1061 1062 1063
      {
	jint num = JPOOL_INT(jcf, index);
	long buf = num;
	REAL_VALUE_TYPE d;

	real_from_target_fmt (&d, &buf, &ieee_single_format);
	value = build_real (float_type_node, d);
	break;
      }
1064

Anthony Green committed
1065
    case CONSTANT_Double:
1066 1067 1068
      {
	long buf[2], lo, hi;
	REAL_VALUE_TYPE d;
1069

1070 1071
	hi = JPOOL_UINT (jcf, index);
	lo = JPOOL_UINT (jcf, index+1);
1072

1073
	if (targetm.float_words_big_endian ())
1074 1075 1076
	  buf[0] = hi, buf[1] = lo;
	else
	  buf[0] = lo, buf[1] = hi;
1077

1078
	real_from_target_fmt (&d, buf, &ieee_double_format);
1079 1080 1081
	value = build_real (double_type_node, d);
	break;
      }
1082

Anthony Green committed
1083 1084 1085
    case CONSTANT_String:
      {
	tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
1086
	const char *utf8_ptr = IDENTIFIER_POINTER (name);
Anthony Green committed
1087
	int utf8_len = IDENTIFIER_LENGTH (name);
Zack Weinberg committed
1088
	const unsigned char *utf8;
1089
	int i;
Anthony Green committed
1090

1091
	/* Check for a malformed Utf8 string.  */
Zack Weinberg committed
1092 1093 1094
	utf8 = (const unsigned char *) utf8_ptr;
	i = utf8_len;
	while (i > 0)
Anthony Green committed
1095
	  {
Zack Weinberg committed
1096
	    int char_len = UT8_CHAR_LENGTH (*utf8);
1097
	    if (char_len < 0 || char_len > 3 || char_len > i)
1098 1099
 	      fatal_error ("bad string constant");

Zack Weinberg committed
1100
	    utf8 += char_len;
Anthony Green committed
1101 1102 1103
	    i -= char_len;
	  }

1104 1105
	/* Allocate a new string value.  */
	value = build_string (utf8_len, utf8_ptr);
Zack Weinberg committed
1106
	TREE_TYPE (value) = build_pointer_type (string_type_node);
Anthony Green committed
1107 1108 1109 1110 1111
      }
      break;
    default:
      goto bad;
    }
1112
  JPOOL_TAG (jcf, index) = tag | CONSTANT_ResolvedFlag;
1113
  jcf->cpool.data[index].t = value;
Anthony Green committed
1114 1115
  return value;
 bad:
1116 1117
  internal_error ("bad value constant type %d, index %d", 
		  JPOOL_TAG (jcf, index), index);
Anthony Green committed
1118 1119 1120
}

tree
1121
get_name_constant (JCF *jcf, int index)
Anthony Green committed
1122 1123
{
  tree name = get_constant (jcf, index);
1124
  gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
Anthony Green committed
1125 1126 1127
  return name;
}

1128
/* Handle reading innerclass attributes. If a nonzero entry (denoting
1129 1130 1131 1132
   a non anonymous entry) is found, We augment the inner class list of
   the outer context with the newly resolved innerclass.  */

static void
1133
handle_innerclass_attribute (int count, JCF *jcf, int attribute_length)
1134
{
1135 1136 1137 1138 1139 1140 1141
  int c = count;

  annotation_write_byte (JV_CLASS_ATTR);
  annotation_write_int (attribute_length+1);
  annotation_write_byte (JV_INNER_CLASSES_KIND);
  annotation_write_short (count);

1142 1143 1144 1145 1146 1147 1148 1149
  while (c--)
    {
      /* Read inner_class_info_index. This may be 0 */
      int icii = JCF_readu2 (jcf);
      /* Read outer_class_info_index. If the innerclasses attribute
	 entry isn't a member (like an inner class) the value is 0. */
      int ocii = JCF_readu2 (jcf);
      /* Read inner_name_index. If the class we're dealing with is
1150
	 an anonymous class, it must be 0. */
1151
      int ini = JCF_readu2 (jcf);
1152 1153
      /* Read the access flag. */
      int acc = JCF_readu2 (jcf);
1154 1155 1156 1157 1158 1159

      annotation_write_short (handle_constant (jcf, icii, CONSTANT_Class));
      annotation_write_short (handle_constant (jcf, ocii, CONSTANT_Class));
      annotation_write_short (handle_constant (jcf, ini, CONSTANT_Utf8));
      annotation_write_short (acc);

1160 1161 1162
      /* If icii is 0, don't try to read the class. */
      if (icii >= 0)
	{
1163 1164
	  tree klass = get_class_constant (jcf, icii);
	  tree decl = TYPE_NAME (klass);
1165 1166 1167 1168 1169
          /* Skip reading further if ocii is null */
          if (DECL_P (decl) && !CLASS_COMPLETE_P (decl) && ocii)
	    {
	      tree outer = TYPE_NAME (get_class_constant (jcf, ocii));
	      tree alias = (ini ? get_name_constant (jcf, ini) : NULL_TREE);
1170
	      set_class_decl_access_flags (acc, decl);
1171 1172 1173 1174 1175 1176 1177 1178 1179
	      DECL_CONTEXT (decl) = outer;
	      DECL_INNER_CLASS_LIST (outer) =
		tree_cons (decl, alias, DECL_INNER_CLASS_LIST (outer));
	      CLASS_COMPLETE_P (decl) = 1;
            }
	}
    }
}

Anthony Green committed
1180
static tree
1181
give_name_to_class (JCF *jcf, int i)
Anthony Green committed
1182
{
1183 1184 1185 1186
  gcc_assert (i > 0
	      && i < JPOOL_SIZE (jcf)
	      && JPOOL_TAG (jcf, i) == CONSTANT_Class);

Anthony Green committed
1187
    {
1188
      tree package_name = NULL_TREE, tmp;
Anthony Green committed
1189 1190 1191
      tree this_class;
      int j = JPOOL_USHORT1 (jcf, i);
      /* verify_constant_pool confirmed that j is a CONSTANT_Utf8. */
1192
      tree class_name = unmangle_classname ((const char *) JPOOL_UTF_DATA (jcf, j),
Anthony Green committed
1193 1194
					    JPOOL_UTF_LENGTH (jcf, j));
      this_class = lookup_class (class_name);
1195 1196
      {
      tree source_name = identifier_subst (class_name, "", '.', '/', ".java");
1197
      const char *sfname = find_sourcefile (IDENTIFIER_POINTER (source_name));
1198 1199
      linemap_add (line_table, LC_ENTER, false, sfname, 0);
      input_location = linemap_line_start (line_table, 0, 1);
1200 1201 1202 1203 1204
      file_start_location = input_location;
      DECL_SOURCE_LOCATION (TYPE_NAME (this_class)) = input_location;
      if (main_input_filename == NULL && jcf == main_jcf)
	main_input_filename = sfname;
      }
Anthony Green committed
1205

1206
      jcf->cpool.data[i].t = this_class;
Anthony Green committed
1207
      JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
1208 1209 1210
      split_qualified_name (&package_name, &tmp, 
      			    DECL_NAME (TYPE_NAME (this_class)));
      TYPE_PACKAGE (this_class) = package_name;
Anthony Green committed
1211 1212 1213 1214 1215 1216 1217
      return this_class;
    }
}

/* Get the class of the CONSTANT_Class whose constant pool index is I. */

tree
1218
get_class_constant (JCF *jcf, int i)
Anthony Green committed
1219 1220
{
  tree type;
1221 1222 1223
  gcc_assert (i > 0
	      && i < JPOOL_SIZE (jcf)
	      && (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) == CONSTANT_Class);
Anthony Green committed
1224 1225 1226 1227 1228

  if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass)
    {
      int name_index = JPOOL_USHORT1 (jcf, i);
      /* verify_constant_pool confirmed that name_index is a CONSTANT_Utf8. */
1229
      const char *name = (const char *) JPOOL_UTF_DATA (jcf, name_index);
Anthony Green committed
1230
      int nlength = JPOOL_UTF_LENGTH (jcf, name_index);
1231

Anthony Green committed
1232
      if (name[0] == '[')  /* Handle array "classes". */
1233
	  type = TREE_TYPE (parse_signature_string ((const unsigned char *) name, nlength));
Anthony Green committed
1234 1235 1236 1237 1238
      else
        { 
          tree cname = unmangle_classname (name, nlength);
          type = lookup_class (cname);
	}
1239
      jcf->cpool.data[i].t = type;
Anthony Green committed
1240 1241 1242
      JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
    }
  else
1243
    type = jcf->cpool.data[i].t;
Anthony Green committed
1244 1245 1246
  return type;
}

Per Bothner committed
1247 1248 1249 1250 1251 1252
/* Read a class with the fully qualified-name NAME.
   Return 1 iff we read the requested file.
   (It is still possible we failed if the file did not
   define the class it is supposed to.) */

int
1253
read_class (tree name)
Anthony Green committed
1254 1255
{
  JCF this_jcf, *jcf;
1256
  tree icv, klass = NULL_TREE;
Anthony Green committed
1257
  tree save_current_class = current_class;
1258
  tree save_output_class = output_class;
1259
  location_t save_location = input_location;
Anthony Green committed
1260 1261
  JCF *save_current_jcf = current_jcf;

1262
  if ((icv = IDENTIFIER_CLASS_VALUE (name)) != NULL_TREE)
1263
    {
1264 1265
      klass = TREE_TYPE (icv);
      jcf = TYPE_JCF (klass);
1266 1267 1268 1269 1270 1271
    }
  else
    jcf = NULL;

  if (jcf == NULL)
    {
1272
      const char* path_name;
1273 1274
      this_jcf.zipd = NULL;
      jcf = &this_jcf;
1275 1276 1277
      
      path_name = find_class (IDENTIFIER_POINTER (name),
			      IDENTIFIER_LENGTH (name),
1278
			      &this_jcf);
1279
      if (path_name == 0)
Mark Mitchell committed
1280
	return 0;
1281
      else
1282
	free(CONST_CAST (char *, path_name));
1283
    }
1284 1285

  current_jcf = jcf;
Anthony Green committed
1286

1287
  if (klass == NULL_TREE || ! CLASS_PARSED_P (klass))
1288
    {
1289
      output_class = current_class = klass;
1290 1291 1292 1293 1294 1295
      if (JCF_SEEN_IN_ZIP (current_jcf))
	read_zip_member(current_jcf,
			current_jcf->zipd, current_jcf->zipd->zipf);
      jcf_parse (current_jcf);
      /* Parsing might change the class, in which case we have to
	 put it back where we found it.  */
1296
      if (current_class != klass && icv != NULL_TREE)
1297
	TREE_TYPE (icv) = current_class;
1298
      klass = current_class;
1299
    }
1300 1301
  layout_class (klass);
  load_inner_classes (klass);
Anthony Green committed
1302

1303 1304
  output_class = save_output_class;
  current_class = save_current_class;
1305
  input_location = save_location;
Anthony Green committed
1306
  current_jcf = save_current_jcf;
Per Bothner committed
1307 1308 1309 1310 1311 1312 1313
  return 1;
}

/* Load CLASS_OR_NAME. CLASS_OR_NAME can be a mere identifier if
   called from the parser, otherwise it's a RECORD_TYPE node. If
   VERBOSE is 1, print error message on failure to load a class. */
void
1314
load_class (tree class_or_name, int verbose)
Per Bothner committed
1315
{
1316
  tree name, saved;
1317 1318 1319 1320 1321 1322 1323 1324
  int class_loaded = 0;
  tree class_decl = NULL_TREE;
  bool is_compiled_class = false;

  /* We've already failed, don't try again.  */
  if (TREE_CODE (class_or_name) == RECORD_TYPE
      && TYPE_DUMMY (class_or_name))
    return;
Per Bothner committed
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334

  /* class_or_name can be the name of the class we want to load */
  if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
    name = class_or_name;
  /* In some cases, it's a dependency that we process earlier that
     we though */
  else if (TREE_CODE (class_or_name) == TREE_LIST)
    name = TYPE_NAME (TREE_PURPOSE (class_or_name));
  /* Or it's a type in the making */
  else
1335 1336
    name = DECL_NAME (TYPE_NAME (class_or_name));

1337 1338 1339 1340 1341 1342 1343 1344 1345
  class_decl = IDENTIFIER_CLASS_VALUE (name);
  if (class_decl != NULL_TREE)
    {
      tree type = TREE_TYPE (class_decl);
      is_compiled_class
	= ((TYPE_JCF (type) && JCF_SEEN_IN_ZIP (TYPE_JCF (type)))
	   || CLASS_FROM_CURRENTLY_COMPILED_P (type));
    }

1346
  saved = name;
1347 1348 1349 1350 1351 1352 1353 1354
  
  /* If flag_verify_invocations is unset, we don't try to load a class
     unless we're looking for Object (which is fixed by the ABI) or
     it's a class that we're going to compile.  */
  if (flag_verify_invocations
      || class_or_name == object_type_node
      || is_compiled_class
      || TREE_CODE (class_or_name) == IDENTIFIER_NODE)
1355
    {
1356 1357
      while (1)
	{
1358
	  const char *separator;
1359

1360 1361 1362 1363 1364 1365 1366 1367 1368 1369
	  /* We've already loaded it.  */
	  if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE)
	    {
	      tree tmp_decl = IDENTIFIER_CLASS_VALUE (name);
	      if (CLASS_PARSED_P (TREE_TYPE (tmp_decl)))
		break;
	    }
	
	  if (read_class (name))
	    break;
1370

1371
	  /* We failed loading name. Now consider that we might be looking
1372
	     for an inner class.  */
1373 1374
	  if ((separator = strrchr (IDENTIFIER_POINTER (name), '$'))
	      || (separator = strrchr (IDENTIFIER_POINTER (name), '.')))
1375 1376 1377
	    name = get_identifier_with_length (IDENTIFIER_POINTER (name),
					       (separator
						- IDENTIFIER_POINTER (name)));
1378 1379
	  /* Otherwise, we failed, we bail. */
	  else
1380
	    break;
1381 1382
	}

1383 1384 1385 1386 1387 1388 1389 1390 1391 1392
      {
	/* have we found the class we're looking for?  */
	tree type_decl = IDENTIFIER_CLASS_VALUE (saved);
	tree type = type_decl ? TREE_TYPE (type_decl) : NULL;
	class_loaded = type && CLASS_PARSED_P (type);
      }	      
    }
  
  if (!class_loaded)
    {
1393
      if (flag_verify_invocations || ! flag_indirect_dispatch)
1394 1395 1396 1397 1398 1399 1400 1401
	{
	  if (verbose)
	    error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
	}
      else if (verbose)
	{
	  /* This is just a diagnostic during testing, not a real problem.  */
	  if (!quiet_flag)
1402 1403
	    warning (0, "cannot find file for class %s", 
		     IDENTIFIER_POINTER (saved));
1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414
	  
	  /* Fake it.  */
	  if (TREE_CODE (class_or_name) == RECORD_TYPE)
	    {
	      set_super_info (0, class_or_name, object_type_node, 0);
	      TYPE_DUMMY (class_or_name) = 1;
	      /* We won't be able to output any debug info for this class.  */
	      DECL_IGNORED_P (TYPE_NAME (class_or_name)) = 1;
	    }
	}
    }
Anthony Green committed
1415 1416 1417 1418
}

/* Parse the .class file JCF. */

1419
static void
1420
jcf_parse (JCF* jcf)
Anthony Green committed
1421 1422
{
  int i, code;
1423 1424

  bitmap_clear (field_offsets);
Anthony Green committed
1425 1426

  if (jcf_parse_preamble (jcf) != 0)
1427
    fatal_error ("not a valid Java .class file");
Anthony Green committed
1428 1429
  code = jcf_parse_constant_pool (jcf);
  if (code != 0)
1430
    fatal_error ("error while parsing constant pool");
Anthony Green committed
1431 1432
  code = verify_constant_pool (jcf);
  if (code > 0)
1433
    fatal_error ("error in constant pool entry #%d\n", code);
Anthony Green committed
1434 1435 1436 1437 1438

  jcf_parse_class (jcf);
  if (main_class == NULL_TREE)
    main_class = current_class;
  if (! quiet_flag && TYPE_NAME (current_class))
1439 1440
    fprintf (stderr, " %s %s",
	     (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class", 
Anthony Green committed
1441
	     IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
1442 1443 1444
  if (CLASS_PARSED_P (current_class))
    {
      /* FIXME - where was first time */
Andrew Haley committed
1445
      fatal_error ("reading class %s for the second time from %s",
1446 1447 1448 1449
		   IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))),
		   jcf->filename);
    }
  CLASS_PARSED_P (current_class) = 1;
Anthony Green committed
1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462

  for (i = 1; i < JPOOL_SIZE(jcf); i++)
    {
      switch (JPOOL_TAG (jcf, i))
	{
	case CONSTANT_Class:
	  get_class_constant (jcf, i);
	  break;
	}
    }
  
  code = jcf_parse_fields (jcf);
  if (code != 0)
1463
    fatal_error ("error while parsing fields");
Anthony Green committed
1464 1465
  code = jcf_parse_methods (jcf);
  if (code != 0)
1466
    fatal_error ("error while parsing methods");
Anthony Green committed
1467 1468
  code = jcf_parse_final_attributes (jcf);
  if (code != 0)
1469
    fatal_error ("error while parsing final attributes");
1470 1471 1472 1473

  if (TYPE_REFLECTION_DATA (current_class))
    annotation_write_byte (JV_DONE_ATTR);

1474
  linemap_add (line_table, LC_LEAVE, false, NULL, 0);
Anthony Green committed
1475 1476 1477 1478 1479

  /* The fields of class_type_node are already in correct order. */
  if (current_class != class_type_node && current_class != object_type_node)
    TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class));

1480
  if (current_class == object_type_node)
1481
    layout_class_methods (object_type_node);
1482
  else
1483
    VEC_safe_push (tree, gc, all_class_list, TYPE_NAME (current_class));
1484
}
1485

1486 1487
/* If we came across inner classes, load them now. */
static void
1488
load_inner_classes (tree cur_class)
1489 1490 1491
{
  tree current;
  for (current = DECL_INNER_CLASS_LIST (TYPE_NAME (cur_class)); current;
1492
       current = TREE_CHAIN (current))
1493 1494 1495
    {
      tree name = DECL_NAME (TREE_PURPOSE (current));
      tree decl = IDENTIFIER_GLOBAL_VALUE (name);
1496 1497
      if (decl && ! CLASS_LOADED_P (TREE_TYPE (decl))
	  && !CLASS_BEING_LAIDOUT (TREE_TYPE (decl)))
1498 1499
	load_class (name, 1);
    }
Anthony Green committed
1500 1501
}

1502
static void
1503 1504 1505
duplicate_class_warning (const char *filename)
{
  location_t warn_loc;
1506 1507
  linemap_add (line_table, LC_RENAME, 0, filename, 0);
  warn_loc = linemap_line_start (line_table, 0, 1);
1508
  warning_at (warn_loc, 0, "duplicate class will only be compiled once");
1509 1510 1511
}

static void
1512 1513
java_layout_seen_class_methods (void)
{
1514 1515
  unsigned start = 0;
  unsigned end = VEC_length (tree, all_class_list);
1516 1517 1518

  while (1)
    {
1519 1520 1521 1522
      unsigned ix;
      unsigned new_length;

      for (ix = start; ix != end; ix++)
1523
        {
1524
	  tree decl = VEC_index (tree, all_class_list, ix);
1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
          tree cls = TREE_TYPE (decl);

	  input_location = DECL_SOURCE_LOCATION (decl);

          if (! CLASS_LOADED_P (cls))
            load_class (cls, 0);

          layout_class_methods (cls);
        }

      /* Note that new classes might have been added while laying out
         methods, changing the value of all_class_list.  */
1537 1538
      new_length = VEC_length (tree, all_class_list);
      if (end != new_length)
1539
	{
1540 1541
	  start = end;
	  end = new_length;
1542 1543 1544 1545 1546 1547 1548
	}
      else
	break;
    }
}

static void
1549
parse_class_file (void)
Anthony Green committed
1550
{
1551
  tree method;
1552
  location_t save_location = input_location;
Anthony Green committed
1553

1554
  java_layout_seen_class_methods ();
1555

1556
  input_location = DECL_SOURCE_LOCATION (TYPE_NAME (current_class));
1557 1558 1559 1560 1561
  {
    /* Re-enter the current file.  */
    expanded_location loc = expand_location (input_location);
    linemap_add (line_table, LC_ENTER, 0, loc.file, loc.line);
  }
1562
  file_start_location = input_location;
1563
  (*debug_hooks->start_source_file) (input_line, input_filename);
Anthony Green committed
1564

1565 1566
  java_mark_class_local (current_class);

1567 1568
  gen_indirect_dispatch_tables (current_class);

1569
  for (method = TYPE_METHODS (current_class);
1570
       method != NULL_TREE; method = DECL_CHAIN (method))
Anthony Green committed
1571 1572 1573
    {
      JCF *jcf = current_jcf;

1574
      if (METHOD_ABSTRACT (method) || METHOD_DUMMY (method))
Anthony Green committed
1575 1576
	continue;

1577 1578
      if (METHOD_NATIVE (method))
	{
1579 1580 1581
	  tree arg;
	  int  decl_max_locals;

1582 1583
	  if (! flag_jni)
	    continue;
1584 1585 1586 1587 1588 1589 1590 1591 1592 1593
	  /* We need to compute the DECL_MAX_LOCALS. We need to take
             the wide types into account too. */
	  for (arg = TYPE_ARG_TYPES (TREE_TYPE (method)), decl_max_locals = 0; 
	       arg != end_params_node;
	       arg = TREE_CHAIN (arg), decl_max_locals += 1)
	    {
	      if (TREE_VALUE (arg) && TYPE_IS_WIDE (TREE_VALUE (arg)))
		decl_max_locals += 1;
	    }
	  DECL_MAX_LOCALS (method) = decl_max_locals;
1594 1595
	  start_java_method (method);
	  give_name_to_locals (jcf);
1596
	  *get_stmts () = build_jni_stub (method);
1597 1598 1599 1600
	  end_java_method ();
	  continue;
	}

Anthony Green committed
1601 1602
      if (DECL_CODE_OFFSET (method) == 0)
	{
1603
	  current_function_decl = method;
Anthony Green committed
1604 1605 1606 1607
	  error ("missing Code attribute");
	  continue;
	}

1608
      input_location = DECL_SOURCE_LOCATION (TYPE_NAME (current_class));
Anthony Green committed
1609 1610
      if (DECL_LINENUMBERS_OFFSET (method))
	{
1611
	  int i;
1612
	  int min_line = 0;
1613
	  unsigned char *ptr;
Anthony Green committed
1614 1615 1616 1617 1618 1619 1620
	  JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method));
	  linenumber_count = i = JCF_readu2 (jcf);
	  linenumber_table = ptr = jcf->read_ptr;

	  for (ptr += 2; --i >= 0; ptr += 4)
	    {
	      int line = GET_u2 (ptr);
1621
	      /* Set initial input_line to smallest linenumber.
Anthony Green committed
1622
	       * Needs to be set before init_function_start. */
1623 1624 1625 1626
	      if (min_line == 0 || line < min_line)
		min_line = line;
	    }
	  if (min_line != 0)
1627
	    input_location = linemap_line_start (line_table, min_line, 1);
Anthony Green committed
1628 1629 1630 1631 1632 1633 1634 1635 1636
	}
      else
	{
	  linenumber_table = NULL;
	  linenumber_count = 0;
	}

      start_java_method (method);

1637 1638
      note_instructions (jcf, method);

Anthony Green committed
1639 1640
      give_name_to_locals (jcf);

1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655
      /* Bump up start_label_pc_this_method so we get a unique label number
	 and reset highest_label_pc_this_method. */
      if (highest_label_pc_this_method >= 0)
	{
	  /* We adjust to the next multiple of 1000.  This is just a frill
	     so the last 3 digits of the label number match the bytecode
	     offset, which might make debugging marginally more convenient. */
	  start_label_pc_this_method
	    = ((((start_label_pc_this_method + highest_label_pc_this_method)
		 / 1000)
		+ 1)
	       * 1000);
	  highest_label_pc_this_method = -1;
	}

1656
      /* Convert bytecode to trees.  */
Anthony Green committed
1657 1658 1659 1660 1661
      expand_byte_code (jcf, method);

      end_java_method ();
    }

1662
  finish_class ();
Anthony Green committed
1663

1664
  (*debug_hooks->end_source_file) (LOCATION_LINE (save_location));
1665
  input_location = save_location;
Anthony Green committed
1666 1667
}

1668 1669
static VEC(tree,gc) *predefined_filenames;

1670
void
1671
add_predefined_file (tree name)
1672
{
1673
  VEC_safe_push (tree, gc, predefined_filenames, name);
1674 1675 1676
}

int
1677
predefined_filename_p (tree node)
1678
{
1679 1680 1681
  unsigned ix;
  tree f;

1682
  FOR_EACH_VEC_ELT (tree, predefined_filenames, ix, f)
1683 1684
    if (f == node)
      return 1;
1685

1686 1687 1688
  return 0;
}

1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700
/* Generate a function that does all static initialization for this 
   translation unit.  */

static void
java_emit_static_constructor (void)
{
  tree body = NULL;

  emit_register_classes (&body);
  write_resource_constructor (&body);

  if (body)
1701 1702 1703 1704
    {
      tree name = get_identifier ("_Jv_global_static_constructor");

      tree decl 
1705
	= build_decl (input_location, FUNCTION_DECL, name,
1706
		      build_function_type_list (void_type_node, NULL_TREE));
1707

1708 1709
      tree resdecl = build_decl (input_location,
				 RESULT_DECL, NULL_TREE, void_type_node);
1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728
      DECL_ARTIFICIAL (resdecl) = 1;
      DECL_RESULT (decl) = resdecl;
      current_function_decl = decl;
      allocate_struct_function (decl, false);

      TREE_STATIC (decl) = 1;
      TREE_USED (decl) = 1;
      DECL_ARTIFICIAL (decl) = 1;
      DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
      DECL_SAVED_TREE (decl) = body;
      DECL_UNINLINABLE (decl) = 1;

      DECL_INITIAL (decl) = make_node (BLOCK);
      TREE_USED (DECL_INITIAL (decl)) = 1;

      DECL_STATIC_CONSTRUCTOR (decl) = 1;
      java_genericize (decl);
      cgraph_finalize_function (decl, false);
    }
1729 1730
}

1731

1732
void
1733
java_parse_file (void)
Anthony Green committed
1734
{
1735
  int filename_count = 0;
1736
  location_t save_location = input_location;
1737
  char *file_list = NULL, *list, *next;
1738
  tree node;
1739
  FILE *finput = NULL;
1740
  int in_quotes = 0;
1741
  unsigned ix;
1742
 
1743 1744 1745
  bitmap_obstack_initialize (&bit_obstack);
  field_offsets = BITMAP_ALLOC (&bit_obstack);

1746 1747 1748
  if (flag_filelist_file)
    {
      int avail = 2000;
1749
      finput = fopen (main_input_filename, "r");
1750
      if (finput == NULL)
1751
	fatal_error ("can%'t open %s: %m", input_filename);
1752
      list = XNEWVEC (char, avail);
1753 1754 1755 1756 1757 1758 1759 1760
      next = list;
      for (;;)
	{
	  int count;
	  if (avail < 500)
	    {
	      count = next - list;
	      avail = 2 * (count + avail);
1761
	      list = XRESIZEVEC (char, list, avail);
1762 1763 1764
	      next = list + count;
	      avail = avail - count;
	    }
Mike Stump committed
1765
	  /* Subtract one to guarantee space for final '\0'. */
1766 1767 1768 1769
	  count = fread (next, 1, avail - 1, finput);
	  if (count == 0)
	    {
	      if (! feof (finput))
1770
		fatal_error ("error closing %s: %m", input_filename);
1771 1772 1773 1774 1775 1776 1777
	      *next = '\0';
	      break;
	    }
	  avail -= count;
	  next += count;
	}
      fclose (finput);
1778
      finput = NULL;
1779
      file_list = list;
1780 1781
    }
  else
1782
    list = CONST_CAST (char *, main_input_filename);
1783

1784
  while (list)
Anthony Green committed
1785
    {
1786
      for (next = list; ; )
1787
	{
1788
	  char ch = *next;
1789 1790 1791
	  if (flag_filelist_file && ! in_quotes
	      && (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' '
		  || ch == '&') /* FIXME */)
1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804
	    {
	      if (next == list)
		{
		  next++;
		  list = next;
		  continue;
		}
	      else
		{
		  *next++ = '\0';
		  break;
		}
	    }
1805 1806 1807 1808 1809 1810 1811 1812 1813
	  if (flag_filelist_file && ch == '"')
	    {
	      in_quotes = ! in_quotes;
	      *next++ = '\0';
	      if (in_quotes) 
		list = next;
	      else 
		break;
	    }
1814 1815 1816 1817 1818 1819
	  if (ch == '\0')
	    {
	      next = NULL;
	      break;
	    }
	  next++;
1820 1821
	}

1822 1823 1824 1825 1826 1827
      /* Exclude .java files.  */
      if (strlen (list) > 5 && ! strcmp (list + strlen (list) - 5, ".java"))
	{
	  /* Nothing. */
	}
      else if (list[0]) 
1828
	{
1829
	  node = get_identifier (list);
1830

1831 1832
	  filename_count++;

1833
	  /* Exclude file that we see twice on the command line. */
1834
	     
1835
	  if (IS_A_COMMAND_LINE_FILENAME_P (node))
1836
	    duplicate_class_warning (IDENTIFIER_POINTER (node));
1837 1838
	  else
	    {
1839
	      build_translation_unit_decl (node);
1840 1841
	      IS_A_COMMAND_LINE_FILENAME_P (node) = 1;
	    }
1842 1843 1844 1845
	}
      list = next;
    }

1846
  free (file_list);
1847

1848
  if (filename_count == 0)
1849
    warning (0, "no input file specified");
1850

1851 1852
  if (resource_name)
    {
1853
      const char *resource_filename;
1854 1855
      
      /* Only one resource file may be compiled at a time.  */
1856
      gcc_assert (VEC_length (tree, all_translation_units) == 1);
1857

1858 1859 1860
      resource_filename
	= IDENTIFIER_POINTER
	    (DECL_NAME (VEC_index (tree, all_translation_units, 0)));
1861
      compile_resource_file (resource_name, resource_filename);
Anthony Green committed
1862

1863
      goto finish;
1864 1865
    }

1866
  current_jcf = main_jcf;
1867
  FOR_EACH_VEC_ELT (tree, all_translation_units, ix, node)
1868
    {
1869
      unsigned char magic_string[4];
1870
      char *real_path;
1871
      uint32 magic = 0;
1872
      tree name = DECL_NAME (node);
1873
      tree real_file;
1874
      const char *filename = IDENTIFIER_POINTER (name);
1875

1876
      /* Skip already parsed files */
1877 1878 1879
      real_path = lrealpath (filename);
      real_file = get_identifier (real_path);
      free (real_path);
1880
      if (HAS_BEEN_ALREADY_PARSED_P (real_file))
1881
	continue;
1882

1883
      /* Close previous descriptor, if any */
1884
      if (finput && fclose (finput))
1885
	fatal_error ("can%'t close input file %s: %m", main_input_filename);
1886
      
1887
      finput = fopen (filename, "rb");
1888
      if (finput == NULL)
1889
	fatal_error ("can%'t open %s: %m", filename);
1890

1891
#ifdef IO_BUFFER_SIZE
1892
      setvbuf (finput, xmalloc (IO_BUFFER_SIZE),
1893 1894
	       _IOFBF, IO_BUFFER_SIZE);
#endif
1895

1896
      /* Figure what kind of file we're dealing with */
1897 1898 1899 1900 1901
      if (fread (magic_string, 1, 4, finput) == 4)
	{
	  fseek (finput, 0L, SEEK_SET);
	  magic = GET_u4 (magic_string);
	}
1902
      if (magic == 0xcafebabe)
1903
	{
1904
	  CLASS_FILE_P (node) = 1;
1905
	  current_jcf = ggc_alloc_cleared_JCF ();
1906 1907
	  current_jcf->read_state = finput;
	  current_jcf->filbuf = jcf_filbuf_from_stdio;
1908
	  jcf_parse (current_jcf);
1909
	  DECL_SOURCE_LOCATION (node) = file_start_location;
1910
	  TYPE_JCF (current_class) = current_jcf;
1911 1912 1913 1914 1915 1916
	  if (CLASS_FROM_CURRENTLY_COMPILED_P (current_class))
	    {
	      /* We've already compiled this class.  */
	      duplicate_class_warning (filename);
	      continue;
	    }
1917
	  CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
1918
	  TREE_TYPE (node) = current_class;
1919 1920 1921
	}
      else if (magic == (JCF_u4)ZIPMAGIC)
	{
1922
	  main_jcf = ggc_alloc_cleared_JCF ();
1923 1924
	  main_jcf->read_state = finput;
	  main_jcf->filbuf = jcf_filbuf_from_stdio;
1925 1926
	  linemap_add (line_table, LC_ENTER, false, filename, 0);
	  input_location = linemap_line_start (line_table, 0, 1);
1927 1928
	  if (open_in_zip (main_jcf, filename, NULL, 0) <  0)
	    fatal_error ("bad zip/jar file %s", filename);
1929
	  localToFile = SeenZipFiles;
1930
	  /* Register all the classes defined there.  */
1931
	  process_zip_dir ((FILE *) main_jcf->read_state);
1932
	  linemap_add (line_table, LC_LEAVE, false, NULL, 0);
1933 1934
	  parse_zip_file_entries ();
	}
1935 1936 1937 1938
      else if (magic == (JCF_u4) ZIPEMPTYMAGIC)
	{
	  /* Ignore an empty input jar.  */
	}
1939 1940
      else
	{
1941 1942
	  gcc_unreachable ();
#if 0
1943 1944
	  java_push_parser_context ();
	  java_parser_context_save_global ();
1945

1946
	  parse_source_file_1 (real_file, filename, finput);
1947 1948
	  java_parser_context_restore_global ();
	  java_pop_parser_context (1);
1949
	  linemap_add (line_table, LC_LEAVE, false, NULL, 0);
1950
#endif
1951
	}
Anthony Green committed
1952
    }
1953

1954
  FOR_EACH_VEC_ELT (tree, all_translation_units, ix, node)
1955
    {
1956
      input_location = DECL_SOURCE_LOCATION (node);
1957 1958
      if (CLASS_FILE_P (node))
	{
1959 1960 1961 1962
	  /* FIXME: These two flags really should be independent.  We
	     should be able to compile fully binary compatible, but
	     with flag_verify_invocations on.  */
	  flag_verify_invocations = ! flag_indirect_dispatch;
1963
	  output_class = current_class = TREE_TYPE (node);
1964

1965
	  current_jcf = TYPE_JCF (current_class);
1966
	  layout_class (current_class);
1967 1968
	  load_inner_classes (current_class);
	  parse_class_file ();
1969
	  JCF_FINISH (current_jcf);
1970 1971
	}
    }
1972
  input_location = save_location;
1973

1974 1975
  bitmap_obstack_release (&bit_obstack);

1976 1977 1978
 finish:
  /* Arrange for any necessary initialization to happen.  */
  java_emit_static_constructor ();
1979
  gcc_assert (global_bindings_p ());
1980 1981
}

1982

1983 1984 1985 1986 1987 1988 1989
/* Return the name of the class corresponding to the name of the file
   in this zip entry.  The result is newly allocated using ALLOC.  */
static char *
compute_class_name (struct ZipDirectory *zdir)
{
  char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
  char *class_name;
Andrew Haley committed
1990
  int i;
1991
  int filename_length = zdir->filename_length;
Andrew Haley committed
1992

1993 1994 1995 1996 1997
  while (filename_length > 2 && strncmp (class_name_in_zip_dir, "./", 2) == 0)
    {
      class_name_in_zip_dir += 2;
      filename_length -= 2;
    }
Andrew Haley committed
1998

1999
  filename_length -= strlen (".class");
2000
  class_name = XNEWVEC (char, filename_length + 1);
Andrew Haley committed
2001 2002 2003 2004 2005 2006
  memcpy (class_name, class_name_in_zip_dir, filename_length);
  class_name [filename_length] = '\0';

  for (i = 0; i < filename_length; i++)
    if (class_name[i] == '/')
      class_name[i] = '.';
2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022

  return class_name;
}

/* Return 0 if we should skip this entry, 1 if it is a .class file, 2
   if it is a property file of some sort.  */
static int
classify_zip_file (struct ZipDirectory *zdir)
{
  char *class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);

  if (zdir->filename_length > 6
      && !strncmp (&class_name_in_zip_dir[zdir->filename_length - 6],
		   ".class", 6))
    return 1;

2023
  /* For now we drop the manifest, but not other information.  */
2024
  if (zdir->filename_length == 20
2025
      && !strncmp (class_name_in_zip_dir, "META-INF/MANIFEST.MF", 20))
2026 2027 2028 2029 2030 2031 2032 2033
    return 0;

  /* Drop directory entries.  */
  if (zdir->filename_length > 0
      && class_name_in_zip_dir[zdir->filename_length - 1] == '/')
    return 0;

  return 2;
Anthony Green committed
2034 2035 2036
}

/* Process all class entries found in the zip file.  */
2037
static void
Anthony Green committed
2038 2039 2040 2041 2042
parse_zip_file_entries (void)
{
  struct ZipDirectory *zdir;
  int i;

2043 2044
  for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
       i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
Anthony Green committed
2045
    {
2046
      tree klass;
Anthony Green committed
2047

2048
      switch (classify_zip_file (zdir))
Anthony Green committed
2049
	{
2050 2051
	case 0:
	  continue;
Anthony Green committed
2052

2053 2054 2055
	case 1:
	  {
	    char *class_name = compute_class_name (zdir);
2056
	    int previous_alias_set = -1;
2057
	    klass = lookup_class (get_identifier (class_name));
2058
	    FREE (class_name);
2059 2060
	    current_jcf = TYPE_JCF (klass);
	    output_class = current_class = klass;
2061

2062 2063
	    /* This is a dummy class, and now we're compiling it for
	       real.  */
2064
	    gcc_assert (! TYPE_DUMMY (klass));
2065

Andrew Haley committed
2066
	    /* This is for a corner case where we have a superclass
2067
	       but no superclass fields.
Andrew Haley committed
2068 2069 2070 2071

	       This can happen if we earlier failed to lay out this
	       class because its superclass was still in the process
	       of being laid out; this occurs when we have recursive
2072 2073 2074 2075 2076 2077 2078
	       class dependencies via inner classes.  We must record
	       the previous alias set and restore it after laying out
	       the class.

	       FIXME: this really is a kludge.  We should figure out a
	       way to lay out the class properly before this
	       happens.  */
2079 2080
	    if (TYPE_SIZE (klass) && CLASSTYPE_SUPER (klass)
		&& integer_zerop (TYPE_SIZE (klass)))
2081
	      {
2082 2083 2084
		TYPE_SIZE (klass) = NULL_TREE;
		previous_alias_set = TYPE_ALIAS_SET (klass);
		TYPE_ALIAS_SET (klass) = -1;
2085
	      }
Andrew Haley committed
2086

2087
	    if (! CLASS_LOADED_P (klass))
2088
	      {
2089
		if (! CLASS_PARSED_P (klass))
2090 2091 2092 2093 2094 2095 2096 2097
		  {
		    read_zip_member (current_jcf, zdir, localToFile);
		    jcf_parse (current_jcf);
		  }
		layout_class (current_class);
		load_inner_classes (current_class);
	      }

2098
	    if (previous_alias_set != -1)
2099
	      TYPE_ALIAS_SET (klass) = previous_alias_set;
2100

2101 2102 2103
	    if (TYPE_SIZE (current_class) != error_mark_node)
	      {
		parse_class_file ();
2104
		free (current_jcf->buffer); /* No longer necessary */
2105 2106 2107 2108 2109 2110 2111 2112 2113 2114 2115 2116
		/* Note: there is a way to free this buffer right after a
		   class seen in a zip file has been parsed. The idea is the
		   set its jcf in such a way that buffer will be reallocated
		   the time the code for the class will be generated. FIXME. */
	      }
	  }
	  break;

	case 2:
	  {
	    char *file_name, *class_name_in_zip_dir, *buffer;
	    JCF *jcf;
2117
	    file_name = XNEWVEC (char, zdir->filename_length + 1);
2118 2119 2120
	    class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
	    strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
	    file_name[zdir->filename_length] = '\0';
2121
	    jcf = XNEW (JCF);
2122 2123 2124 2125 2126 2127 2128 2129 2130 2131
	    JCF_ZERO (jcf);
	    jcf->read_state  = finput;
	    jcf->filbuf      = jcf_filbuf_from_stdio;
	    jcf->classname   = NULL;
	    jcf->filename    = file_name;
	    jcf->zipd        = zdir;

	    if (read_zip_member (jcf, zdir, localToFile) < 0)
	      fatal_error ("error while reading %s from zip file", file_name);

2132
	    buffer = XNEWVEC (char, zdir->filename_length + 1 +
2133 2134
			    (jcf->buffer_end - jcf->buffer));
	    strcpy (buffer, file_name);
2135 2136 2137
	    /* This is not a typo: we overwrite the trailing \0 of the
	       file name; this is just how the data is laid out.  */
	    memcpy (buffer + zdir->filename_length,
2138 2139 2140 2141 2142
		    jcf->buffer, jcf->buffer_end - jcf->buffer);

	    compile_resource_data (file_name, buffer,
				   jcf->buffer_end - jcf->buffer);
	    JCF_FINISH (jcf);
2143 2144
	    free (jcf);
	    free (buffer);
2145 2146 2147 2148
	  }
	  break;

	default:
2149
	  gcc_unreachable ();
2150
	}
Anthony Green committed
2151 2152 2153 2154 2155 2156
    }
}

/* Read all the entries of the zip file, creates a class and a JCF. Sets the
   jcf up for further processing and link it to the created class.  */

2157 2158
static void
process_zip_dir (FILE *finput)
Anthony Green committed
2159 2160 2161 2162
{
  int i;
  ZipDirectory *zdir;

2163 2164
  for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
       i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
Anthony Green committed
2165 2166
    {
      char *class_name, *file_name, *class_name_in_zip_dir;
2167
      tree klass;
Anthony Green committed
2168 2169 2170 2171
      JCF  *jcf;

      class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);

2172 2173 2174
      /* Here we skip non-class files; we handle them later.  */
      if (classify_zip_file (zdir) != 1)
	continue;
Anthony Green committed
2175

2176
      class_name = compute_class_name (zdir);
2177
      file_name  = XNEWVEC (char, zdir->filename_length+1);
2178
      jcf = ggc_alloc_cleared_JCF ();
Anthony Green committed
2179 2180 2181 2182

      strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
      file_name [zdir->filename_length] = '\0';

2183
      klass = lookup_class (get_identifier (class_name));
Anthony Green committed
2184

2185
      if (CLASS_FROM_CURRENTLY_COMPILED_P (klass))
2186 2187 2188 2189 2190 2191 2192
	{
	  /* We've already compiled this class.  */
	  duplicate_class_warning (file_name);
	  continue;
	}
      /* This function is only called when processing a zip file seen
	 on the command line.  */
2193
      CLASS_FROM_CURRENTLY_COMPILED_P (klass) = 1;
2194

Anthony Green committed
2195 2196 2197 2198
      jcf->read_state  = finput;
      jcf->filbuf      = jcf_filbuf_from_stdio;
      jcf->classname   = class_name;
      jcf->filename    = file_name;
2199
      jcf->zipd        = zdir;
Anthony Green committed
2200

2201
      TYPE_JCF (klass) = jcf;
Anthony Green committed
2202 2203 2204
    }
}

2205
#include "gt-java-jcf-parse.h"
2206
#include "gtype-java.h"