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