1 // $Id: control.cpp,v 1.79 2004/05/01 14:47:42 elliott-oss Exp $
2 //
3 // This software is subject to the terms of the IBM Jikes Compiler
4 // License Agreement available at the following URL:
5 // http://ibm.com/developerworks/opensource/jikes.
6 // Copyright (C) 1996, 2004 IBM Corporation and others. All Rights Reserved.
7 // You must accept the terms of that agreement to use this software.
8 //
9 #include "control.h"
10 #include "scanner.h"
11 #include "parser.h"
12 #include "semantic.h"
13 #include "error.h"
14 #include "bytecode.h"
15 #include "case.h"
16 #include "option.h"
17
18 #ifdef HAVE_JIKES_NAMESPACE
19 namespace Jikes { // Open namespace Jikes block
20 #endif
21
Control(char ** arguments,Option & option_)22 Control::Control(char** arguments, Option& option_)
23 : return_code(0)
24 , option(option_)
25 , dot_classpath_index(0)
26 , system_table(NULL)
27 , system_semantic(NULL)
28 , semantic(1024)
29 , needs_body_work(1024)
30 , type_trash_bin(1024)
31 , input_java_file_set(1021)
32 , input_class_file_set(1021)
33 , expired_file_set()
34 , recompilation_file_set(1021)
35 // Type and method cache. These variables are assigned in control.h
36 // accessors, but must be NULL at startup.
37 , Annotation_type(NULL)
38 , AssertionError_type(NULL)
39 , AssertionError_Init_method(NULL)
40 , AssertionError_InitWithChar_method(NULL)
41 , AssertionError_InitWithBoolean_method(NULL)
42 , AssertionError_InitWithInt_method(NULL)
43 , AssertionError_InitWithLong_method(NULL)
44 , AssertionError_InitWithFloat_method(NULL)
45 , AssertionError_InitWithDouble_method(NULL)
46 , AssertionError_InitWithObject_method(NULL)
47 , Boolean_type(NULL)
48 , Boolean_TYPE_field(NULL)
49 , Byte_type(NULL)
50 , Byte_TYPE_field(NULL)
51 , Character_type(NULL)
52 , Character_TYPE_field(NULL)
53 , Class_type(NULL)
54 , Class_forName_method(NULL)
55 , Class_getComponentType_method(NULL)
56 , Class_desiredAssertionStatus_method(NULL)
57 , ClassNotFoundException_type(NULL)
58 , Cloneable_type(NULL)
59 , Comparable_type(NULL)
60 , Double_type(NULL)
61 , Double_TYPE_field(NULL)
62 , ElementType_type(NULL)
63 , ElementType_TYPE_field(NULL)
64 , ElementType_FIELD_field(NULL)
65 , ElementType_METHOD_field(NULL)
66 , ElementType_PARAMETER_field(NULL)
67 , ElementType_CONSTRUCTOR_field(NULL)
68 , ElementType_LOCAL_VARIABLE_field(NULL)
69 , ElementType_ANNOTATION_TYPE_field(NULL)
70 , ElementType_PACKAGE_field(NULL)
71 , Enum_type(NULL)
72 , Enum_Init_method(NULL)
73 , Enum_ordinal_method(NULL)
74 , Enum_valueOf_method(NULL)
75 , Error_type(NULL)
76 , Exception_type(NULL)
77 , Float_type(NULL)
78 , Float_TYPE_field(NULL)
79 , Integer_type(NULL)
80 , Integer_TYPE_field(NULL)
81 , Iterable_type(NULL)
82 , Iterable_iterator_method(NULL)
83 , Iterator_type(NULL)
84 , Iterator_hasNext_method(NULL)
85 , Iterator_next_method(NULL)
86 , Long_type(NULL)
87 , Long_TYPE_field(NULL)
88 , NoClassDefFoundError_type(NULL)
89 , NoClassDefFoundError_Init_method(NULL)
90 , NoClassDefFoundError_InitString_method(NULL)
91 , Object_type(NULL)
92 , Object_getClass_method(NULL)
93 , Overrides_type(NULL)
94 , Retention_type(NULL)
95 , RetentionPolicy_type(NULL)
96 , RetentionPolicy_SOURCE_field(NULL)
97 , RetentionPolicy_CLASS_field(NULL)
98 , RetentionPolicy_RUNTIME_field(NULL)
99 , RuntimeException_type(NULL)
100 , Serializable_type(NULL)
101 , Short_type(NULL)
102 , Short_TYPE_field(NULL)
103 , String_type(NULL)
104 , StringBuffer_type(NULL)
105 , StringBuffer_Init_method(NULL)
106 , StringBuffer_InitWithString_method(NULL)
107 , StringBuffer_toString_method(NULL)
108 , StringBuffer_append_char_method(NULL)
109 , StringBuffer_append_boolean_method(NULL)
110 , StringBuffer_append_int_method(NULL)
111 , StringBuffer_append_long_method(NULL)
112 , StringBuffer_append_float_method(NULL)
113 , StringBuffer_append_double_method(NULL)
114 , StringBuffer_append_string_method(NULL)
115 , StringBuffer_append_object_method(NULL)
116 , StringBuilder_type(NULL)
117 , StringBuilder_Init_method(NULL)
118 , StringBuilder_InitWithString_method(NULL)
119 , StringBuilder_toString_method(NULL)
120 , StringBuilder_append_char_method(NULL)
121 , StringBuilder_append_boolean_method(NULL)
122 , StringBuilder_append_int_method(NULL)
123 , StringBuilder_append_long_method(NULL)
124 , StringBuilder_append_float_method(NULL)
125 , StringBuilder_append_double_method(NULL)
126 , StringBuilder_append_string_method(NULL)
127 , StringBuilder_append_object_method(NULL)
128 , Target_type(NULL)
129 , Throwable_type(NULL)
130 , Throwable_getMessage_method(NULL)
131 , Throwable_initCause_method(NULL)
132 , Void_type(NULL)
133 , Void_TYPE_field(NULL)
134 // storage for all literals seen in source
135 , int_pool(&bad_value)
136 , long_pool(&bad_value)
137 , float_pool(&bad_value)
138 , double_pool(&bad_value)
139 , Utf8_pool(&bad_value)
140 #ifdef JIKES_DEBUG
141 , input_files_processed(0)
142 , class_files_read(0)
143 , class_files_written(0)
144 , line_count(0)
145 #endif // JIKES_DEBUG
146 // Package cache. unnamed and lang are initialized in constructor body.
147 , annotation_package(NULL)
148 , io_package(NULL)
149 , util_package(NULL)
150 {
151 ProcessGlobals();
152 ProcessUnnamedPackage();
153 ProcessPath();
154 ProcessSystemInformation();
155
156 //
157 // Instantiate a scanner and a parser and initialize the static members
158 // for the semantic processors.
159 //
160 scanner = new Scanner(*this);
161 parser = new Parser();
162 SemanticError::StaticInitializer();
163
164 //
165 // Process all file names specified in command line
166 //
167 ProcessNewInputFiles(input_java_file_set, arguments);
168
169 //
170 // For each input file, copy it into the input_files array and process
171 // its package declaration. Estimate we need 64 tokens.
172 //
173 StoragePool* ast_pool = new StoragePool(64);
174 FileSymbol** input_files = new FileSymbol*[input_java_file_set.Size() + 1];
175 int num_files = 0;
176 FileSymbol* file_symbol;
177 for (file_symbol = (FileSymbol*) input_java_file_set.FirstElement();
178 file_symbol;
179 file_symbol = (FileSymbol*) input_java_file_set.NextElement())
180 {
181 input_files[num_files++] = file_symbol;
182 #ifdef JIKES_DEBUG
183 input_files_processed++;
184 #endif
185 errno = 0;
186 scanner -> Scan(file_symbol);
187 if (file_symbol -> lex_stream) // did we have a successful scan!
188 {
189 AstPackageDeclaration* package_declaration =
190 parser -> PackageHeaderParse(file_symbol -> lex_stream,
191 ast_pool);
192 ProcessPackageDeclaration(file_symbol, package_declaration);
193 ast_pool -> Reset();
194 }
195 else
196 {
197 const char* std_err = strerror(errno);
198 ErrorString err_str;
199 err_str << '"' << std_err << '"' << " while trying to open "
200 << file_symbol -> FileName();
201 general_io_errors.Next() = err_str.SafeArray();
202 }
203 }
204
205 //
206 //
207 //
208 FileSymbol* main_file_clone;
209 if (num_files > 0)
210 main_file_clone = input_files[0] -> Clone();
211 else
212 {
213 //
214 // Some name, any name !!! We use dot_name_symbol as a bad file name
215 // because no file can be named ".".
216 //
217 FileSymbol* file_symbol = classpath[dot_classpath_index] ->
218 RootDirectory() -> InsertFileSymbol(dot_name_symbol);
219 file_symbol -> directory_symbol = classpath[dot_classpath_index] ->
220 RootDirectory();
221 file_symbol -> SetJava();
222
223 main_file_clone = file_symbol -> Clone();
224 }
225
226 main_file_clone -> semantic = new Semantic(*this, main_file_clone);
227 system_semantic = main_file_clone -> semantic;
228 scanner -> SetUp(main_file_clone);
229
230 #ifdef WIN32_FILE_SYSTEM
231 //
232 //
233 //
234 if (option.BadMainDisk())
235 {
236 system_semantic -> ReportSemError(SemanticError::NO_CURRENT_DIRECTORY,
237 BAD_TOKEN);
238 }
239 #endif // WIN32_FILE_SYSTEM
240
241 unsigned i;
242 for (i = 0; i < bad_dirnames.Length(); i++)
243 {
244 system_semantic ->
245 ReportSemError(SemanticError::CANNOT_OPEN_PATH_DIRECTORY,
246 BAD_TOKEN, bad_dirnames[i]);
247 }
248 for (i = 0; i < bad_zip_filenames.Length(); i++)
249 {
250 system_semantic -> ReportSemError(SemanticError::CANNOT_OPEN_ZIP_FILE,
251 BAD_TOKEN, bad_zip_filenames[i]);
252 }
253 for (i = 0; i < general_io_warnings.Length(); i++)
254 {
255 system_semantic -> ReportSemError(SemanticError::IO_WARNING, BAD_TOKEN,
256 general_io_warnings[i]);
257 delete [] general_io_warnings[i];
258 }
259 for (i = 0; i < general_io_errors.Length(); i++)
260 {
261 system_semantic -> ReportSemError(SemanticError::IO_ERROR, BAD_TOKEN,
262 general_io_errors[i]);
263 delete [] general_io_errors[i];
264 }
265
266 //
267 // Require the existence of java.lang.
268 //
269 if (lang_package -> directory.Length() == 0)
270 {
271 system_semantic -> ReportSemError(SemanticError::PACKAGE_NOT_FOUND,
272 BAD_TOKEN,
273 StringConstant::US_java_SL_lang);
274 }
275
276 //
277 // When the -d option is specified, create the relevant
278 // directories if they don't already exist.
279 //
280 if (option.directory)
281 {
282 if (! SystemIsDirectory(option.directory))
283 {
284 for (char* ptr = option.directory; *ptr; ptr++)
285 {
286 char delimiter = *ptr;
287 if (delimiter == U_SLASH)
288 {
289 *ptr = U_NULL;
290
291 if (! SystemIsDirectory(option.directory))
292 SystemMkdir(option.directory);
293
294 *ptr = delimiter;
295 }
296 }
297
298 SystemMkdir(option.directory);
299
300 if (! SystemIsDirectory(option.directory))
301 {
302 int length = strlen(option.directory);
303 wchar_t* name = new wchar_t[length + 1];
304 for (int j = 0; j < length; j++)
305 name[j] = option.directory[j];
306 name[length] = U_NULL;
307 system_semantic -> ReportSemError(SemanticError::CANNOT_OPEN_DIRECTORY,
308 BAD_TOKEN, name);
309 delete [] name;
310 }
311 }
312 }
313
314 //
315 //
316 //
317 for (i = 0; i < bad_input_filenames.Length(); i++)
318 {
319 system_semantic -> ReportSemError(SemanticError::BAD_INPUT_FILE,
320 BAD_TOKEN, bad_input_filenames[i]);
321 }
322
323 //
324 //
325 //
326 for (i = 0; i < unreadable_input_filenames.Length(); i++)
327 {
328 system_semantic -> ReportSemError(SemanticError::UNREADABLE_INPUT_FILE,
329 BAD_TOKEN,
330 unreadable_input_filenames[i]);
331 }
332
333 //
334 //
335 //
336 if (system_semantic -> NumErrors() > 0)
337 {
338 system_semantic -> PrintMessages();
339 return_code = system_semantic -> return_code;
340 }
341 else
342 {
343 //
344 // There might be some warnings we want to print.
345 //
346 system_semantic -> PrintMessages();
347 input_java_file_set.SetEmpty();
348 for (int j = 0; j < num_files; j++)
349 {
350 FileSymbol* file_symbol = input_files[j];
351 if (! input_java_file_set.IsElement(file_symbol))
352 ProcessFile(file_symbol);
353 }
354
355 //
356 // Clean up all the files that have just been compiled in this new
357 // batch.
358 //
359 FileSymbol* file_symbol;
360 for (file_symbol = (FileSymbol*) input_java_file_set.FirstElement();
361 file_symbol;
362 file_symbol = (FileSymbol*) input_java_file_set.NextElement())
363 {
364 CleanUp(file_symbol);
365 }
366
367 //
368 // If more messages were added to system_semantic, print them...
369 //
370 system_semantic -> PrintMessages();
371 if (system_semantic -> return_code > 0 ||
372 bad_input_filenames.Length() > 0 ||
373 unreadable_input_filenames.Length() > 0)
374 {
375 return_code = 1;
376 }
377
378 //
379 // If the incremental flag is on, check to see if the user wants us
380 // to recompile.
381 //
382 if (option.incremental)
383 {
384 // The depend flag should only be in effect in the first pass
385 option.depend = false;
386
387 for (bool recompile = IncrementalRecompilation();
388 recompile; recompile = IncrementalRecompilation())
389 {
390 // Reset the return code as we may compile clean in this pass.
391 return_code = 0;
392 system_semantic -> return_code = 0;
393
394 //
395 //
396 //
397 for (i = 0; i < bad_input_filenames.Length(); i++)
398 {
399 system_semantic ->
400 ReportSemError(SemanticError::BAD_INPUT_FILE,
401 BAD_TOKEN, bad_input_filenames[i]);
402 }
403
404 //
405 //
406 //
407 for (i = 0; i < unreadable_input_filenames.Length(); i++)
408 {
409 system_semantic ->
410 ReportSemError(SemanticError::UNREADABLE_INPUT_FILE,
411 BAD_TOKEN,
412 unreadable_input_filenames[i]);
413 }
414
415 FileSymbol* file_symbol;
416
417 num_files = 0;
418 delete [] input_files; // delete previous copy
419 input_files = new FileSymbol*[recompilation_file_set.Size()];
420 for (file_symbol = (FileSymbol*) recompilation_file_set.FirstElement();
421 file_symbol;
422 file_symbol = (FileSymbol*) recompilation_file_set.NextElement())
423 {
424 input_java_file_set.RemoveElement(file_symbol);
425 input_files[num_files++] = file_symbol;
426
427 LexStream* lex_stream = file_symbol -> lex_stream;
428 if (lex_stream)
429 {
430 AstPackageDeclaration* package_declaration = parser ->
431 PackageHeaderParse(lex_stream, ast_pool);
432 ProcessPackageDeclaration(file_symbol,
433 package_declaration);
434 ast_pool -> Reset();
435 }
436 }
437
438 //
439 // If a file was erased, remove it from the input file set.
440 //
441 for (file_symbol = (FileSymbol*) expired_file_set.FirstElement();
442 file_symbol;
443 file_symbol = (FileSymbol*) expired_file_set.NextElement())
444 {
445 input_java_file_set.RemoveElement(file_symbol);
446 }
447
448 //
449 // Reset the global objects before recompiling this new batch.
450 //
451 expired_file_set.SetEmpty();
452 recompilation_file_set.SetEmpty();
453 type_trash_bin.Reset();
454
455 //
456 // For each file that should be recompiled, process it if it
457 // has not already been dragged in by dependence.
458 //
459 for (int j = 0; j < num_files; j++)
460 {
461 FileSymbol* file_symbol = input_files[j];
462 if (! input_java_file_set.IsElement(file_symbol))
463 ProcessFile(file_symbol);
464 }
465
466 //
467 // Clean up all the files that have just been compiled in
468 // this new batch.
469 //
470 for (file_symbol = (FileSymbol*) input_java_file_set.FirstElement();
471 // delete file_symbol
472 file_symbol;
473 file_symbol = (FileSymbol*) input_java_file_set.NextElement())
474 {
475 // delete file_symbol
476 CleanUp(file_symbol);
477 }
478
479 //
480 // If any system error or warning was detected, print it...
481 //
482 system_semantic -> PrintMessages();
483 if (system_semantic -> return_code > 0 ||
484 bad_input_filenames.Length() > 0 ||
485 unreadable_input_filenames.Length() > 0)
486 {
487 return_code = 1;
488 }
489 }
490 }
491
492 //
493 // Are we supposed to generate Makefiles?
494 //
495 if (option.makefile)
496 {
497 if (option.dependence_report)
498 {
499 FILE* outfile = SystemFopen(option.dependence_report_name,
500 "w");
501 if (outfile == NULL)
502 Coutput << "*** Cannot open dependence output file "
503 << option.dependence_report_name << endl;
504 else
505 {
506 SymbolSet types_in_new_files;
507 FileSymbol* file_symbol;
508 for (file_symbol = (FileSymbol*) input_java_file_set.FirstElement();
509 file_symbol;
510 file_symbol = (FileSymbol*) input_java_file_set.NextElement())
511 {
512 char* java_name = file_symbol -> FileName();
513
514 for (i = 0; i < file_symbol -> types.Length(); i++)
515 {
516 TypeSymbol* type = file_symbol -> types[i];
517 fprintf(outfile, "%s : %s\n", java_name,
518 type -> SignatureString());
519
520 TypeSymbol* static_parent;
521 for (static_parent = (TypeSymbol*) type -> static_parents -> FirstElement();
522 static_parent;
523 static_parent = (TypeSymbol*) type -> static_parents -> NextElement())
524 {
525 if (! type -> parents ->
526 IsElement(static_parent))
527 {
528 // Only a static ref to static_parent?
529 fprintf(outfile, " !%s\n",
530 static_parent -> SignatureString());
531
532 //
533 // If the type is contained in a type that
534 // is not one of the input files, save it
535 //
536 if (static_parent -> file_symbol &&
537 static_parent -> file_symbol -> IsClass())
538 {
539 types_in_new_files.AddElement(static_parent);
540 }
541 }
542 }
543
544 TypeSymbol* parent;
545 for (parent = (TypeSymbol*) type -> parents -> FirstElement();
546 parent;
547 parent = (TypeSymbol*) type -> parents -> NextElement())
548 {
549 fprintf(outfile, " %s\n",
550 parent -> SignatureString());
551
552 //
553 // If the type is contained in a type that is
554 // not one of the input files, save it
555 //
556 if (parent -> file_symbol &&
557 parent -> file_symbol -> IsClass())
558 {
559 types_in_new_files.AddElement(parent);
560 }
561 }
562 }
563 }
564
565 //
566 // Print the list of class files that are referenced.
567 //
568 TypeSymbol* type;
569 for (type = (TypeSymbol*) types_in_new_files.FirstElement();
570 type;
571 type = (TypeSymbol*) types_in_new_files.NextElement())
572 {
573 char* class_name = type -> file_symbol -> FileName();
574 fprintf(outfile, "%s : %s\n", class_name,
575 type -> SignatureString());
576 }
577
578 fclose(outfile);
579 }
580 }
581 else
582 {
583 SymbolSet* candidates =
584 new SymbolSet(input_java_file_set.Size() +
585 input_class_file_set.Size());
586 *candidates = input_java_file_set;
587 candidates -> Union(input_class_file_set);
588
589 TypeDependenceChecker* dependence_checker =
590 new TypeDependenceChecker(this, *candidates,
591 type_trash_bin);
592 dependence_checker -> PartialOrder();
593 dependence_checker -> OutputDependences();
594 delete dependence_checker;
595
596 delete candidates;
597 }
598 }
599 }
600
601 delete ast_pool;
602 delete main_file_clone; // delete the clone of the main source file...
603 delete [] input_files;
604 }
605
606
~Control()607 Control::~Control()
608 {
609 unsigned i;
610 for (i = 0; i < bad_zip_filenames.Length(); i++)
611 delete [] bad_zip_filenames[i];
612 for (i = 0; i < bad_input_filenames.Length(); i++)
613 delete [] bad_input_filenames[i];
614 for (i = 0; i < unreadable_input_filenames.Length(); i++)
615 delete [] unreadable_input_filenames[i];
616 for (i = 0; i < system_directories.Length(); i++)
617 delete system_directories[i];
618
619 delete scanner;
620 delete parser;
621 delete system_semantic;
622 delete system_table;
623
624 #ifdef JIKES_DEBUG
625 if (option.debug_dump_lex || option.debug_dump_ast ||
626 option.debug_unparse_ast)
627 {
628 Coutput << line_count << " source lines read" << endl
629 << class_files_read << " \".class\" files read" << endl
630 << class_files_written << " \".class\" files written" << endl
631 << input_files_processed << " \".java\" files processed"
632 << endl;
633 }
634 #endif // JIKES_DEBUG
635 }
636
637
ProcessPackage(const wchar_t * name)638 PackageSymbol* Control::ProcessPackage(const wchar_t* name)
639 {
640 int name_length = wcslen(name);
641 wchar_t* package_name = new wchar_t[name_length];
642 int length;
643 for (length = 0;
644 length < name_length && name[length] != U_SLASH; length++)
645 {
646 package_name[length] = name[length];
647 }
648 NameSymbol* name_symbol = FindOrInsertName(package_name, length);
649
650 PackageSymbol* package_symbol =
651 external_table.FindPackageSymbol(name_symbol);
652 if (! package_symbol)
653 {
654 package_symbol = external_table.InsertPackageSymbol(name_symbol, NULL);
655 FindPathsToDirectory(package_symbol);
656 }
657
658 while (length < name_length)
659 {
660 int start = ++length;
661 for (int i = 0;
662 length < name_length && name[length] != U_SLASH;
663 i++, length++)
664 {
665 package_name[i] = name[length];
666 }
667 name_symbol = FindOrInsertName(package_name, length - start);
668 PackageSymbol* subpackage_symbol =
669 package_symbol -> FindPackageSymbol(name_symbol);
670 if (! subpackage_symbol)
671 {
672 subpackage_symbol =
673 package_symbol -> InsertPackageSymbol(name_symbol);
674 FindPathsToDirectory(subpackage_symbol);
675 }
676 package_symbol = subpackage_symbol;
677 }
678
679 delete [] package_name;
680 return package_symbol;
681 }
682
683
684 //
685 // When searching for a subdirectory in a zipped file, it must already be
686 // present in the hierarchy.
687 //
FindSubdirectory(PathSymbol * path_symbol,wchar_t * name,int name_length)688 DirectorySymbol* Control::FindSubdirectory(PathSymbol* path_symbol,
689 wchar_t* name, int name_length)
690 {
691 wchar_t* directory_name = new wchar_t[name_length + 1];
692
693 DirectorySymbol* directory_symbol = path_symbol -> RootDirectory();
694 for (int start = 0, end;
695 directory_symbol && start < name_length;
696 start = end + 1)
697 {
698 end = start;
699 for (int i = 0; end < name_length && name[end] != U_SLASH; i++, end++)
700 directory_name[i] = name[end];
701 NameSymbol* name_symbol = FindOrInsertName(directory_name,
702 end - start);
703 directory_symbol =
704 directory_symbol -> FindDirectorySymbol(name_symbol);
705 }
706
707 delete [] directory_name;
708 return directory_symbol;
709 }
710
711
712 //
713 // When searching for a directory in the system, if it is not already present
714 // in the hierarchy insert it and attempt to read it from the system...
715 //
716 #ifdef UNIX_FILE_SYSTEM
ProcessSubdirectories(wchar_t * source_name,int source_name_length,bool source_dir)717 DirectorySymbol* Control::ProcessSubdirectories(wchar_t* source_name,
718 int source_name_length,
719 bool source_dir)
720 {
721 int name_length = (source_name_length < 0 ? 0 : source_name_length);
722 char* input_name = new char[name_length + 1];
723 for (int i = 0; i < name_length; i++)
724 input_name[i] = source_name[i];
725 input_name[name_length] = U_NULL;
726
727 DirectorySymbol* directory_symbol = NULL;
728 struct stat status;
729 if (SystemStat(input_name, &status) == 0 &&
730 (status.st_mode & JIKES_STAT_S_IFDIR))
731 {
732 directory_symbol = system_table ->
733 FindDirectorySymbol(status.st_dev, status.st_ino);
734 }
735
736 if (! directory_symbol)
737 {
738 if (input_name[0] == U_SLASH) // file name starts with '/'
739 {
740 directory_symbol =
741 new DirectorySymbol(FindOrInsertName(source_name, name_length),
742 classpath[dot_classpath_index],
743 source_dir);
744 directory_symbol -> ReadDirectory();
745 system_directories.Next() = directory_symbol;
746 system_table -> InsertDirectorySymbol(status.st_dev,
747 status.st_ino,
748 directory_symbol);
749 }
750 else
751 {
752 wchar_t* name = new wchar_t[name_length + 1];
753 for (int i = 0; i < name_length; i++)
754 name[i] = source_name[i];
755 name[name_length] = U_NULL;
756
757 // Start at the dot directory.
758 directory_symbol =
759 classpath[dot_classpath_index] -> RootDirectory();
760
761 wchar_t* directory_name = new wchar_t[name_length];
762 int end = 0;
763 for (int start = end; start < name_length; start = end)
764 {
765 int length;
766 for (length = 0;
767 end < name_length && name[end] != U_SLASH;
768 length++, end++)
769 {
770 directory_name[length] = name[end];
771 }
772
773 if (length != 1 || directory_name[0] != U_DOT)
774 {
775 // Not the current directory.
776 if (length == 2 && directory_name[0] == U_DOT &&
777 directory_name[1] == U_DOT)
778 {
779 // keep the current directory
780 if (directory_symbol -> Identity() == dot_name_symbol ||
781 directory_symbol -> Identity() == dot_dot_name_symbol)
782 {
783 DirectorySymbol* subdirectory_symbol =
784 directory_symbol -> FindDirectorySymbol(dot_dot_name_symbol);
785 if (! subdirectory_symbol)
786 subdirectory_symbol =
787 directory_symbol -> InsertDirectorySymbol(dot_dot_name_symbol,
788 source_dir);
789 directory_symbol = subdirectory_symbol;
790 }
791 else directory_symbol = directory_symbol -> owner -> DirectoryCast();
792 }
793 else
794 {
795 NameSymbol* name_symbol =
796 FindOrInsertName(directory_name, length);
797 DirectorySymbol* subdirectory_symbol =
798 directory_symbol -> FindDirectorySymbol(name_symbol);
799 if (! subdirectory_symbol)
800 subdirectory_symbol =
801 directory_symbol -> InsertDirectorySymbol(name_symbol,
802 source_dir);
803 directory_symbol = subdirectory_symbol;
804 }
805 }
806
807 for (end++;
808 end < name_length && name[end] == U_SLASH;
809 end++); // skip all extra '/'
810 }
811
812 //
813 // Insert the new directory into the system table to avoid
814 // duplicates, in case the same directory is specified with
815 // a different name.
816 //
817 if (directory_symbol !=
818 classpath[dot_classpath_index] -> RootDirectory())
819 {
820 // Not the dot directory.
821 system_table -> InsertDirectorySymbol(status.st_dev,
822 status.st_ino,
823 directory_symbol);
824 directory_symbol -> ReadDirectory();
825 }
826
827 delete [] directory_name;
828 delete [] name;
829 }
830 }
831
832 delete [] input_name;
833 return directory_symbol;
834 }
835 #elif defined(WIN32_FILE_SYSTEM)
ProcessSubdirectories(wchar_t * source_name,int source_name_length,bool source_dir)836 DirectorySymbol* Control::ProcessSubdirectories(wchar_t* source_name,
837 int source_name_length,
838 bool source_dir)
839 {
840 DirectorySymbol* directory_symbol =
841 classpath[dot_classpath_index] -> RootDirectory();
842
843 int name_length = (source_name_length < 0 ? 0 : source_name_length);
844 wchar_t* name = new wchar_t[name_length + 1];
845 char* input_name = new char[name_length + 1];
846 for (int i = 0; i < name_length; i++)
847 input_name[i] = name[i] = source_name[i];
848 input_name[name_length] = name[name_length] = U_NULL;
849
850 if (name_length >= 2 && Case::IsAsciiAlpha(input_name[0]) &&
851 input_name[1] == U_COLON) // a disk was specified
852 {
853 char disk = input_name[0];
854 option.SaveCurrentDirectoryOnDisk(disk);
855 if (SetCurrentDirectory(input_name))
856 {
857 // First, get the right size.
858 DWORD directory_length = GetCurrentDirectory(0, input_name);
859 char* full_directory_name = new char[directory_length + 1];
860 DWORD length = GetCurrentDirectory(directory_length, full_directory_name);
861 if (length <= directory_length)
862 {
863 // Turn '\' to '/'.
864 for (char* ptr = full_directory_name; *ptr; ptr++)
865 *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH);
866
867 char* current_directory = option.GetMainCurrentDirectory();
868 int prefix_length = strlen(current_directory);
869 int start = (prefix_length <= (int) length &&
870 Case::StringSegmentEqual(current_directory,
871 full_directory_name,
872 prefix_length) &&
873 (full_directory_name[prefix_length] == U_SLASH ||
874 full_directory_name[prefix_length] == U_NULL)
875 ? prefix_length + 1
876 : 0);
877
878 if (start > (int) length)
879 name_length = 0;
880 else if (start <= (int) length) // note that we can assert that (start != length)
881 {
882 delete [] name;
883 name_length = length - start;
884 name = new wchar_t[name_length + 1];
885 for (int k = 0, i = start; i < (int) length; i++, k++)
886 name[k] = full_directory_name[i];
887 name[name_length] = U_NULL;
888 }
889 }
890
891 delete [] full_directory_name;
892 }
893
894 // Reset the current directory on this disk.
895 option.ResetCurrentDirectoryOnDisk(disk);
896 option.SetMainCurrentDirectory(); // Reset the real current directory.
897 }
898
899 int end;
900 if (name_length > 2 && Case::IsAsciiAlpha(name[0]) &&
901 name[1] == U_COLON && name[2] == U_SLASH)
902 {
903 end = 3;
904 }
905 else
906 {
907 for (end = 0;
908 end < name_length && name[end] == U_SLASH;
909 end++); // keep all extra leading '/'
910 }
911
912 wchar_t* directory_name = new wchar_t[name_length];
913 int length;
914 if (end > 0)
915 {
916 for (length = 0; length < end; length++)
917 directory_name[length] = name[length];
918 NameSymbol* name_symbol = FindOrInsertName(directory_name, length);
919 DirectorySymbol* subdirectory_symbol =
920 directory_symbol -> FindDirectorySymbol(name_symbol);
921 if (! subdirectory_symbol)
922 subdirectory_symbol =
923 directory_symbol -> InsertDirectorySymbol(name_symbol,
924 source_dir);
925 directory_symbol = subdirectory_symbol;
926 }
927
928 for (int start = end; start < name_length; start = end)
929 {
930 for (length = 0;
931 end < name_length && name[end] != U_SLASH;
932 length++, end++)
933 {
934 directory_name[length] = name[end];
935 }
936
937 if (length != 1 || directory_name[0] != U_DOT)
938 {
939 // Not the current directory.
940 if (length == 2 && directory_name[0] == U_DOT &&
941 directory_name[1] == U_DOT)
942 {
943 // Keep the current directory.
944 if (directory_symbol -> Identity() == dot_name_symbol ||
945 directory_symbol -> Identity() == dot_dot_name_symbol)
946 {
947 DirectorySymbol* subdirectory_symbol =
948 directory_symbol -> FindDirectorySymbol(dot_dot_name_symbol);
949 if (! subdirectory_symbol)
950 subdirectory_symbol =
951 directory_symbol -> InsertDirectorySymbol(dot_dot_name_symbol,
952 source_dir);
953 directory_symbol = subdirectory_symbol;
954 }
955 else directory_symbol = directory_symbol -> owner -> DirectoryCast();
956 }
957 else
958 {
959 NameSymbol* name_symbol = FindOrInsertName(directory_name,
960 length);
961 DirectorySymbol* subdirectory_symbol =
962 directory_symbol -> FindDirectorySymbol(name_symbol);
963 if (! subdirectory_symbol)
964 subdirectory_symbol =
965 directory_symbol -> InsertDirectorySymbol(name_symbol,
966 source_dir);
967 directory_symbol = subdirectory_symbol;
968 }
969 }
970
971 for (end++;
972 end < name_length && name[end] == U_SLASH;
973 end++); // skip all extra '/'
974 }
975
976 directory_symbol -> ReadDirectory();
977
978 delete [] directory_name;
979 delete [] name;
980 delete [] input_name;
981 return directory_symbol;
982 }
983 #endif // WIN32_FILE_SYSTEM
984
985
ProcessNewInputFiles(SymbolSet & file_set,char ** arguments)986 void Control::ProcessNewInputFiles(SymbolSet& file_set, char** arguments)
987 {
988 unsigned i;
989 for (i = 0; i < bad_input_filenames.Length(); i++)
990 delete [] bad_input_filenames[i];
991 bad_input_filenames.Reset();
992 for (i = 0; i < unreadable_input_filenames.Length(); i++)
993 delete [] unreadable_input_filenames[i];
994 unreadable_input_filenames.Reset();
995
996 //
997 // Process all file names specified in command line. By this point, only
998 // filenames should remain in arguments - constructing the Option should
999 // have filtered out all options and expanded @files.
1000 //
1001 if (arguments)
1002 {
1003 int j = 0;
1004 while (arguments[j])
1005 {
1006 char* file_name = arguments[j++];
1007 unsigned file_name_length = strlen(file_name);
1008
1009 wchar_t* name = new wchar_t[file_name_length + 1];
1010 for (unsigned i = 0; i < file_name_length; i++)
1011 name[i] = (file_name[i] != U_BACKSLASH ? file_name[i]
1012 : (wchar_t) U_SLASH); // Change '\' to '/'.
1013 name[file_name_length] = U_NULL;
1014
1015 //
1016 // File must be of the form xxx.java where xxx is a
1017 // character string consisting of at least one character.
1018 //
1019 if (file_name_length < FileSymbol::java_suffix_length ||
1020 (! FileSymbol::IsJavaSuffix(&file_name[file_name_length - FileSymbol::java_suffix_length])))
1021 {
1022 bad_input_filenames.Next() = name;
1023 }
1024 else
1025 {
1026 FileSymbol* file_symbol =
1027 FindOrInsertJavaInputFile(name,
1028 file_name_length - FileSymbol::java_suffix_length);
1029
1030 if (! file_symbol)
1031 unreadable_input_filenames.Next() = name;
1032 else
1033 {
1034 delete [] name;
1035 file_set.AddElement(file_symbol);
1036 }
1037 }
1038 }
1039 }
1040 }
1041
1042
FindOrInsertJavaInputFile(DirectorySymbol * directory_symbol,NameSymbol * file_name_symbol)1043 FileSymbol* Control::FindOrInsertJavaInputFile(DirectorySymbol* directory_symbol,
1044 NameSymbol* file_name_symbol)
1045 {
1046 FileSymbol* file_symbol = NULL;
1047
1048 int length = file_name_symbol -> Utf8NameLength() +
1049 FileSymbol::java_suffix_length;
1050 char* java_name = new char[length + 1]; // +1 for \0
1051 strcpy(java_name, file_name_symbol -> Utf8Name());
1052 strcat(java_name, FileSymbol::java_suffix);
1053
1054 DirectoryEntry* entry = directory_symbol -> FindEntry(java_name, length);
1055 if (entry)
1056 {
1057 file_symbol = directory_symbol -> FindFileSymbol(file_name_symbol);
1058
1059 if (! file_symbol)
1060 {
1061 file_symbol =
1062 directory_symbol -> InsertFileSymbol(file_name_symbol);
1063 file_symbol -> directory_symbol = directory_symbol;
1064 file_symbol -> SetJava();
1065 }
1066
1067 file_symbol -> mtime = entry -> Mtime();
1068 }
1069
1070 delete [] java_name;
1071 return file_symbol;
1072 }
1073
1074
FindOrInsertJavaInputFile(wchar_t * name,int name_length)1075 FileSymbol* Control::FindOrInsertJavaInputFile(wchar_t* name, int name_length)
1076 {
1077 FileSymbol* file_symbol = NULL;
1078
1079 //
1080 // The name has been preprocessed so that if it contains any
1081 // slashes it is a forward slash. In the loop below we look
1082 // for the occurrence of the first slash (if any) that separates
1083 // the file name from its directory name.
1084 //
1085 DirectorySymbol* directory_symbol;
1086 NameSymbol* file_name_symbol;
1087 #ifdef UNIX_FILE_SYSTEM
1088 int len;
1089 for (len = name_length - 1; len >= 0 && name[len] != U_SLASH; len--)
1090 ;
1091 directory_symbol = ProcessSubdirectories(name, len, true);
1092 file_name_symbol = FindOrInsertName(&name[len + 1],
1093 name_length - (len + 1));
1094 #elif defined(WIN32_FILE_SYSTEM)
1095 int len;
1096 for (len = name_length - 1;
1097 len >= 0 && name[len] != U_SLASH && name[len] != U_COLON;
1098 len--);
1099
1100 directory_symbol = ProcessSubdirectories(name,
1101 (name[len] == U_COLON ? len + 1
1102 : len),
1103 true);
1104 file_name_symbol = FindOrInsertName(&name[len + 1],
1105 name_length - (len + 1));
1106 #endif // WIN32_FILE_SYSTEM
1107
1108 for (unsigned i = 1; i < classpath.Length(); i++)
1109 {
1110 if (i == dot_classpath_index) // the current directory (.).
1111 {
1112 file_symbol = FindOrInsertJavaInputFile(directory_symbol,
1113 file_name_symbol);
1114 if (file_symbol)
1115 break;
1116 }
1117 else if (classpath[i] -> IsZip())
1118 {
1119 DirectorySymbol* directory_symbol = FindSubdirectory(classpath[i],
1120 name, len);
1121 if (directory_symbol)
1122 {
1123 file_symbol =
1124 directory_symbol -> FindFileSymbol(file_name_symbol);
1125 if (file_symbol && file_symbol -> IsJava())
1126 break;
1127 else file_symbol = NULL;
1128 }
1129 }
1130 }
1131
1132 //
1133 // If the file was found, return it; otherwise, in case the (.) directory
1134 // was not specified in the classpath, search for the file in it...
1135 //
1136 return file_symbol ? file_symbol
1137 : FindOrInsertJavaInputFile(directory_symbol, file_name_symbol);
1138 }
1139
1140
FindOrInsertPackage(LexStream * lex_stream,AstName * name)1141 PackageSymbol* Control::FindOrInsertPackage(LexStream* lex_stream,
1142 AstName* name)
1143 {
1144 PackageSymbol* package;
1145
1146 if (name -> base_opt)
1147 {
1148 package = FindOrInsertPackage(lex_stream, name -> base_opt);
1149 NameSymbol* name_symbol =
1150 lex_stream -> NameSymbol(name -> identifier_token);
1151 PackageSymbol* subpackage = package -> FindPackageSymbol(name_symbol);
1152 if (! subpackage)
1153 subpackage = package -> InsertPackageSymbol(name_symbol);
1154 package = subpackage;
1155 }
1156 else
1157 {
1158 NameSymbol* name_symbol =
1159 lex_stream -> NameSymbol(name -> identifier_token);
1160 package = external_table.FindPackageSymbol(name_symbol);
1161 if (! package)
1162 package = external_table.InsertPackageSymbol(name_symbol, NULL);
1163 }
1164
1165 FindPathsToDirectory(package);
1166 return package;
1167 }
1168
1169
ProcessFile(FileSymbol * file_symbol)1170 void Control::ProcessFile(FileSymbol* file_symbol)
1171 {
1172 ProcessHeaders(file_symbol);
1173
1174 //
1175 // As long as there are new bodies, ...
1176 //
1177 for (unsigned i = 0; i < needs_body_work.Length(); i++)
1178 {
1179 assert(semantic.Length() == 0);
1180
1181 //
1182 // These bodies are not necessarily in file_symbol; they
1183 // might be in another FileSymbol used by file_symbol.
1184 //
1185 ProcessBodies(needs_body_work[i]);
1186 }
1187 needs_body_work.Reset();
1188 }
1189
1190
ProcessHeaders(FileSymbol * file_symbol)1191 void Control::ProcessHeaders(FileSymbol* file_symbol)
1192 {
1193 if (file_symbol -> semantic)
1194 return;
1195 input_java_file_set.AddElement(file_symbol);
1196
1197 bool initial_invocation = (semantic.Length() == 0);
1198
1199 if (option.verbose)
1200 {
1201 Coutput << "[read "
1202 << file_symbol -> FileName()
1203 << "]" << endl;
1204 }
1205
1206 if (! file_symbol -> lex_stream)
1207 scanner -> Scan(file_symbol);
1208 else file_symbol -> lex_stream -> Reset();
1209
1210 if (file_symbol -> lex_stream) // do we have a successful scan!
1211 {
1212 if (! file_symbol -> compilation_unit)
1213 file_symbol -> compilation_unit =
1214 parser -> HeaderParse(file_symbol -> lex_stream);
1215 //
1216 // If we have a compilation unit, analyze it, process its types.
1217 //
1218 if (file_symbol -> compilation_unit)
1219 {
1220 assert(! file_symbol -> semantic);
1221
1222 if (! file_symbol -> package)
1223 ProcessPackageDeclaration(file_symbol,
1224 file_symbol -> compilation_unit -> package_declaration_opt);
1225 file_symbol -> semantic = new Semantic(*this, file_symbol);
1226 semantic.Next() = file_symbol -> semantic;
1227 file_symbol -> semantic -> ProcessTypeNames();
1228 }
1229 }
1230
1231 if (initial_invocation)
1232 ProcessMembers();
1233 }
1234
1235
ProcessMembers()1236 void Control::ProcessMembers()
1237 {
1238 Tuple<TypeSymbol*> partially_ordered_types(1024);
1239 SymbolSet needs_member_work(101);
1240 TypeCycleChecker cycle_checker(partially_ordered_types);
1241 TopologicalSort topological_sorter(needs_member_work,
1242 partially_ordered_types);
1243
1244 unsigned start = 0;
1245 while (start < semantic.Length())
1246 {
1247 needs_member_work.SetEmpty();
1248
1249 do
1250 {
1251 //
1252 // Check whether or not there are cycles in this new batch of
1253 // types. Create a partial order of the types (cycles are ordered
1254 // arbitrarily) and place the result in partially_ordered_types.
1255 //
1256 cycle_checker.PartialOrder(semantic, start);
1257 start = semantic.Length(); // next starting point
1258
1259 //
1260 // Process the extends and implements clauses.
1261 //
1262 for (unsigned j = 0; j < partially_ordered_types.Length(); j++)
1263 {
1264 TypeSymbol* type = partially_ordered_types[j];
1265 needs_member_work.AddElement(type);
1266 type -> ProcessTypeHeaders();
1267 type -> semantic_environment -> sem ->
1268 types_to_be_processed.AddElement(type);
1269 }
1270 } while (start < semantic.Length());
1271
1272 //
1273 // Partially order the collection of types in needs_member_work and
1274 // place the result in partially_ordered_types. This reordering is
1275 // based on the complete "supertype" information computed in
1276 // ProcessTypeHeaders.
1277 //
1278 topological_sorter.Sort();
1279 for (unsigned i = 0; i < partially_ordered_types.Length(); i++)
1280 {
1281 TypeSymbol* type = partially_ordered_types[i];
1282 needs_body_work.Next() = type;
1283 type -> ProcessMembers();
1284 }
1285 }
1286
1287 semantic.Reset();
1288 }
1289
1290
CollectTypes(TypeSymbol * type,Tuple<TypeSymbol * > & types)1291 void Control::CollectTypes(TypeSymbol* type, Tuple<TypeSymbol*>& types)
1292 {
1293 types.Next() = type;
1294
1295 for (unsigned j = 0; j < type -> NumAnonymousTypes(); j++)
1296 CollectTypes(type -> AnonymousType(j), types);
1297
1298 if (type -> local)
1299 {
1300 for (TypeSymbol* local_type = (TypeSymbol*) type -> local -> FirstElement();
1301 local_type;
1302 local_type = (TypeSymbol*) type -> local -> NextElement())
1303 {
1304 CollectTypes(local_type, types);
1305 }
1306 }
1307
1308 if (type -> non_local)
1309 {
1310 for (TypeSymbol* non_local_type = (TypeSymbol*) type -> non_local -> FirstElement();
1311 non_local_type;
1312 non_local_type = (TypeSymbol*) type -> non_local -> NextElement())
1313 {
1314 CollectTypes(non_local_type, types);
1315 }
1316 }
1317 }
1318
1319
ProcessBodies(TypeSymbol * type)1320 void Control::ProcessBodies(TypeSymbol* type)
1321 {
1322 Semantic* sem = type -> semantic_environment -> sem;
1323
1324 if (type -> declaration &&
1325 ! sem -> compilation_unit -> BadCompilationUnitCast())
1326 {
1327 #ifdef WIN32_FILE_SYSTEM
1328 if (! type -> file_symbol -> IsZip())
1329 {
1330 int length = type -> Utf8NameLength() +
1331 FileSymbol::class_suffix_length;
1332 char* classfile_name = new char[length + 1]; // +1 for "\0"
1333 strcpy(classfile_name, type -> Utf8Name());
1334 strcat(classfile_name, FileSymbol::class_suffix);
1335
1336 DirectorySymbol* directory =
1337 type -> file_symbol -> OutputDirectory();
1338 DirectoryEntry* entry =
1339 directory -> FindCaseInsensitiveEntry(classfile_name, length);
1340
1341 //
1342 // If an entry is found and it is not identical (in a
1343 // case-sensitive test) to the name of the type, issue an
1344 // appropriate message.
1345 //
1346 if (entry && strcmp(classfile_name, entry -> name) != 0)
1347 {
1348 wchar_t* entry_name = new wchar_t[entry -> length + 1];
1349 for (int i = 0; i < length; i++)
1350 entry_name[i] = entry -> name[i];
1351 entry_name[entry -> length] = U_NULL;
1352 sem -> ReportSemError(SemanticError::FILE_FILE_CONFLICT,
1353 type -> declaration -> identifier_token,
1354 type -> Name(), entry_name,
1355 directory -> Name());
1356 delete [] entry_name;
1357 }
1358 delete [] classfile_name;
1359 }
1360 #endif // WIN32_FILE_SYSTEM
1361
1362 if (! parser -> InitializerParse(sem -> lex_stream,
1363 type -> declaration))
1364 {
1365 // Mark that syntax errors were detected.
1366 sem -> compilation_unit -> MarkBad();
1367 }
1368 else
1369 {
1370 type -> CompleteSymbolTable();
1371 if (! parser -> BodyParse(sem -> lex_stream, type -> declaration))
1372 {
1373 // Mark that syntax errors were detected.
1374 sem -> compilation_unit -> MarkBad();
1375 }
1376 else type -> ProcessExecutableBodies();
1377 }
1378
1379 if (sem -> NumErrors() == 0 &&
1380 sem -> lex_stream -> NumBadTokens() == 0 &&
1381 ! sem -> compilation_unit -> BadCompilationUnitCast())
1382 {
1383 Tuple<TypeSymbol*>* types = new Tuple<TypeSymbol*>(1024);
1384 CollectTypes(type, *types);
1385
1386 //
1387 // If we are supposed to generate code, do so now !!!
1388 //
1389 if (option.bytecode)
1390 {
1391 for (unsigned k = 0; k < types -> Length(); k++)
1392 {
1393 TypeSymbol* type = (*types)[k];
1394 // Make sure the literal is available for bytecode.
1395 type -> file_symbol -> SetFileNameLiteral(this);
1396 ByteCode* code = new ByteCode(type);
1397 code -> GenerateCode();
1398 delete code;
1399 }
1400 }
1401
1402 //
1403 // If no error was detected while generating code, then
1404 // start cleaning up.
1405 //
1406 if (! option.nocleanup)
1407 {
1408 if (sem -> NumErrors() == 0)
1409 {
1410 for (unsigned k = 0; k < types -> Length(); k++)
1411 {
1412 TypeSymbol* type = (*types)[k];
1413 delete type -> semantic_environment;
1414 type -> semantic_environment = NULL;
1415 type -> declaration -> semantic_environment = NULL;
1416 }
1417 }
1418 delete types;
1419 }
1420 }
1421 }
1422
1423 sem -> types_to_be_processed.RemoveElement(type);
1424
1425 if (sem -> types_to_be_processed.Size() == 0)
1426 {
1427 // All types belonging to this compilation unit have been processed.
1428 CheckForUnusedImports(sem);
1429 if (! option.nocleanup)
1430 {
1431 CleanUp(sem -> source_file_symbol);
1432 }
1433 }
1434 }
1435
CheckForUnusedImports(Semantic * sem)1436 void Control::CheckForUnusedImports(Semantic* sem)
1437 {
1438 if (sem -> NumErrors() != 0 ||
1439 sem -> lex_stream -> NumBadTokens() != 0 ||
1440 sem -> compilation_unit -> BadCompilationUnitCast())
1441 {
1442 //
1443 // It's not worth checking for unused imports if compilation
1444 // wasn't successful; we may well have just not got round to
1445 // compiling the relevant code, and if there were errors, the
1446 // user has more important things to worry about than unused
1447 // imports!
1448 //
1449 return;
1450 }
1451
1452 for (unsigned i = 0;
1453 i < sem -> compilation_unit -> NumImportDeclarations(); ++i)
1454 {
1455 AstImportDeclaration* import_declaration =
1456 sem -> compilation_unit -> ImportDeclaration(i);
1457 Symbol* symbol = import_declaration -> name -> symbol;
1458 if (import_declaration -> star_token_opt)
1459 {
1460 PackageSymbol* package = symbol -> PackageCast();
1461 if (package &&
1462 ! sem -> referenced_package_imports.IsElement(package))
1463 {
1464 sem -> ReportSemError(SemanticError::UNUSED_PACKAGE_IMPORT,
1465 import_declaration,
1466 package -> PackageName());
1467 }
1468 }
1469 else
1470 {
1471 TypeSymbol* import_type = symbol -> TypeCast();
1472 if (import_type &&
1473 ! sem -> referenced_type_imports.IsElement(import_type))
1474 {
1475 sem -> ReportSemError(SemanticError::UNUSED_TYPE_IMPORT,
1476 import_declaration,
1477 import_type -> ContainingPackage() -> PackageName(),
1478 import_type -> ExternalName());
1479 }
1480 }
1481 }
1482 }
1483
1484 //
1485 // Introduce the main package and the current package.
1486 // This procedure is invoked directly only while doing
1487 // an incremental compilation.
1488 //
ProcessPackageDeclaration(FileSymbol * file_symbol,AstPackageDeclaration * package_declaration)1489 void Control::ProcessPackageDeclaration(FileSymbol* file_symbol,
1490 AstPackageDeclaration* package_declaration)
1491 {
1492 file_symbol -> package = (package_declaration
1493 ? FindOrInsertPackage(file_symbol -> lex_stream,
1494 package_declaration -> name)
1495 : unnamed_package);
1496
1497 for (unsigned i = 0; i < file_symbol -> lex_stream -> NumTypes(); i++)
1498 {
1499 TokenIndex identifier_token = file_symbol -> lex_stream ->
1500 Next(file_symbol -> lex_stream -> Type(i));
1501 if (file_symbol -> lex_stream -> Kind(identifier_token) ==
1502 TK_Identifier)
1503 {
1504 NameSymbol* name_symbol =
1505 file_symbol -> lex_stream -> NameSymbol(identifier_token);
1506 if (! file_symbol -> package -> FindTypeSymbol(name_symbol))
1507 {
1508 TypeSymbol* type = file_symbol -> package ->
1509 InsertOuterTypeSymbol(name_symbol);
1510 type -> file_symbol = file_symbol;
1511 type -> outermost_type = type;
1512 type -> supertypes_closure = new SymbolSet;
1513 type -> subtypes = new SymbolSet;
1514 type -> SetOwner(file_symbol -> package);
1515 type -> SetSignature(*this);
1516 type -> MarkSourcePending();
1517
1518 //
1519 // If this type is contained in the unnamed package add it to
1520 // the set unnamed_package_types if a type of similar name was
1521 // not already there.
1522 //
1523 if (! package_declaration &&
1524 unnamed_package_types.Image(type -> Identity()) == NULL)
1525 {
1526 unnamed_package_types.AddElement(type);
1527 }
1528 }
1529 }
1530 }
1531 }
1532
1533
CleanUp(FileSymbol * file_symbol)1534 void Control::CleanUp(FileSymbol* file_symbol)
1535 {
1536 Semantic* sem = file_symbol -> semantic;
1537
1538 if (sem)
1539 {
1540 #ifdef JIKES_DEBUG
1541 if (option.debug_dump_lex)
1542 {
1543 sem -> lex_stream -> Reset(); // rewind input and ...
1544 sem -> lex_stream -> Dump(); // dump it!
1545 }
1546 if (option.debug_dump_ast)
1547 sem -> compilation_unit -> Print(*sem -> lex_stream);
1548 if (option.debug_unparse_ast)
1549 {
1550 if (option.debug_unparse_ast_debug)
1551 {
1552 // which of these is correct?
1553 sem -> compilation_unit -> debug_unparse = true;
1554 Ast::debug_unparse = true;
1555 }
1556 sem -> compilation_unit -> Unparse(sem -> lex_stream,
1557 "unparsed/");
1558 }
1559 #endif // JIKES_DEBUG
1560 sem -> PrintMessages();
1561 if (sem -> return_code > 0)
1562 return_code = 1;
1563
1564 file_symbol -> CleanUp();
1565 }
1566 }
1567
1568
1569 #ifdef HAVE_JIKES_NAMESPACE
1570 } // Close namespace Jikes block
1571 #endif
1572
1573