00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #include "config.h"
00029 #include "system.h"
00030 #include "tree.h"
00031 #include "obstack.h"
00032 #include "flags.h"
00033 #include "java-except.h"
00034 #include "input.h"
00035 #include "java-tree.h"
00036 #include "toplev.h"
00037 #include "parse.h"
00038 #include "ggc.h"
00039 #include "debug.h"
00040 #include "assert.h"
00041
00042 #ifdef HAVE_LOCALE_H
00043 #include <locale.h>
00044 #endif
00045
00046 #ifdef HAVE_NL_LANGINFO
00047 #include <langinfo.h>
00048 #endif
00049
00050
00051 #define JPOOL_UTF(JCF, INDEX) CPOOL_UTF(&(JCF)->cpool, INDEX)
00052 #define JPOOL_UTF_LENGTH(JCF, INDEX) IDENTIFIER_LENGTH (JPOOL_UTF (JCF, INDEX))
00053 #define JPOOL_UTF_DATA(JCF, INDEX) \
00054 ((const unsigned char *) IDENTIFIER_POINTER (JPOOL_UTF (JCF, INDEX)))
00055 #define HANDLE_CONSTANT_Utf8(JCF, INDEX, LENGTH) \
00056 do { \
00057 unsigned char save; unsigned char *text; \
00058 JCF_FILL (JCF, (LENGTH)+1); \
00059 text = (JCF)->read_ptr; \
00060 save = text[LENGTH]; \
00061 text[LENGTH] = 0; \
00062 (JCF)->cpool.data[INDEX] = (jword) get_identifier (text); \
00063 text[LENGTH] = save; \
00064 JCF_SKIP (JCF, LENGTH); } while (0)
00065
00066 #include "jcf.h"
00067
00068 extern struct obstack *saveable_obstack;
00069 extern struct obstack temporary_obstack;
00070 extern struct obstack permanent_obstack;
00071
00072
00073
00074 extern int always_initialize_class_p;
00075
00076 static tree parse_roots[3] = { NULL_TREE, NULL_TREE, NULL_TREE };
00077
00078
00079 #define current_field parse_roots[0]
00080
00081
00082 #define current_method parse_roots[1]
00083
00084
00085 #define current_file_list parse_roots[2]
00086
00087
00088 static struct JCF main_jcf[1];
00089
00090 static struct ZipFile *localToFile;
00091
00092
00093 static void handle_innerclass_attribute PARAMS ((int count, JCF *));
00094 static tree give_name_to_class PARAMS ((JCF *jcf, int index));
00095 static void parse_zip_file_entries PARAMS ((void));
00096 static void process_zip_dir PARAMS ((FILE *));
00097 static void parse_source_file_1 PARAMS ((tree, FILE *));
00098 static void parse_source_file_2 PARAMS ((void));
00099 static void parse_source_file_3 PARAMS ((void));
00100 static void parse_class_file PARAMS ((void));
00101 static void set_source_filename PARAMS ((JCF *, int));
00102 static void ggc_mark_jcf PARAMS ((void**));
00103 static void jcf_parse PARAMS ((struct JCF*));
00104 static void load_inner_classes PARAMS ((tree));
00105
00106
00107
00108
00109
00110 static void
00111 ggc_mark_jcf (elt)
00112 void **elt;
00113 {
00114 JCF *jcf = *(JCF**) elt;
00115 if (jcf != NULL && !jcf->finished)
00116 {
00117 CPool *cpool = &jcf->cpool;
00118 int size = CPOOL_COUNT(cpool);
00119 int index;
00120 for (index = 1; index < size; index++)
00121 {
00122 int tag = JPOOL_TAG (jcf, index);
00123 if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
00124 ggc_mark_tree ((tree) cpool->data[index]);
00125 }
00126 }
00127 }
00128
00129
00130
00131 static void
00132 set_source_filename (jcf, index)
00133 JCF *jcf;
00134 int index;
00135 {
00136 tree sfname_id = get_name_constant (jcf, index);
00137 const char *sfname = IDENTIFIER_POINTER (sfname_id);
00138 if (input_filename != NULL)
00139 {
00140 int old_len = strlen (input_filename);
00141 int new_len = IDENTIFIER_LENGTH (sfname_id);
00142
00143
00144 if (old_len > new_len
00145 && strcmp (sfname, input_filename + old_len - new_len) == 0
00146 && (input_filename[old_len - new_len - 1] == '/'
00147 || input_filename[old_len - new_len - 1] == '\\'))
00148 return;
00149 }
00150 input_filename = sfname;
00151 DECL_SOURCE_FILE (TYPE_NAME (current_class)) = sfname;
00152 if (current_class == main_class) main_input_filename = input_filename;
00153 }
00154
00155 #define HANDLE_SOURCEFILE(INDEX) set_source_filename (jcf, INDEX)
00156
00157 #define HANDLE_CLASS_INFO(ACCESS_FLAGS, THIS, SUPER, INTERFACES_COUNT) \
00158 { tree super_class = SUPER==0 ? NULL_TREE : get_class_constant (jcf, SUPER); \
00159 current_class = give_name_to_class (jcf, THIS); \
00160 set_super_info (ACCESS_FLAGS, current_class, super_class, INTERFACES_COUNT);}
00161
00162 #define HANDLE_CLASS_INTERFACE(INDEX) \
00163 add_interface (current_class, get_class_constant (jcf, INDEX))
00164
00165 #define HANDLE_START_FIELD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
00166 { int sig_index = SIGNATURE; \
00167 current_field = add_field (current_class, get_name_constant (jcf, NAME), \
00168 parse_signature (jcf, sig_index), ACCESS_FLAGS); \
00169 set_java_signature (TREE_TYPE (current_field), JPOOL_UTF (jcf, sig_index)); \
00170 if ((ACCESS_FLAGS) & ACC_FINAL) \
00171 MAYBE_CREATE_VAR_LANG_DECL_SPECIFIC (current_field); \
00172 }
00173
00174 #define HANDLE_END_FIELDS() \
00175 (current_field = NULL_TREE)
00176
00177 #define HANDLE_CONSTANTVALUE(INDEX) \
00178 { tree constant; int index = INDEX; \
00179 if (! flag_emit_class_files && JPOOL_TAG (jcf, index) == CONSTANT_String) { \
00180 tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index)); \
00181 constant = build_utf8_ref (name); \
00182 } \
00183 else \
00184 constant = get_constant (jcf, index); \
00185 set_constant_value (current_field, constant); }
00186
00187 #define HANDLE_METHOD(ACCESS_FLAGS, NAME, SIGNATURE, ATTRIBUTE_COUNT) \
00188 (current_method = add_method (current_class, ACCESS_FLAGS, \
00189 get_name_constant (jcf, NAME), \
00190 get_name_constant (jcf, SIGNATURE)), \
00191 DECL_LOCALVARIABLES_OFFSET (current_method) = 0, \
00192 DECL_LINENUMBERS_OFFSET (current_method) = 0)
00193
00194 #define HANDLE_END_METHODS() \
00195 { tree handle_type = CLASS_TO_HANDLE_TYPE (current_class); \
00196 if (handle_type != current_class) layout_type (handle_type); \
00197 current_method = NULL_TREE; }
00198
00199 #define HANDLE_CODE_ATTRIBUTE(MAX_STACK, MAX_LOCALS, CODE_LENGTH) \
00200 { DECL_MAX_STACK (current_method) = (MAX_STACK); \
00201 DECL_MAX_LOCALS (current_method) = (MAX_LOCALS); \
00202 DECL_CODE_LENGTH (current_method) = (CODE_LENGTH); \
00203 DECL_CODE_OFFSET (current_method) = JCF_TELL (jcf); }
00204
00205 #define HANDLE_LOCALVARIABLETABLE_ATTRIBUTE(COUNT) \
00206 { int n = (COUNT); \
00207 DECL_LOCALVARIABLES_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
00208 JCF_SKIP (jcf, n * 10); }
00209
00210 #define HANDLE_LINENUMBERTABLE_ATTRIBUTE(COUNT) \
00211 { int n = (COUNT); \
00212 DECL_LINENUMBERS_OFFSET (current_method) = JCF_TELL (jcf) - 2; \
00213 JCF_SKIP (jcf, n * 4); }
00214
00215 #define HANDLE_EXCEPTIONS_ATTRIBUTE(COUNT) \
00216 { \
00217 int n = COUNT; \
00218 tree list = DECL_FUNCTION_THROWS (current_method); \
00219 while (--n >= 0) \
00220 { \
00221 tree thrown_class = get_class_constant (jcf, JCF_readu2 (jcf)); \
00222 list = tree_cons (NULL_TREE, thrown_class, list); \
00223 } \
00224 DECL_FUNCTION_THROWS (current_method) = nreverse (list); \
00225 }
00226
00227
00228
00229 #define HANDLE_INNERCLASSES_ATTRIBUTE(COUNT) \
00230 handle_innerclass_attribute (COUNT, jcf)
00231
00232 #define HANDLE_SYNTHETIC_ATTRIBUTE() \
00233 { \
00234
00235
00236
00237 \
00238 if (current_method) \
00239 DECL_ARTIFICIAL (current_method) = 1; \
00240 }
00241
00242 #define HANDLE_GCJCOMPILED_ATTRIBUTE() \
00243 { \
00244 if (current_class == object_type_node) \
00245 jcf->right_zip = 1; \
00246 }
00247
00248 #include "jcf-reader.c"
00249
00250 static int yydebug;
00251
00252 tree
00253 parse_signature (jcf, sig_index)
00254 JCF *jcf;
00255 int sig_index;
00256 {
00257 if (sig_index <= 0 || sig_index >= JPOOL_SIZE (jcf)
00258 || JPOOL_TAG (jcf, sig_index) != CONSTANT_Utf8)
00259 abort ();
00260 else
00261 return parse_signature_string (JPOOL_UTF_DATA (jcf, sig_index),
00262 JPOOL_UTF_LENGTH (jcf, sig_index));
00263 }
00264
00265 void
00266 java_set_yydebug (value)
00267 int value;
00268 {
00269 yydebug = value;
00270 }
00271
00272 tree
00273 get_constant (jcf, index)
00274 JCF *jcf;
00275 int index;
00276 {
00277 tree value;
00278 int tag;
00279 if (index <= 0 || index >= JPOOL_SIZE(jcf))
00280 goto bad;
00281 tag = JPOOL_TAG (jcf, index);
00282 if ((tag & CONSTANT_ResolvedFlag) || tag == CONSTANT_Utf8)
00283 return (tree) jcf->cpool.data[index];
00284 switch (tag)
00285 {
00286 case CONSTANT_Integer:
00287 {
00288 jint num = JPOOL_INT(jcf, index);
00289 value = build_int_2 (num, num < 0 ? -1 : 0);
00290 TREE_TYPE (value) = int_type_node;
00291 break;
00292 }
00293 case CONSTANT_Long:
00294 {
00295 unsigned HOST_WIDE_INT num = JPOOL_UINT (jcf, index);
00296 HOST_WIDE_INT lo, hi;
00297 lshift_double (num, 0, 32, 64, &lo, &hi, 0);
00298 num = JPOOL_UINT (jcf, index+1);
00299 add_double (lo, hi, num, 0, &lo, &hi);
00300 value = build_int_2 (lo, hi);
00301 TREE_TYPE (value) = long_type_node;
00302 force_fit_type (value, 0);
00303 break;
00304 }
00305 #if TARGET_FLOAT_FORMAT == IEEE_FLOAT_FORMAT
00306 case CONSTANT_Float:
00307 {
00308 jint num = JPOOL_INT(jcf, index);
00309 REAL_VALUE_TYPE d;
00310 #ifdef REAL_ARITHMETIC
00311 d = REAL_VALUE_FROM_TARGET_SINGLE (num);
00312 #else
00313 union { float f; jint i; } u;
00314 u.i = num;
00315 d = u.f;
00316 #endif
00317 value = build_real (float_type_node, d);
00318 break;
00319 }
00320 case CONSTANT_Double:
00321 {
00322 HOST_WIDE_INT num[2];
00323 REAL_VALUE_TYPE d;
00324 HOST_WIDE_INT lo, hi;
00325 num[0] = JPOOL_UINT (jcf, index);
00326 lshift_double (num[0], 0, 32, 64, &lo, &hi, 0);
00327 num[0] = JPOOL_UINT (jcf, index+1);
00328 add_double (lo, hi, num[0], 0, &lo, &hi);
00329
00330
00331
00332
00333
00334
00335
00336
00337 if (FLOAT_WORDS_BIG_ENDIAN && sizeof(num[0]) < 8)
00338 {
00339 num[0] = hi;
00340 num[1] = lo;
00341 }
00342 else
00343 {
00344 num[0] = lo;
00345 num[1] = hi;
00346 }
00347 #ifdef REAL_ARITHMETIC
00348 d = REAL_VALUE_FROM_TARGET_DOUBLE (num);
00349 #else
00350 {
00351 union { double d; jint i[2]; } u;
00352 u.i[0] = (jint) num[0];
00353 u.i[1] = (jint) num[1];
00354 d = u.d;
00355 }
00356 #endif
00357 value = build_real (double_type_node, d);
00358 break;
00359 }
00360 #endif
00361 case CONSTANT_String:
00362 {
00363 tree name = get_name_constant (jcf, JPOOL_USHORT1 (jcf, index));
00364 const char *utf8_ptr = IDENTIFIER_POINTER (name);
00365 int utf8_len = IDENTIFIER_LENGTH (name);
00366 const unsigned char *utf8;
00367 int i;
00368
00369
00370 utf8 = (const unsigned char *) utf8_ptr;
00371 i = utf8_len;
00372 while (i > 0)
00373 {
00374 int char_len = UT8_CHAR_LENGTH (*utf8);
00375 if (char_len < 0 || char_len > 3 || char_len > i)
00376 fatal_error ("bad string constant");
00377
00378 utf8 += char_len;
00379 i -= char_len;
00380 }
00381
00382
00383 value = build_string (utf8_len, utf8_ptr);
00384 TREE_TYPE (value) = build_pointer_type (string_type_node);
00385 }
00386 break;
00387 default:
00388 goto bad;
00389 }
00390 JPOOL_TAG (jcf, index) = tag | CONSTANT_ResolvedFlag;
00391 jcf->cpool.data [index] = (jword) value;
00392 return value;
00393 bad:
00394 internal_error ("bad value constant type %d, index %d",
00395 JPOOL_TAG (jcf, index), index);
00396 }
00397
00398 tree
00399 get_name_constant (jcf, index)
00400 JCF *jcf;
00401 int index;
00402 {
00403 tree name = get_constant (jcf, index);
00404
00405 if (TREE_CODE (name) != IDENTIFIER_NODE)
00406 abort ();
00407
00408 return name;
00409 }
00410
00411
00412
00413
00414
00415 static void
00416 handle_innerclass_attribute (count, jcf)
00417 int count;
00418 JCF *jcf;
00419 {
00420 int c = (count);
00421 while (c--)
00422 {
00423
00424 int icii = JCF_readu2 (jcf);
00425
00426
00427 int ocii = JCF_readu2 (jcf);
00428
00429
00430 int ini = JCF_readu2 (jcf);
00431
00432 int acc = JCF_readu2 (jcf);
00433
00434 if (icii >= 0)
00435 {
00436 tree class = get_class_constant (jcf, icii);
00437 tree decl = TYPE_NAME (class);
00438
00439 if (DECL_P (decl) && !CLASS_COMPLETE_P (decl) && ocii)
00440 {
00441 tree outer = TYPE_NAME (get_class_constant (jcf, ocii));
00442 tree alias = (ini ? get_name_constant (jcf, ini) : NULL_TREE);
00443 set_class_decl_access_flags (acc, decl);
00444 DECL_CONTEXT (decl) = outer;
00445 DECL_INNER_CLASS_LIST (outer) =
00446 tree_cons (decl, alias, DECL_INNER_CLASS_LIST (outer));
00447 CLASS_COMPLETE_P (decl) = 1;
00448 }
00449 }
00450 }
00451 }
00452
00453 static tree
00454 give_name_to_class (jcf, i)
00455 JCF *jcf;
00456 int i;
00457 {
00458 if (i <= 0 || i >= JPOOL_SIZE (jcf)
00459 || JPOOL_TAG (jcf, i) != CONSTANT_Class)
00460 abort ();
00461 else
00462 {
00463 tree this_class;
00464 int j = JPOOL_USHORT1 (jcf, i);
00465
00466 tree class_name = unmangle_classname (JPOOL_UTF_DATA (jcf, j),
00467 JPOOL_UTF_LENGTH (jcf, j));
00468 this_class = lookup_class (class_name);
00469 input_filename = DECL_SOURCE_FILE (TYPE_NAME (this_class));
00470 lineno = 0;
00471 if (main_input_filename == NULL && jcf == main_jcf)
00472 main_input_filename = input_filename;
00473
00474 jcf->cpool.data[i] = (jword) this_class;
00475 JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
00476 return this_class;
00477 }
00478 }
00479
00480
00481
00482 tree
00483 get_class_constant (JCF *jcf , int i)
00484 {
00485 tree type;
00486 if (i <= 0 || i >= JPOOL_SIZE (jcf)
00487 || (JPOOL_TAG (jcf, i) & ~CONSTANT_ResolvedFlag) != CONSTANT_Class)
00488 abort ();
00489
00490 if (JPOOL_TAG (jcf, i) != CONSTANT_ResolvedClass)
00491 {
00492 int name_index = JPOOL_USHORT1 (jcf, i);
00493
00494 const char *name = JPOOL_UTF_DATA (jcf, name_index);
00495 int nlength = JPOOL_UTF_LENGTH (jcf, name_index);
00496
00497 if (name[0] == '[')
00498 type = TREE_TYPE (parse_signature_string (name, nlength));
00499 else
00500 {
00501 tree cname = unmangle_classname (name, nlength);
00502 type = lookup_class (cname);
00503 }
00504 jcf->cpool.data[i] = (jword) type;
00505 JPOOL_TAG (jcf, i) = CONSTANT_ResolvedClass;
00506 }
00507 else
00508 type = (tree) jcf->cpool.data[i];
00509 return type;
00510 }
00511
00512
00513
00514
00515
00516
00517 int
00518 read_class (name)
00519 tree name;
00520 {
00521 JCF this_jcf, *jcf;
00522 tree icv, class = NULL_TREE;
00523 tree save_current_class = current_class;
00524 const char *save_input_filename = input_filename;
00525 JCF *save_current_jcf = current_jcf;
00526
00527 if ((icv = IDENTIFIER_CLASS_VALUE (name)) != NULL_TREE)
00528 {
00529 class = TREE_TYPE (icv);
00530 jcf = TYPE_JCF (class);
00531 }
00532 else
00533 jcf = NULL;
00534
00535 if (jcf == NULL)
00536 {
00537 this_jcf.zipd = NULL;
00538 jcf = &this_jcf;
00539 if (find_class (IDENTIFIER_POINTER (name), IDENTIFIER_LENGTH (name),
00540 &this_jcf, 1) == 0)
00541 return 0;
00542 }
00543
00544 current_jcf = jcf;
00545
00546 if (current_jcf->java_source)
00547 {
00548 const char *filename = current_jcf->filename;
00549 tree file;
00550 FILE *finput;
00551 int generate;
00552
00553 java_parser_context_save_global ();
00554 java_push_parser_context ();
00555 BUILD_FILENAME_IDENTIFIER_NODE (file, filename);
00556 generate = IS_A_COMMAND_LINE_FILENAME_P (file);
00557 if (wfl_operator == NULL_TREE)
00558 wfl_operator = build_expr_wfl (NULL_TREE, NULL, 0, 0);
00559 EXPR_WFL_FILENAME_NODE (wfl_operator) = file;
00560 input_filename = ggc_strdup (filename);
00561 current_class = NULL_TREE;
00562 current_function_decl = NULL_TREE;
00563 if (!HAS_BEEN_ALREADY_PARSED_P (file))
00564 {
00565 if (!(finput = fopen (input_filename, "r")))
00566 fatal_io_error ("can't reopen %s", input_filename);
00567 parse_source_file_1 (file, finput);
00568 parse_source_file_2 ();
00569 parse_source_file_3 ();
00570 if (fclose (finput))
00571 fatal_io_error ("can't close %s", input_filename);
00572 }
00573 JCF_FINISH (current_jcf);
00574 java_pop_parser_context (generate);
00575 java_parser_context_restore_global ();
00576 }
00577 else
00578 {
00579 if (class == NULL_TREE || ! CLASS_PARSED_P (class))
00580 {
00581 java_parser_context_save_global ();
00582 java_push_parser_context ();
00583 current_class = class;
00584 input_filename = current_jcf->filename;
00585 if (JCF_SEEN_IN_ZIP (current_jcf))
00586 read_zip_member(current_jcf,
00587 current_jcf->zipd, current_jcf->zipd->zipf);
00588 jcf_parse (current_jcf);
00589 class = current_class;
00590 java_pop_parser_context (0);
00591 java_parser_context_restore_global ();
00592 }
00593 layout_class (class);
00594 load_inner_classes (class);
00595 }
00596
00597 current_class = save_current_class;
00598 input_filename = save_input_filename;
00599 current_jcf = save_current_jcf;
00600 return 1;
00601 }
00602
00603
00604
00605
00606
00607
00608
00609
00610 void
00611 load_class (class_or_name, verbose)
00612 tree class_or_name;
00613 int verbose;
00614 {
00615 tree name, saved;
00616 int class_loaded;
00617
00618
00619 if (TREE_CODE (class_or_name) == IDENTIFIER_NODE)
00620 name = class_or_name;
00621
00622
00623 else if (TREE_CODE (class_or_name) == TREE_LIST)
00624 name = TYPE_NAME (TREE_PURPOSE (class_or_name));
00625
00626 else
00627 name = DECL_NAME (TYPE_NAME (class_or_name));
00628
00629 saved = name;
00630 while (1)
00631 {
00632 char *separator;
00633
00634 if ((class_loaded = read_class (name)))
00635 break;
00636
00637
00638
00639 if ((separator = strrchr (IDENTIFIER_POINTER (name), '$'))
00640 || (separator = strrchr (IDENTIFIER_POINTER (name), '.')))
00641 {
00642 int c = *separator;
00643 *separator = '\0';
00644 name = get_identifier (IDENTIFIER_POINTER (name));
00645 *separator = c;
00646 }
00647
00648 else
00649 break;
00650 }
00651
00652 if (!class_loaded && verbose)
00653 error ("cannot find file for class %s", IDENTIFIER_POINTER (saved));
00654 }
00655
00656
00657
00658 void
00659 jcf_parse (jcf)
00660 JCF* jcf;
00661 {
00662 int i, code;
00663
00664 if (jcf_parse_preamble (jcf) != 0)
00665 fatal_error ("not a valid Java .class file");
00666 code = jcf_parse_constant_pool (jcf);
00667 if (code != 0)
00668 fatal_error ("error while parsing constant pool");
00669 code = verify_constant_pool (jcf);
00670 if (code > 0)
00671 fatal_error ("error in constant pool entry #%d\n", code);
00672
00673 jcf_parse_class (jcf);
00674 if (main_class == NULL_TREE)
00675 main_class = current_class;
00676 if (! quiet_flag && TYPE_NAME (current_class))
00677 fprintf (stderr, " %s %s",
00678 (jcf->access_flags & ACC_INTERFACE) ? "interface" : "class",
00679 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))));
00680 if (CLASS_PARSED_P (current_class))
00681 {
00682
00683 fatal_error ("reading class %s for the second time from %s",
00684 IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (current_class))),
00685 jcf->filename);
00686 }
00687 CLASS_PARSED_P (current_class) = 1;
00688
00689 for (i = 1; i < JPOOL_SIZE(jcf); i++)
00690 {
00691 switch (JPOOL_TAG (jcf, i))
00692 {
00693 case CONSTANT_Class:
00694 get_class_constant (jcf, i);
00695 break;
00696 }
00697 }
00698
00699 code = jcf_parse_fields (jcf);
00700 if (code != 0)
00701 fatal_error ("error while parsing fields");
00702 code = jcf_parse_methods (jcf);
00703 if (code != 0)
00704 fatal_error ("error while parsing methods");
00705 code = jcf_parse_final_attributes (jcf);
00706 if (code != 0)
00707 fatal_error ("error while parsing final attributes");
00708
00709
00710 if (current_class != class_type_node && current_class != object_type_node)
00711 TYPE_FIELDS (current_class) = nreverse (TYPE_FIELDS (current_class));
00712
00713 if (current_class == object_type_node)
00714 {
00715 layout_class_methods (object_type_node);
00716
00717
00718
00719 if (!jcf->right_zip
00720 && (!flag_emit_class_files || flag_force_classes_archive_check))
00721 fatal_error ("the `java.lang.Object' that was found in `%s' didn't have the special zero-length `gnu.gcj.gcj-compiled' attribute. This generally means that your classpath is incorrectly set. Use `info gcj \"Input Options\"' to see the info page describing how to set the classpath", jcf->filename);
00722 }
00723 else
00724 all_class_list = tree_cons (NULL_TREE,
00725 TYPE_NAME (current_class), all_class_list );
00726 }
00727
00728
00729 static void
00730 load_inner_classes (cur_class)
00731 tree cur_class;
00732 {
00733 tree current;
00734 for (current = DECL_INNER_CLASS_LIST (TYPE_NAME (cur_class)); current;
00735 current = TREE_CHAIN (current))
00736 {
00737 tree name = DECL_NAME (TREE_PURPOSE (current));
00738 tree decl = IDENTIFIER_GLOBAL_VALUE (name);
00739 if (decl && ! CLASS_LOADED_P (TREE_TYPE (decl))
00740 && !CLASS_BEING_LAIDOUT (TREE_TYPE (decl)))
00741 load_class (name, 1);
00742 }
00743 }
00744
00745 void
00746 init_outgoing_cpool ()
00747 {
00748 current_constant_pool_data_ref = NULL_TREE;
00749 outgoing_cpool = (struct CPool *)xmalloc (sizeof (struct CPool));
00750 memset (outgoing_cpool, 0, sizeof (struct CPool));
00751 }
00752
00753 static void
00754 parse_class_file ()
00755 {
00756 tree method, field;
00757 const char *save_input_filename = input_filename;
00758 int save_lineno = lineno;
00759
00760 java_layout_seen_class_methods ();
00761
00762 input_filename = DECL_SOURCE_FILE (TYPE_NAME (current_class));
00763 lineno = 0;
00764 (*debug_hooks->start_source_file) (lineno, input_filename);
00765 init_outgoing_cpool ();
00766
00767
00768
00769 always_initialize_class_p = 1;
00770
00771 for (field = TYPE_FIELDS (CLASS_TO_HANDLE_TYPE (current_class));
00772 field != NULL_TREE; field = TREE_CHAIN (field))
00773 if (FIELD_STATIC (field))
00774 DECL_EXTERNAL (field) = 0;
00775
00776 for (method = TYPE_METHODS (CLASS_TO_HANDLE_TYPE (current_class));
00777 method != NULL_TREE; method = TREE_CHAIN (method))
00778 {
00779 JCF *jcf = current_jcf;
00780
00781 if (METHOD_ABSTRACT (method))
00782 continue;
00783
00784 if (METHOD_NATIVE (method))
00785 {
00786 tree arg;
00787 int decl_max_locals;
00788
00789 if (! flag_jni)
00790 continue;
00791
00792
00793 for (arg = TYPE_ARG_TYPES (TREE_TYPE (method)), decl_max_locals = 0;
00794 arg != end_params_node;
00795 arg = TREE_CHAIN (arg), decl_max_locals += 1)
00796 {
00797 if (TREE_VALUE (arg) && TYPE_IS_WIDE (TREE_VALUE (arg)))
00798 decl_max_locals += 1;
00799 }
00800 DECL_MAX_LOCALS (method) = decl_max_locals;
00801 start_java_method (method);
00802 give_name_to_locals (jcf);
00803 expand_expr_stmt (build_jni_stub (method));
00804 end_java_method ();
00805 continue;
00806 }
00807
00808 if (DECL_CODE_OFFSET (method) == 0)
00809 {
00810 current_function_decl = method;
00811 error ("missing Code attribute");
00812 continue;
00813 }
00814
00815 lineno = 0;
00816 if (DECL_LINENUMBERS_OFFSET (method))
00817 {
00818 register int i;
00819 register unsigned char *ptr;
00820 JCF_SEEK (jcf, DECL_LINENUMBERS_OFFSET (method));
00821 linenumber_count = i = JCF_readu2 (jcf);
00822 linenumber_table = ptr = jcf->read_ptr;
00823
00824 for (ptr += 2; --i >= 0; ptr += 4)
00825 {
00826 int line = GET_u2 (ptr);
00827
00828
00829 if (lineno == 0 || line < lineno)
00830 lineno = line;
00831 }
00832 }
00833 else
00834 {
00835 linenumber_table = NULL;
00836 linenumber_count = 0;
00837 }
00838
00839 start_java_method (method);
00840
00841 note_instructions (jcf, method);
00842
00843 give_name_to_locals (jcf);
00844
00845
00846 expand_byte_code (jcf, method);
00847
00848 end_java_method ();
00849 }
00850
00851 if (flag_emit_class_files)
00852 write_classfile (current_class);
00853
00854 finish_class ();
00855
00856 (*debug_hooks->end_source_file) (save_lineno);
00857 input_filename = save_input_filename;
00858 lineno = save_lineno;
00859 }
00860
00861
00862
00863 static void
00864 parse_source_file_1 (file, finput)
00865 tree file;
00866 FILE *finput;
00867 {
00868 int save_error_count = java_error_count;
00869
00870 HAS_BEEN_ALREADY_PARSED_P (file) = 1;
00871
00872 jcf_dependency_add_file (input_filename, 0);
00873
00874 lang_init_source (1);
00875
00876
00877
00878
00879 #if defined (HAVE_LOCALE_H) && defined (HAVE_ICONV) && defined (HAVE_NL_LANGINFO)
00880 setlocale (LC_CTYPE, "");
00881 if (current_encoding == NULL)
00882 current_encoding = nl_langinfo (CODESET);
00883 #endif
00884 if (current_encoding == NULL || *current_encoding == '\0')
00885 current_encoding = DEFAULT_ENCODING;
00886
00887
00888 java_init_lex (finput, current_encoding);
00889 java_parse_abort_on_error ();
00890
00891 java_parse ();
00892 java_parse_abort_on_error ();
00893 }
00894
00895
00896
00897 static void
00898 parse_source_file_2 ()
00899 {
00900 int save_error_count = java_error_count;
00901 java_complete_class ();
00902 java_parse_abort_on_error ();
00903 }
00904
00905 static void
00906 parse_source_file_3 ()
00907 {
00908 int save_error_count = java_error_count;
00909 java_check_circular_reference ();
00910 java_parse_abort_on_error ();
00911 java_fix_constructors ();
00912 java_parse_abort_on_error ();
00913 java_reorder_fields ();
00914 }
00915
00916 void
00917 add_predefined_file (name)
00918 tree name;
00919 {
00920 predef_filenames = tree_cons (NULL_TREE, name, predef_filenames);
00921 }
00922
00923 int
00924 predefined_filename_p (node)
00925 tree node;
00926 {
00927 tree iter;
00928
00929 for (iter = predef_filenames; iter != NULL_TREE; iter = TREE_CHAIN (iter))
00930 {
00931 if (TREE_VALUE (iter) == node)
00932 return 1;
00933 }
00934 return 0;
00935 }
00936
00937 int
00938 yyparse ()
00939 {
00940 int filename_count = 0;
00941 char *list, *next;
00942 tree node;
00943 FILE *finput = NULL;
00944
00945 if (flag_filelist_file)
00946 {
00947 int avail = 2000;
00948 finput = fopen (input_filename, "r");
00949 if (finput == NULL)
00950 fatal_io_error ("can't open %s", input_filename);
00951 list = xmalloc(avail);
00952 next = list;
00953 for (;;)
00954 {
00955 int count;
00956 if (avail < 500)
00957 {
00958 count = next - list;
00959 avail = 2 * (count + avail);
00960 list = xrealloc (list, avail);
00961 next = list + count;
00962 avail = avail - count;
00963 }
00964
00965 count = fread (next, 1, avail - 1, finput);
00966 if (count == 0)
00967 {
00968 if (! feof (finput))
00969 fatal_io_error ("error closing %s", input_filename);
00970 *next = '\0';
00971 break;
00972 }
00973 avail -= count;
00974 next += count;
00975 }
00976 fclose (finput);
00977 finput = NULL;
00978 }
00979 else
00980 list = xstrdup (input_filename);
00981
00982 do
00983 {
00984 for (next = list; ; )
00985 {
00986 char ch = *next;
00987 if (ch == '\n' || ch == '\r' || ch == '\t' || ch == ' '
00988 || ch == '&' )
00989 {
00990 if (next == list)
00991 {
00992 next++;
00993 list = next;
00994 continue;
00995 }
00996 else
00997 {
00998 *next++ = '\0';
00999 break;
01000 }
01001 }
01002 if (ch == '\0')
01003 {
01004 next = NULL;
01005 break;
01006 }
01007 next++;
01008 }
01009
01010 if (list[0])
01011 {
01012 char *value;
01013 tree id;
01014 int twice = 0;
01015
01016 int len = strlen (list);
01017
01018 obstack_grow0 (&temporary_obstack, list, len);
01019 value = obstack_finish (&temporary_obstack);
01020
01021 filename_count++;
01022
01023
01024
01025
01026
01027
01028
01029
01030 if ((id = maybe_get_identifier (value)))
01031 {
01032 if (predefined_filename_p (id))
01033 {
01034 tree c;
01035 for (c = current_file_list; c; c = TREE_CHAIN (c))
01036 if (TREE_VALUE (c) == id)
01037 twice = 1;
01038 }
01039 else
01040 twice = 1;
01041 }
01042
01043 if (twice)
01044 {
01045 const char *saved_input_filename = input_filename;
01046 input_filename = value;
01047 warning ("source file seen twice on command line and will be compiled only once");
01048 input_filename = saved_input_filename;
01049 }
01050 else
01051 {
01052 BUILD_FILENAME_IDENTIFIER_NODE (node, value);
01053 IS_A_COMMAND_LINE_FILENAME_P (node) = 1;
01054 current_file_list = tree_cons (NULL_TREE, node,
01055 current_file_list);
01056 }
01057 }
01058 list = next;
01059 }
01060 while (next);
01061
01062 if (filename_count == 0)
01063 warning ("no input file specified");
01064
01065 if (resource_name)
01066 {
01067 const char *resource_filename;
01068
01069
01070 assert (TREE_CHAIN (current_file_list) == NULL);
01071
01072 resource_filename = IDENTIFIER_POINTER (TREE_VALUE (current_file_list));
01073 compile_resource_file (resource_name, resource_filename);
01074
01075 return 0;
01076 }
01077
01078 current_jcf = main_jcf;
01079 current_file_list = nreverse (current_file_list);
01080 for (node = current_file_list; node; node = TREE_CHAIN (node))
01081 {
01082 unsigned char magic_string[4];
01083 uint32 magic = 0;
01084 tree name = TREE_VALUE (node);
01085
01086
01087 if (HAS_BEEN_ALREADY_PARSED_P (name))
01088 continue;
01089
01090
01091 if (finput && fclose (finput))
01092 fatal_io_error ("can't close input file %s", main_input_filename);
01093
01094 finput = fopen (IDENTIFIER_POINTER (name), "rb");
01095 if (finput == NULL)
01096 fatal_io_error ("can't open %s", IDENTIFIER_POINTER (name));
01097
01098 #ifdef IO_BUFFER_SIZE
01099 setvbuf (finput, (char *) xmalloc (IO_BUFFER_SIZE),
01100 _IOFBF, IO_BUFFER_SIZE);
01101 #endif
01102 input_filename = IDENTIFIER_POINTER (name);
01103
01104
01105 if (fread (magic_string, 1, 4, finput) == 4)
01106 {
01107 fseek (finput, 0L, SEEK_SET);
01108 magic = GET_u4 (magic_string);
01109 }
01110 if (magic == 0xcafebabe)
01111 {
01112 CLASS_FILE_P (node) = 1;
01113 current_jcf = ALLOC (sizeof (JCF));
01114 JCF_ZERO (current_jcf);
01115 current_jcf->read_state = finput;
01116 current_jcf->filbuf = jcf_filbuf_from_stdio;
01117 jcf_parse (current_jcf);
01118 TYPE_JCF (current_class) = current_jcf;
01119 CLASS_FROM_CURRENTLY_COMPILED_P (current_class) = 1;
01120 TREE_PURPOSE (node) = current_class;
01121 }
01122 else if (magic == (JCF_u4)ZIPMAGIC)
01123 {
01124 ZIP_FILE_P (node) = 1;
01125 JCF_ZERO (main_jcf);
01126 main_jcf->read_state = finput;
01127 main_jcf->filbuf = jcf_filbuf_from_stdio;
01128 if (open_in_zip (main_jcf, input_filename, NULL, 0) < 0)
01129 fatal_error ("bad zip/jar file %s", IDENTIFIER_POINTER (name));
01130 localToFile = SeenZipFiles;
01131
01132 process_zip_dir (main_jcf->read_state);
01133 parse_zip_file_entries ();
01134
01135
01136
01137
01138 }
01139 else
01140 {
01141 JAVA_FILE_P (node) = 1;
01142 java_push_parser_context ();
01143 java_parser_context_save_global ();
01144 parse_source_file_1 (name, finput);
01145 java_parser_context_restore_global ();
01146 java_pop_parser_context (1);
01147 }
01148 }
01149
01150 for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
01151 {
01152 input_filename = ctxp->filename;
01153 parse_source_file_2 ();
01154 }
01155
01156 for (ctxp = ctxp_for_generation; ctxp; ctxp = ctxp->next)
01157 {
01158 input_filename = ctxp->filename;
01159 parse_source_file_3 ();
01160 }
01161
01162 for (node = current_file_list; node; node = TREE_CHAIN (node))
01163 {
01164 input_filename = IDENTIFIER_POINTER (TREE_VALUE (node));
01165 if (CLASS_FILE_P (node))
01166 {
01167 current_class = TREE_PURPOSE (node);
01168 current_jcf = TYPE_JCF (current_class);
01169 layout_class (current_class);
01170 load_inner_classes (current_class);
01171 parse_class_file ();
01172 JCF_FINISH (current_jcf);
01173 }
01174 }
01175 input_filename = main_input_filename;
01176
01177 java_expand_classes ();
01178 if (!java_report_errors () && !flag_syntax_only)
01179 {
01180 emit_register_classes ();
01181 if (flag_indirect_dispatch)
01182 emit_offset_symbol_table ();
01183 }
01184 return 0;
01185 }
01186
01187
01188 static void
01189 parse_zip_file_entries (void)
01190 {
01191 struct ZipDirectory *zdir;
01192 int i;
01193
01194 for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
01195 i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
01196 {
01197 tree class;
01198
01199
01200 if (!zdir->size || !zdir->filename_offset)
01201 continue;
01202
01203 class = lookup_class (get_identifier (ZIPDIR_FILENAME (zdir)));
01204 current_jcf = TYPE_JCF (class);
01205 current_class = class;
01206
01207 if ( !CLASS_LOADED_P (class))
01208 {
01209 if (! CLASS_PARSED_P (class))
01210 {
01211 read_zip_member(current_jcf, zdir, localToFile);
01212 jcf_parse (current_jcf);
01213 }
01214 layout_class (current_class);
01215 load_inner_classes (current_class);
01216 }
01217
01218 if (TYPE_SIZE (current_class) != error_mark_node)
01219 {
01220 input_filename = current_jcf->filename;
01221 parse_class_file ();
01222 FREE (current_jcf->buffer);
01223
01224
01225
01226
01227 }
01228 }
01229 }
01230
01231
01232
01233
01234 static void
01235 process_zip_dir (FILE *finput)
01236 {
01237 int i;
01238 ZipDirectory *zdir;
01239
01240 for (i = 0, zdir = (ZipDirectory *)localToFile->central_directory;
01241 i < localToFile->count; i++, zdir = ZIPDIR_NEXT (zdir))
01242 {
01243 char *class_name, *file_name, *class_name_in_zip_dir;
01244 tree class;
01245 JCF *jcf;
01246 int j;
01247
01248 class_name_in_zip_dir = ZIPDIR_FILENAME (zdir);
01249
01250
01251
01252 if (!zdir->size || !zdir->filename_offset ||
01253 strncmp (&class_name_in_zip_dir[zdir->filename_length-6],
01254 ".class", 6))
01255 {
01256
01257 zdir->size = 0;
01258 continue;
01259 }
01260
01261 class_name = ALLOC (zdir->filename_length+1-6);
01262 file_name = ALLOC (zdir->filename_length+1);
01263 jcf = ALLOC (sizeof (JCF));
01264 JCF_ZERO (jcf);
01265
01266 strncpy (class_name, class_name_in_zip_dir, zdir->filename_length-6);
01267 class_name [zdir->filename_length-6] = '\0';
01268 strncpy (file_name, class_name_in_zip_dir, zdir->filename_length);
01269 file_name [zdir->filename_length] = '\0';
01270
01271 for (j=0; class_name[j]; j++)
01272 class_name [j] = (class_name [j] == '/' ? '.' : class_name [j]);
01273
01274
01275 strcpy (class_name_in_zip_dir, class_name);
01276 zdir->filename_length = j;
01277 class = lookup_class (get_identifier (class_name));
01278
01279 jcf->read_state = finput;
01280 jcf->filbuf = jcf_filbuf_from_stdio;
01281 jcf->java_source = 0;
01282 jcf->classname = class_name;
01283 jcf->filename = file_name;
01284 jcf->zipd = zdir;
01285
01286 TYPE_JCF (class) = jcf;
01287 }
01288 }
01289
01290
01291
01292 void
01293 init_jcf_parse ()
01294 {
01295
01296 ggc_add_tree_root (parse_roots, sizeof (parse_roots) / sizeof(tree));
01297
01298 ggc_add_root (¤t_jcf, 1, sizeof (JCF), (void (*)(void *))ggc_mark_jcf);
01299
01300 init_src_parse ();
01301 }