1 // $Id: system.cpp,v 1.63 2004/06/20 21:24:19 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 
10 #include "platform.h"
11 #include "control.h"
12 #include "semantic.h"
13 #include "zip.h"
14 #include "option.h"
15 #include "case.h"
16 
17 #ifdef HAVE_JIKES_NAMESPACE
18 namespace Jikes { // Open namespace Jikes block
19 #endif
20 
21 //
22 // Convert the null terminated Unicode string source into its Utf8
23 // representation pointed to by target. The char string target is presumed
24 // to have been allocated and to be large enough to accomodate the conversion.
25 //
ConvertUnicodeToUtf8(const wchar_t * source,char * target)26 int Control::ConvertUnicodeToUtf8(const wchar_t* source, char* target)
27 {
28     int length = 0;
29 
30     for ( ; *source; source++)
31     {
32         int ch = *source;
33 
34         if (ch == 0)
35         {
36              target[length++] = (char) 0xC0;
37              target[length++] = (char) 0x80;
38         }
39         else if (ch <= 0x007F)
40              target[length++] = (char) ch;
41         else if (ch <= 0x07FF)
42         {
43 
44             target[length++] = (char) (0xC0 | ((ch >> 6) & 0x1F));
45             target[length++] = (char) (0x80 | (ch & 0x3F));
46         }
47         else
48         {
49             target[length++] = (char) (0xE0 | ((ch >> 12) & 0x0F));
50             target[length++] = (char) (0x80 | ((ch >> 6) & 0x3F));
51             target[length++] = (char) (0x80 | (ch & 0x3F));
52         }
53     }
54     target[length] = U_NULL;
55     return length;
56 }
57 
58 
59 //
60 // Turn a C string literal into a NameSymbol. Because it works even on
61 // non-ASCII systems (where 'a' != U_a), it is slightly inefficient. Hence it
62 // is private and only called from caching accessor methods.
63 //
FindOrInsertSystemName(const char * name)64 NameSymbol* Control::FindOrInsertSystemName(const char* name)
65 {
66     int len = strlen(name);
67     wchar_t* wname = new wchar_t[len + 1];
68     for (int i = 0; i < len; i++)
69     {
70         // Only list the characters we expect in system names.
71         switch (name[i])
72         {
73         case 'a': wname[i] = U_a; break;
74         case 'b': wname[i] = U_b; break;
75         case 'c': wname[i] = U_c; break;
76         case 'd': wname[i] = U_d; break;
77         case 'e': wname[i] = U_e; break;
78         case 'f': wname[i] = U_f; break;
79         case 'g': wname[i] = U_g; break;
80         case 'h': wname[i] = U_h; break;
81         case 'i': wname[i] = U_i; break;
82         case 'j': wname[i] = U_j; break;
83         case 'k': wname[i] = U_k; break;
84         case 'l': wname[i] = U_l; break;
85         case 'm': wname[i] = U_m; break;
86         case 'n': wname[i] = U_n; break;
87         case 'o': wname[i] = U_o; break;
88         case 'p': wname[i] = U_p; break;
89         case 'q': wname[i] = U_q; break;
90         case 'r': wname[i] = U_r; break;
91         case 's': wname[i] = U_s; break;
92         case 't': wname[i] = U_t; break;
93         case 'u': wname[i] = U_u; break;
94         case 'v': wname[i] = U_v; break;
95         case 'w': wname[i] = U_w; break;
96         case 'x': wname[i] = U_x; break;
97         case 'y': wname[i] = U_y; break;
98         case 'z': wname[i] = U_z; break;
99         case 'A': wname[i] = U_A; break;
100         case 'B': wname[i] = U_B; break;
101         case 'C': wname[i] = U_C; break;
102         case 'D': wname[i] = U_D; break;
103         case 'E': wname[i] = U_E; break;
104         case 'F': wname[i] = U_F; break;
105         case 'G': wname[i] = U_G; break;
106         case 'H': wname[i] = U_H; break;
107         case 'I': wname[i] = U_I; break;
108         case 'J': wname[i] = U_J; break;
109         case 'K': wname[i] = U_K; break;
110         case 'L': wname[i] = U_L; break;
111         case 'M': wname[i] = U_M; break;
112         case 'N': wname[i] = U_N; break;
113         case 'O': wname[i] = U_O; break;
114         case 'P': wname[i] = U_P; break;
115         case 'Q': wname[i] = U_Q; break;
116         case 'R': wname[i] = U_R; break;
117         case 'S': wname[i] = U_S; break;
118         case 'T': wname[i] = U_T; break;
119         case 'U': wname[i] = U_U; break;
120         case 'V': wname[i] = U_V; break;
121         case 'W': wname[i] = U_W; break;
122         case 'X': wname[i] = U_X; break;
123         case 'Y': wname[i] = U_Y; break;
124         case 'Z': wname[i] = U_Z; break;
125         case '0': wname[i] = U_0; break;
126         case '1': wname[i] = U_1; break;
127         case '2': wname[i] = U_2; break;
128         case '3': wname[i] = U_3; break;
129         case '4': wname[i] = U_4; break;
130         case '5': wname[i] = U_5; break;
131         case '6': wname[i] = U_6; break;
132         case '7': wname[i] = U_7; break;
133         case '8': wname[i] = U_8; break;
134         case '9': wname[i] = U_9; break;
135         case '_': wname[i] = U_UN; break;
136         case '$': wname[i] = U_DS; break;
137         case '(': wname[i] = U_LP; break;
138         case ')': wname[i] = U_RP; break;
139         case ';': wname[i] = U_SC; break;
140         case '<': wname[i] = U_LT; break;
141         case '>': wname[i] = U_GT; break;
142         case '/': wname[i] = U_SL; break;
143         case '[': wname[i] = U_LB; break;
144         case ']': wname[i] = U_RB; break;
145         case '-': wname[i] = U_MI; break;
146         case '.': wname[i] = U_DO; break;
147         case '?': wname[i] = U_QU; break;
148         default: assert(false && "bad character in system name");
149         }
150     }
151     wname[len] = U_NULL;
152     NameSymbol* name_symbol = name_table.FindOrInsertName(wname, len);
153     delete [] wname;
154     if (! name_symbol -> Utf8_literal)
155         name_symbol -> Utf8_literal =
156             ConvertUnicodeToUtf8(name_symbol -> Name());
157     return name_symbol;
158 }
159 
160 
161 //
162 // Convert the Utf8 string of length len pointed to by source into its unicode
163 // representation pointed to by target. The wchar_t string target is presumed
164 // to have been allocated and to be large enough (at least len + 1) to
165 // accomodate the conversion.
166 //
ConvertUtf8ToUnicode(wchar_t * target,const char * source,int len)167 int Control::ConvertUtf8ToUnicode(wchar_t* target, const char* source, int len)
168 {
169     wchar_t* ptr = target;
170     for (int i = 0; i < len; i++, ptr++)
171     {
172         u1 ch = source[i];
173 
174         if ((ch & 0x80) == 0)
175             *ptr = ch;
176         else if ((ch & 0xE0) == 0xC0)
177         {
178             *ptr = ch & 0x1F;
179             *ptr <<= 6;
180             i++;
181             ch = source[i] & 0x3F;
182             *ptr += ch;
183         }
184         else if ((ch & 0xF0) == 0xE0)
185         {
186             *ptr = ch & 0x0F;
187             *ptr <<= 6;
188             i++;
189             ch = source[i] & 0x3F;
190             *ptr += ch;
191 
192             *ptr <<= 6;
193             i++;
194             ch = source[i] & 0x3F;
195             *ptr += ch;
196         }
197         else assert(false && "invalid character encoding");
198     }
199     *ptr = U_NULL;
200     return ptr - target;
201 }
202 
203 
FindPathsToDirectory(PackageSymbol * package)204 void Control::FindPathsToDirectory(PackageSymbol* package)
205 {
206     if (package -> directory.Length() == 0)
207     {
208         PackageSymbol* owner_package = package -> owner;
209         if (owner_package) // package is a subpackage?
210         {
211             for (unsigned i = 0; i < owner_package -> directory.Length(); i++)
212             {
213                 DirectorySymbol* owner_directory_symbol =
214                     owner_package -> directory[i];
215                 DirectorySymbol* subdirectory_symbol =
216                     owner_directory_symbol -> FindDirectorySymbol(package -> Identity());
217                 if (! owner_directory_symbol -> IsZip())
218                 {
219                     if (! subdirectory_symbol)
220                     {
221                         int length =
222                             owner_directory_symbol -> DirectoryNameLength() +
223                             package -> Utf8NameLength() + 1; // +1 for '/'
224                         char* directory_name = new char[length + 1];
225 
226                         strcpy(directory_name,
227                                owner_directory_symbol -> DirectoryName());
228                         if (owner_directory_symbol -> DirectoryName()[owner_directory_symbol -> DirectoryNameLength() - 1] != U_SLASH)
229                             strcat(directory_name, StringConstant::U8S_SL);
230                         strcat(directory_name, package -> Utf8Name());
231 
232                         if (SystemIsDirectory(directory_name))
233                             subdirectory_symbol = owner_directory_symbol ->
234                                 InsertDirectorySymbol(package -> Identity(),
235                                                       owner_directory_symbol -> IsSourceDirectory());
236 
237                         delete [] directory_name;
238                     }
239 
240                     if (subdirectory_symbol)
241                         subdirectory_symbol -> ReadDirectory();
242                 }
243 
244                 if (subdirectory_symbol)
245                     package -> directory.Next() = subdirectory_symbol;
246             }
247         }
248         else
249         {
250             //
251             // Recall that since classpath[0] contains the default directory,
252             // we always start searching at location 1.
253             //
254             for (unsigned k = 1; k < classpath.Length(); k++)
255             {
256                 PathSymbol* path_symbol = classpath[k];
257                 DirectorySymbol* directory_symbol =
258                     path_symbol -> RootDirectory() -> FindDirectorySymbol(package -> Identity());
259                 if (! path_symbol -> IsZip())
260                 {
261                     if (! directory_symbol)
262                     {
263                         int length = path_symbol -> Utf8NameLength() +
264                             package -> Utf8NameLength() + 1; // +1 for '/'
265                         char* directory_name = new char[length + 1];
266                         strcpy(directory_name, path_symbol -> Utf8Name());
267                         char tail = path_symbol -> Utf8Name()[path_symbol -> Utf8NameLength() - 1];
268                         if (tail != U_SLASH && tail != U_BACKSLASH)
269                             strcat(directory_name, StringConstant::U8S_SL);
270                         strcat(directory_name, package -> Utf8Name());
271 
272                         if (SystemIsDirectory(directory_name))
273                             directory_symbol = path_symbol -> RootDirectory() ->
274                                 InsertDirectorySymbol(package -> Identity(),
275                                                       path_symbol -> RootDirectory() -> IsSourceDirectory());
276                         delete [] directory_name;
277                     }
278 
279                     if (directory_symbol)
280                         directory_symbol -> ReadDirectory();
281                 }
282 
283                 if (directory_symbol)
284                     package -> directory.Next() = directory_symbol;
285             }
286         }
287     }
288 }
289 
290 
ProcessGlobals()291 void Control::ProcessGlobals()
292 {
293     // Some names are conditional on 1.5 VMs, which expanded the set of legal
294     // VM names to include non-Java identifiers.
295     access_name_symbol =
296         FindOrInsertSystemName(option.source < JikesOption::SDK1_5
297                                ? "access$" : "-");
298     array_name_symbol = FindOrInsertSystemName("array");
299     assert_name_symbol = FindOrInsertSystemName("assert");
300     block_init_name_symbol = FindOrInsertSystemName("this");
301     class_name_symbol = FindOrInsertSystemName("class");
302     clinit_name_symbol = FindOrInsertSystemName("<clinit>");
303     clone_name_symbol = FindOrInsertSystemName("clone");
304     dot_name_symbol = FindOrInsertSystemName(".");
305     dot_dot_name_symbol = FindOrInsertSystemName("..");
306     Enum_name_symbol = FindOrInsertSystemName("Enum");
307     equals_name_symbol = FindOrInsertSystemName("equals");
308     false_name_symbol = FindOrInsertSystemName("false");
309     hashCode_name_symbol = FindOrInsertSystemName("hashCode");
310     init_name_symbol = FindOrInsertSystemName("<init>");
311     length_name_symbol = FindOrInsertSystemName("length");
312     null_name_symbol = FindOrInsertSystemName("null");
313     Object_name_symbol = FindOrInsertSystemName("Object");
314     package_info_name_symbol = FindOrInsertSystemName("package-info");
315     question_name_symbol = FindOrInsertSystemName("??");
316     serialPersistentFields_name_symbol =
317         FindOrInsertSystemName("serialPersistentFields");
318     serialVersionUID_name_symbol = FindOrInsertSystemName("serialVersionUID");
319     this_name_symbol = FindOrInsertSystemName("this");
320     true_name_symbol = FindOrInsertSystemName("true");
321     val_name_symbol =
322         FindOrInsertSystemName(option.source < JikesOption::SDK1_5
323                                ? "val$" : "-");
324 
325     ConstantValue_literal = Utf8_pool.FindOrInsert(U8S_ConstantValue,
326                                                    strlen(U8S_ConstantValue));
327     Exceptions_literal = Utf8_pool.FindOrInsert(U8S_Exceptions,
328                                                 strlen(U8S_Exceptions));
329     InnerClasses_literal = Utf8_pool.FindOrInsert(U8S_InnerClasses,
330                                                   strlen(U8S_InnerClasses));
331     Synthetic_literal = Utf8_pool.FindOrInsert(U8S_Synthetic,
332                                                strlen(U8S_Synthetic));
333     Deprecated_literal = Utf8_pool.FindOrInsert(U8S_Deprecated,
334                                                 strlen(U8S_Deprecated));
335     LineNumberTable_literal =
336         Utf8_pool.FindOrInsert(U8S_LineNumberTable,
337                                strlen(U8S_LineNumberTable));
338     LocalVariableTable_literal =
339         Utf8_pool.FindOrInsert(U8S_LocalVariableTable,
340                                strlen(U8S_LocalVariableTable));
341     Code_literal = Utf8_pool.FindOrInsert(U8S_Code, strlen(U8S_Code));
342     SourceFile_literal = Utf8_pool.FindOrInsert(U8S_SourceFile,
343                                                 strlen(U8S_SourceFile));
344     EnclosingMethod_literal =
345         Utf8_pool.FindOrInsert(U8S_EnclosingMethod,
346                                strlen(U8S_EnclosingMethod));
347 }
348 
349 
350 //
351 // Create the unnamed package and set up global names.
352 //
ProcessUnnamedPackage()353 void Control::ProcessUnnamedPackage()
354 {
355     unnamed_package = external_table
356         .InsertPackageSymbol(FindOrInsertName(US_EMPTY, 0), NULL);
357 
358     //
359     // Create an entry for no_type. no_type is used primarily to signal an
360     // error.
361     //
362     no_type = unnamed_package -> InsertSystemTypeSymbol(question_name_symbol);
363     no_type -> SetSignature(dot_name_symbol -> Utf8_literal);
364     no_type -> outermost_type = no_type;
365     no_type -> SetOwner(unnamed_package);
366     no_type -> subtypes = new SymbolSet();
367     no_type -> MarkBad();
368 
369     //
370     // Create an entry for the null type.
371     //
372     null_type = unnamed_package -> InsertSystemTypeSymbol(null_name_symbol);
373     null_type -> outermost_type = null_type;
374     null_type -> SetOwner(unnamed_package);
375     null_type -> SetACC_PUBLIC();
376 }
377 
378 
ProcessPath()379 void Control::ProcessPath()
380 {
381 #ifdef UNIX_FILE_SYSTEM
382     NameSymbol* dot_path_name_symbol = dot_name_symbol;
383 
384     //
385     // We need a place to start. Allocate a "." directory with no owner
386     // initially. (Hence, the null argument.) Allocate a "." path whose
387     // associated directory is the "." directory. Identify the "." path as
388     // the owner of the "." directory. It's not a sourcepath, so pass false.
389     //
390     DirectorySymbol* default_directory = new DirectorySymbol(dot_name_symbol,
391                                                              NULL, false);
392     // Since the "." directory may not be the first directory, set
393     // dot_classpath_index to the first instance in classpath.
394     dot_classpath_index = classpath.Length();
395     classpath.Next() = classpath_table.InsertPathSymbol(dot_path_name_symbol,
396                                                         default_directory);
397     // Note that the default_directory is reset after it has been assigned
398     // the owner above.
399     default_directory -> ReadDirectory();
400     system_directories.Next() = default_directory;
401 
402     system_table = new SystemTable();
403     struct stat status;
404     //FIXME: need to check for stat errors
405     if (SystemStat(dot_name_symbol -> Utf8Name(), &status) == 0 &&
406         (status.st_mode & JIKES_STAT_S_IFDIR))
407         system_table -> InsertDirectorySymbol(status.st_dev, status.st_ino,
408                                               default_directory);
409 
410 #elif defined(WIN32_FILE_SYSTEM)
411 
412     char* main_current_directory = option.GetMainCurrentDirectory();
413     int dot_path_name_length = strlen(main_current_directory);
414     wchar_t* dot_path_name = new wchar_t[dot_path_name_length + 1];
415     for (int i = 0; i < dot_path_name_length; i++)
416         dot_path_name[i] = main_current_directory[i];
417     dot_path_name[dot_path_name_length] = U_NULL;
418     NameSymbol* dot_path_name_symbol = FindOrInsertName(dot_path_name,
419                                                         dot_path_name_length);
420     delete [] dot_path_name;
421 
422     //
423     // We need a place to start. Allocate a "." directory with no owner
424     // initially. (Hence, the null argument.) Allocate a "." path whose
425     // associated directory is the "." directory. Identify the "." path as
426     // the owner of the "." directory. It's not a sourcepath, so pass false.
427     //
428     DirectorySymbol* default_directory = new DirectorySymbol(dot_name_symbol,
429                                                              NULL, false);
430     // Since the "." directory may not be the first directory, set
431     // dot_classpath_index to the first instance in classpath.
432     dot_classpath_index = classpath.Length();
433     classpath.Next() = classpath_table.InsertPathSymbol(dot_path_name_symbol,
434                                                         default_directory);
435     // Note that the default_directory is reset after it has been assigned
436     // the owner above.
437     default_directory -> ReadDirectory();
438     system_directories.Next() = default_directory;
439 #endif // WIN32_FILE_SYSTEM
440     //
441     //
442     //
443 
444     ProcessBootClassPath();
445     ProcessExtDirs();
446     ProcessClassPath();
447     ProcessSourcePath();
448 
449     //
450     // TODO: If the user did not specify "." in the class path we assume it.
451     // javac makes that assumption also. Is that correct?
452     //
453     if (dot_classpath_index == 0)
454         unnamed_package -> directory.Next() = classpath[0] -> RootDirectory();
455 }
456 
ProcessBootClassPath()457 void Control::ProcessBootClassPath()
458 {
459     if (option.bootclasspath)
460     {
461         // The longest possible path name we can encounter
462         int max_path_name_length = strlen(option.bootclasspath) + 1;
463         wchar_t* path_name = new wchar_t[max_path_name_length + 1];
464 
465         wchar_t* input_name = NULL;
466 #ifdef WIN32_FILE_SYSTEM
467         char* full_directory_name = NULL;
468 #endif
469 
470         for (char* path = option.bootclasspath,
471                  * path_tail = &path[strlen(path)];
472              path < path_tail; path++)
473         {
474 #ifdef WIN32_FILE_SYSTEM
475             delete [] full_directory_name;
476             delete [] input_name;
477 #endif
478             char* head;
479             for (head = path; path < path_tail && *path != PathSeparator();
480                  path++);
481 
482             // If a separator was encountered, replace it by \0 to terminate
483             // the string.
484             *path = U_NULL;
485             int input_name_length = path - head;
486 
487             int path_name_length = input_name_length;
488             for (int i = 0; i < path_name_length; i++)
489                 path_name[i] = head[i];
490             path_name[path_name_length] = U_NULL;
491 
492 #ifdef UNIX_FILE_SYSTEM
493 
494             input_name = path_name;
495 
496 #elif defined(WIN32_FILE_SYSTEM)
497 
498             input_name = NULL;
499             full_directory_name = NULL;
500             char disk = (input_name_length >= 2 &&
501                          Case::IsAsciiAlpha(head[0]) &&
502                          head[1] == U_COLON ? head[0] : 0);
503 
504             //
505             // Look for the directory. If it is found, update input_name and
506             // head.
507             //
508             option.SaveCurrentDirectoryOnDisk(disk);
509             if (SetCurrentDirectory(head))
510             {
511                 char tmp[1];
512                 // First, get the right size.
513                 DWORD directory_length = GetCurrentDirectory(0, tmp);
514                 full_directory_name = new char[directory_length + 1];
515                 DWORD length = GetCurrentDirectory(directory_length,
516                                                    full_directory_name);
517                 if (length <= directory_length)
518                 {
519                     for (char* ptr = full_directory_name; *ptr; ptr++)
520                     {
521                         *ptr = (*ptr != U_BACKSLASH
522                                 ? *ptr : (char) U_SLASH); // turn '\' to '/'.
523                     }
524 
525                     input_name_length = length;
526                     input_name = new wchar_t[input_name_length + 1];
527                     for (int k = 0; k < input_name_length; k++)
528                         input_name[k] = full_directory_name[k];
529                     input_name[input_name_length] = U_NULL;
530                     head = full_directory_name;
531                 }
532             }
533 
534             //
535             // Default input_name, in case we do not succeed in finding the
536             // directory.
537             //
538             if (! input_name)
539             {
540                 input_name = new wchar_t[input_name_length + 1];
541                 for (int j = 0; j < input_name_length; j++)
542                     input_name[j] = path_name[j];
543                 input_name[input_name_length] = U_NULL;
544             }
545 
546             // Reset the current directory on disk.
547             option.ResetCurrentDirectoryOnDisk(disk);
548             // Reset the real current directory...
549             option.SetMainCurrentDirectory();
550 #endif // WIN32_FILE_SYSTEM
551 
552             if (input_name_length > 0)
553             {
554                 NameSymbol* name_symbol = FindOrInsertName(path_name,
555                                                            path_name_length);
556 
557                 //
558                 // If a directory is specified more than once, ignore the
559                 // duplicates.
560                 //
561                 if (classpath_table.FindPathSymbol(name_symbol))
562                 {
563                     if (name_symbol == dot_name_symbol)
564                     {
565                         // The next index
566                         dot_classpath_index = classpath.Length();
567                         // Share the "." directory.
568                         classpath.Next() = classpath[0];
569                         unnamed_package -> directory.Next() =
570                             classpath[0] -> RootDirectory();
571                     }
572 
573                     continue;
574                 }
575 
576                 //
577                 // Check whether or not the path points to a system directory.
578                 // If not, assume it's a zip file.
579                 //
580                 if (SystemIsDirectory(head))
581                 {
582                     // This is the bootclasspath so it's not sourcepath, pass
583                     // false
584                     DirectorySymbol* dot_directory =
585                         ProcessSubdirectories(input_name, input_name_length,
586                                               false);
587                     unnamed_package -> directory.Next() = dot_directory;
588                     classpath.Next() =
589                         classpath_table.InsertPathSymbol(name_symbol,
590                                                          dot_directory);
591                 }
592                 else
593                 {
594                     errno = 0;
595                     Zip* zipinfo = new Zip(*this, head);
596                     if (! zipinfo -> IsValid())
597                     {
598                         // If the zipfile is all screwed up, give up here !!!
599                         wchar_t* name = new wchar_t[input_name_length + 1];
600                         for (int i = 0; i < input_name_length; i++)
601                             name[i] = input_name[i];
602                         name[input_name_length] = U_NULL;
603                         if (errno)
604                         {
605                             const char* std_err = strerror(errno);
606                             ErrorString err_str;
607                             err_str << '"' << std_err << '"'
608                                     << " while trying to open " << name;
609                             general_io_warnings.Next() = err_str.SafeArray();
610                         }
611                         else
612                         {
613                             wchar_t* tail = &name[input_name_length - 3];
614                             if (Case::StringSegmentEqual(tail, US_zip, 3) ||
615                                Case::StringSegmentEqual(tail, US_jar, 3))
616                             {
617                                 bad_zip_filenames.Next() = name;
618                             }
619                             else bad_dirnames.Next() = name;
620                         }
621                     }
622 
623                     unnamed_package -> directory.Next() =
624                         zipinfo -> RootDirectory();
625 
626                     //
627                     // Create the new path symbol and update the class path
628                     // with it.
629                     //
630                     PathSymbol* path_symbol =
631                         classpath_table.InsertPathSymbol(name_symbol,
632                                                          zipinfo -> RootDirectory());
633                     path_symbol -> zipfile = zipinfo;
634                     classpath.Next() = path_symbol;
635                 }
636             }
637         }
638 
639 #ifdef WIN32_FILE_SYSTEM
640         delete [] full_directory_name;
641         delete [] input_name;
642 #endif // WIN32_FILE_SYSTEM
643         delete [] path_name;
644     }
645 }
646 
ProcessExtDirs()647 void Control::ProcessExtDirs()
648 {
649     SymbolSet extdirs_set;
650     if (option.extdirs)
651     {
652         // The longest possible path name we can encounter
653         int max_path_name_length = strlen(option.extdirs) + 1;
654         wchar_t* path_name = new wchar_t[max_path_name_length + 1];
655 
656         wchar_t* input_name = NULL;
657 #ifdef WIN32_FILE_SYSTEM
658         char* full_directory_name = NULL;
659 #endif
660 
661         for (char* path = option.extdirs, *path_tail = &path[strlen(path)];
662              path < path_tail; path++)
663         {
664 #ifdef WIN32_FILE_SYSTEM
665             delete [] full_directory_name;
666             delete [] input_name;
667 #endif
668             char* head;
669             for (head = path; path < path_tail && *path != PathSeparator();
670                  path++);
671 
672             // If a separator was encountered, replace it by \0 to terminate
673             // the string.
674             *path = U_NULL;
675 
676             int input_name_length = path - head;
677 
678             int path_name_length = input_name_length;
679             for (int i = 0; i < path_name_length; i++)
680                 path_name[i] = head[i];
681             path_name[path_name_length] = U_NULL;
682 
683 #ifdef UNIX_FILE_SYSTEM
684 
685             input_name = path_name;
686 
687 #elif defined(WIN32_FILE_SYSTEM)
688 
689             input_name = NULL;
690             full_directory_name = NULL;
691             char disk = (input_name_length >= 2 &&
692                          Case::IsAsciiAlpha(head[0]) &&
693                          head[1] == U_COLON ? head[0] : 0);
694 
695             //
696             // Look for the directory. If it is found, update input_name and
697             // head.
698             //
699             option.SaveCurrentDirectoryOnDisk(disk);
700             if (SetCurrentDirectory(head))
701             {
702                 char tmp[1];
703                 // First, get the right size.
704                 DWORD directory_length = GetCurrentDirectory(0, tmp);
705                 full_directory_name = new char[directory_length + 1];
706                 DWORD length = GetCurrentDirectory(directory_length,
707                                                    full_directory_name);
708                 if (length <= directory_length)
709                 {
710                     for (char* ptr = full_directory_name; *ptr; ptr++)
711                         *ptr = (*ptr != U_BACKSLASH
712                                 ? *ptr : (char) U_SLASH); // turn '\' to '/'.
713 
714                     input_name_length = length;
715                     input_name = new wchar_t[input_name_length + 1];
716                     for (int k = 0; k < input_name_length; k++)
717                         input_name[k] = full_directory_name[k];
718                     input_name[input_name_length] = U_NULL;
719                     head = full_directory_name;
720                 }
721             }
722 
723             //
724             // Default input_name, in case we do not succeed in finding the
725             // directory.
726             //
727             if (! input_name)
728             {
729                 input_name = new wchar_t[input_name_length + 1];
730                 for (int j = 0; j < input_name_length; j++)
731                     input_name[j] = path_name[j];
732                 input_name[input_name_length] = U_NULL;
733             }
734 
735             // Reset the current directory on disk.
736             option.ResetCurrentDirectoryOnDisk(disk);
737             // Reset the real current directory...
738             option.SetMainCurrentDirectory();
739 #endif // WIN32_FILE_SYSTEM
740 
741             if (input_name_length > 0)
742             {
743                 NameSymbol* name_symbol = FindOrInsertName(path_name,
744                                                            path_name_length);
745 
746                 //
747                 // If a directory is specified more than once, ignore the
748                 // duplicates.
749                 //
750                 if (extdirs_set.IsElement(name_symbol))
751                     continue;
752 
753                 extdirs_set.AddElement(name_symbol);
754 
755                 //
756                 // Check whether or not the path points to a system
757                 // directory. TODO If not, should we print a warning ??
758                 //
759                 if (SystemIsDirectory(head))
760                 {
761 //FIXME: should be in platform.cpp??
762 #ifdef UNIX_FILE_SYSTEM
763 
764                     DIR* extdir = opendir(head);
765 
766                     if (extdir)
767                     {
768                         for (dirent* entry = readdir(extdir); entry; entry =
769                              readdir(extdir))
770                         {
771                             int entry_length = strlen(entry -> d_name);
772                             // + 1 for possible '/' between path and file.
773                             int fullpath_length = input_name_length +
774                                 entry_length + 1;
775                             char* ending = &(entry->d_name[entry_length-3]);
776                             // skip ., .., non-zip, and non-jar
777                             if (! strcmp(entry -> d_name, ".") ||
778                                 ! strcmp(entry -> d_name, "..") ||
779                                 (strcasecmp(ending, "zip") &&
780                                  strcasecmp(ending, "jar")))
781                             {
782                                 continue;
783                             }
784 
785                             char* extdir_entry = new char[fullpath_length + 1];
786                             // First put on path.
787                             strcpy(extdir_entry, head);
788 
789                             // Add '/' if it's not already there
790                             if (head[input_name_length - 1] != U_SLASH)
791                                 strcat(extdir_entry, U8S_SL);
792 
793                             // Then add the filename.
794                             strcat(extdir_entry, entry -> d_name);
795 
796                             wchar_t* extdir_entry_name =
797                                 new wchar_t[fullpath_length + 1];
798                             for (int i = 0; i < fullpath_length; ++i)
799                                 extdir_entry_name[i] = extdir_entry[i];
800 
801                             errno = 0;
802                             Zip* zipinfo = new Zip(*this, extdir_entry);
803                             if (! zipinfo -> IsValid())
804                             {
805                                 wchar_t* name =
806                                     new wchar_t[fullpath_length + 1];
807                                 for (int i = 0; i < fullpath_length; ++i)
808                                     name[i] = extdir_entry_name[i];
809                                 name[fullpath_length] = U_NULL;
810                                 if (errno)
811                                 {
812                                     const char* std_err = strerror(errno);
813                                     ErrorString err_str;
814                                     err_str << '"' << std_err << '"'
815                                             << " while trying to open "
816                                             << name;
817                                     general_io_warnings.Next() =
818                                         err_str.SafeArray();
819                                 }
820                                 else bad_zip_filenames.Next() = name;
821                             }
822 
823                             unnamed_package->directory.Next() =
824                                 zipinfo -> RootDirectory();
825 
826                             //
827                             // Make a new PathSymbol to add to the classpath.
828                             //
829                             NameSymbol* extdir_entry_symbol =
830                                 FindOrInsertName(extdir_entry_name,
831                                                  fullpath_length);
832                             PathSymbol* path_symbol =
833                                 classpath_table.InsertPathSymbol(extdir_entry_symbol,
834                                                                  zipinfo -> RootDirectory());
835                             path_symbol -> zipfile = zipinfo;
836                             classpath.Next() = path_symbol;
837                         }
838                         closedir(extdir);
839                     }
840 #elif defined(WIN32_FILE_SYSTEM)
841 
842                     // +2 for "/*" +1 for '\0'
843                     char* directory_name = new char[input_name_length + 3];
844                     strcpy(directory_name, head);
845                     if (directory_name[input_name_length - 1] != U_SLASH)
846                         directory_name[input_name_length++] = U_SLASH;
847                     directory_name[input_name_length++] = U_STAR;
848                     directory_name[input_name_length] = U_NULL;
849 
850                     WIN32_FIND_DATA entry;
851                     HANDLE file_handle = FindFirstFile(directory_name, &entry);
852                     if (file_handle != INVALID_HANDLE_VALUE)
853                     {
854                         do
855                         {
856                             int entry_length = strlen(entry.cFileName);
857                             // + 1 for possible '/' between path and file.
858                             int fullpath_length = input_name_length +
859                                 entry_length + 1;
860                             char* ending = &(entry.cFileName[entry_length-3]);
861                             // skip ., .., and not zip or jar
862                             if ((! strcmp(entry.cFileName, "." )) ||
863                                 (! strcmp(entry.cFileName, "..")) ||
864                                 ( strcasecmp(ending, "zip") &&
865                                   strcasecmp(ending, "jar")))
866                             {
867                                 continue;
868                             }
869 
870                             char* extdir_entry = new char[fullpath_length + 1];
871                             wchar_t* extdir_entry_name =
872                                 new wchar_t[fullpath_length + 1];
873                             // First put path
874                             strcpy(extdir_entry, head);
875 
876                             // If no slash, add slash before copying filename.
877                             if (head[input_name_length - 1] != U_SLASH)
878                             {
879                                 int path_length = input_name_length + 1;
880                                 strcat(extdir_entry, U8S_SL);
881 
882                                 for (int i = 0; i < entry_length; i++)
883                                 {
884                                     extdir_entry[i + path_length] =
885                                         entry.cFileName[i] == U_BACKSLASH
886                                         ? (char) U_SLASH : entry.cFileName[i];
887                                 }
888                             }
889                             else
890                             { // If it's there, just append filename.
891                                 for (int i = 0; i < entry_length; i++)
892                                 {
893                                     extdir_entry[i + input_name_length] =
894                                         entry.cFileName[i] == U_BACKSLASH
895                                         ? (char) U_SLASH : entry.cFileName[i];
896                                 }
897                             }
898 
899                             for (int i = 0; i < fullpath_length; ++i)
900                                 extdir_entry_name[i] = extdir_entry[i];
901 
902                             errno = 0;
903                             Zip* zipinfo = new Zip(*this, extdir_entry);
904                             if (! zipinfo -> IsValid())
905                             {
906                                 wchar_t* name =
907                                     new wchar_t[fullpath_length + 1];
908                                 for (int i = 0; i < fullpath_length; ++i)
909                                     name[i] = extdir_entry_name[i];
910                                 name[fullpath_length] = U_NULL;
911                                 if (errno)
912                                 {
913                                     const char* std_err = strerror(errno);
914                                     ErrorString err_str;
915                                     err_str << '"' << std_err << '"'
916                                             << " while trying to open "
917                                             << name;
918                                     general_io_warnings.Next() =
919                                         err_str.SafeArray();
920                                 }
921                                 else bad_zip_filenames.Next() = name;
922                             }
923 
924                             unnamed_package -> directory.Next() =
925                                 zipinfo -> RootDirectory();
926 
927                             NameSymbol* extdir_entry_symbol =
928                                 FindOrInsertName(extdir_entry_name,
929                                                  fullpath_length);
930                             //
931                             // Make a new PathSymbol to add to the classpath.
932                             //
933                             PathSymbol* path_symbol =
934                                 classpath_table.InsertPathSymbol(extdir_entry_symbol,
935                                                                  zipinfo -> RootDirectory());
936                             path_symbol -> zipfile = zipinfo;
937                             classpath.Next() = path_symbol;
938 
939                         } while (FindNextFile(file_handle, &entry));
940                         FindClose(file_handle);
941                     }
942 
943                     delete [] directory_name;
944 #endif // WIN32_FILE_SYSTEM
945                 }
946                 else
947                 {
948                     wchar_t* name = new wchar_t[input_name_length + 1];
949                     for (int i = 0; i < input_name_length; ++i)
950                         name[i] = input_name[i];
951                     name[input_name_length] = U_NULL;
952                     bad_dirnames.Next() = name;
953                 }
954             }
955         }
956 
957 #ifdef WIN32_FILE_SYSTEM
958         delete [] full_directory_name;
959         delete [] input_name;
960 #endif
961 
962         delete [] path_name;
963     }
964 }
965 
ProcessClassPath()966 void Control::ProcessClassPath()
967 {
968     if (option.classpath)
969     {
970         // The longest possible path name we can encounter.
971         int max_path_name_length = strlen(option.classpath) + 1;
972         wchar_t* path_name = new wchar_t[max_path_name_length + 1];
973 
974         wchar_t* input_name = NULL;
975 #ifdef WIN32_FILE_SYSTEM
976         char* full_directory_name = NULL;
977 #endif
978 
979         for (char* path = option.classpath, *path_tail = &path[strlen(path)];
980              path < path_tail; path++)
981         {
982 #ifdef WIN32_FILE_SYSTEM
983             delete [] full_directory_name;
984             delete [] input_name;
985 #endif
986             char* head;
987             for (head = path; path < path_tail && *path != PathSeparator();
988                  path++);
989 
990             // If a separator was encountered, replace it by \0 to terminate
991             // the string.
992             *path = U_NULL;
993             int input_name_length = path - head;
994 
995             int path_name_length = input_name_length;
996             for (int i = 0; i < path_name_length; i++)
997                 path_name[i] = head[i];
998             path_name[path_name_length] = U_NULL;
999 
1000 #ifdef UNIX_FILE_SYSTEM
1001 
1002             input_name = path_name;
1003 
1004 #elif defined(WIN32_FILE_SYSTEM)
1005 
1006             input_name = NULL;
1007             full_directory_name = NULL;
1008             char disk = (input_name_length >= 2 &&
1009                          Case::IsAsciiAlpha(head[0]) &&
1010                          head[1] == U_COLON ? head[0] : 0);
1011 
1012             //
1013             // Look for the directory. If it is found, update input_name and
1014             // head.
1015             //
1016             option.SaveCurrentDirectoryOnDisk(disk);
1017             if (SetCurrentDirectory(head))
1018             {
1019                 char tmp[1];
1020                 // First, get the right size.
1021                 DWORD directory_length = GetCurrentDirectory(0, tmp);
1022                 full_directory_name = new char[directory_length + 1];
1023                 DWORD length = GetCurrentDirectory(directory_length,
1024                                                    full_directory_name);
1025                 if (length <= directory_length)
1026                 {
1027                     for (char* ptr = full_directory_name; *ptr; ptr++)
1028                         *ptr = (*ptr != U_BACKSLASH
1029                                 ? *ptr : (char) U_SLASH); // turn '\' to '/'.
1030 
1031                     input_name_length = length;
1032                     input_name = new wchar_t[input_name_length + 1];
1033                     for (int k = 0; k < input_name_length; k++)
1034                         input_name[k] = full_directory_name[k];
1035                     input_name[input_name_length] = U_NULL;
1036                     head = full_directory_name;
1037                 }
1038             }
1039 
1040             //
1041             // Default input_name, in case we do not succeed in finding the
1042             // directory.
1043             //
1044             if (! input_name)
1045             {
1046                 input_name = new wchar_t[input_name_length + 1];
1047                 for (int j = 0; j < input_name_length; j++)
1048                     input_name[j] = path_name[j];
1049                 input_name[input_name_length] = U_NULL;
1050             }
1051 
1052             // Reset the current directory on disk.
1053             option.ResetCurrentDirectoryOnDisk(disk);
1054             // Reset the real current directory...
1055             option.SetMainCurrentDirectory();
1056 #endif // WIN32_FILE_SYSTEM
1057 
1058             if (input_name_length > 0)
1059             {
1060                 NameSymbol* name_symbol = FindOrInsertName(path_name,
1061                                                            path_name_length);
1062 
1063                 //
1064                 // If a directory is specified more than once, ignore the
1065                 // duplicates.
1066                 //
1067                 if (classpath_table.FindPathSymbol(name_symbol))
1068                 {
1069                     if (name_symbol == dot_name_symbol)
1070                     {
1071                         // The next index
1072                         dot_classpath_index = classpath.Length();
1073                         // Share the "." directory
1074                         classpath.Next() = classpath[0];
1075                         unnamed_package -> directory.Next() =
1076                             classpath[0] -> RootDirectory();
1077                     }
1078 
1079                     continue;
1080                 }
1081 
1082                 //
1083                 // Check whether or not the path points to a system directory.
1084                 // If not, assume it's a zip file.
1085                 //
1086                 if (SystemIsDirectory(head))
1087                 {
1088                     // This is the classpath so it's not sourcepath, pass false
1089                     DirectorySymbol* dot_directory =
1090                         ProcessSubdirectories(input_name, input_name_length,
1091                                               false);
1092                     unnamed_package -> directory.Next() = dot_directory;
1093                     classpath.Next() =
1094                         classpath_table.InsertPathSymbol(name_symbol,
1095                                                          dot_directory);
1096                 }
1097                 else
1098                 {
1099                     errno = 0;
1100                     Zip* zipinfo = new Zip(*this, head);
1101                     // If the zipfile is all screwed up, give up here !!!
1102                     if (! zipinfo -> IsValid())
1103                     {
1104                         wchar_t* name = new wchar_t[input_name_length + 1];
1105                         for (int i = 0; i < input_name_length; i++)
1106                             name[i] = input_name[i];
1107                         name[input_name_length] = U_NULL;
1108                         if (errno)
1109                         {
1110                             const char* std_err = strerror(errno);
1111                             ErrorString err_str;
1112                             err_str << '"' << std_err << '"'
1113                                     << " while trying to open " << name;
1114                             general_io_warnings.Next() = err_str.SafeArray();
1115                         }
1116                         else
1117                         {
1118                             wchar_t* tail = &name[input_name_length - 3];
1119                             if (Case::StringSegmentEqual(tail, US_zip, 3) ||
1120                                 Case::StringSegmentEqual(tail, US_jar, 3))
1121                             {
1122                                 bad_zip_filenames.Next() = name;
1123                             }
1124                             else bad_dirnames.Next() = name;
1125                         }
1126                     }
1127 
1128                     unnamed_package -> directory.Next() =
1129                         zipinfo -> RootDirectory();
1130 
1131                     //
1132                     // Create the new path symbol and update the class path
1133                     // with it.
1134                     //
1135                     PathSymbol* path_symbol =
1136                         classpath_table.InsertPathSymbol(name_symbol,
1137                                                          zipinfo -> RootDirectory());
1138                     path_symbol -> zipfile = zipinfo;
1139                     classpath.Next() = path_symbol;
1140                 }
1141             }
1142         }
1143 
1144 #ifdef WIN32_FILE_SYSTEM
1145         delete [] full_directory_name;
1146         delete [] input_name;
1147 #endif
1148 
1149         delete [] path_name;
1150     }
1151 }
1152 
ProcessSourcePath()1153 void Control::ProcessSourcePath()
1154 {
1155     if (option.sourcepath)
1156     {
1157         // The longest possible path name we can encounter.
1158         int max_path_name_length = strlen(option.sourcepath) + 1;
1159         wchar_t* path_name = new wchar_t[max_path_name_length + 1];
1160 
1161         wchar_t* input_name = NULL;
1162 #ifdef WIN32_FILE_SYSTEM
1163         char* full_directory_name = NULL;
1164 #endif
1165 
1166         for (char* path = option.sourcepath, *path_tail = &path[strlen(path)];
1167              path < path_tail; path++)
1168         {
1169 #ifdef WIN32_FILE_SYSTEM
1170             delete [] full_directory_name;
1171             delete [] input_name;
1172 #endif
1173             char* head;
1174             for (head = path; path < path_tail && *path != PathSeparator(); path++)
1175                 ;
1176             *path = U_NULL; // If a separator was encountered, replace it by \0 to terminate the string.
1177             int input_name_length = path - head;
1178 
1179             int path_name_length = input_name_length;
1180             for (int i = 0; i < path_name_length; i++)
1181                 path_name[i] = head[i];
1182             path_name[path_name_length] = U_NULL;
1183 
1184 #ifdef UNIX_FILE_SYSTEM
1185 
1186             input_name = path_name;
1187 
1188 #elif defined(WIN32_FILE_SYSTEM)
1189 
1190             input_name = NULL;
1191             full_directory_name = NULL;
1192             char disk = (input_name_length >= 2 && Case::IsAsciiAlpha(head[0]) && head[1] == U_COLON ? head[0] : 0);
1193 
1194             //
1195             // Look for the directory. If it is found, update input_name and head.
1196             //
1197             option.SaveCurrentDirectoryOnDisk(disk);
1198             if (SetCurrentDirectory(head))
1199             {
1200                 char tmp[1];
1201                 DWORD directory_length = GetCurrentDirectory(0, tmp); // first, get the right size
1202                 full_directory_name = new char[directory_length + 1];  // allocate the directory
1203                 DWORD length = GetCurrentDirectory(directory_length, full_directory_name);
1204                 if (length <= directory_length)
1205                 {
1206                     for (char* ptr = full_directory_name; *ptr; ptr++)
1207                         *ptr = (*ptr != U_BACKSLASH ? *ptr : (char) U_SLASH); // turn '\' to '/'.
1208 
1209                     input_name_length = length;
1210                     input_name = new wchar_t[input_name_length + 1];
1211                     for (int k = 0; k < input_name_length; k++)
1212                         input_name[k] = full_directory_name[k];
1213                     input_name[input_name_length] = U_NULL;
1214                     head = full_directory_name;
1215                 }
1216             }
1217 
1218             //
1219             // Default input_name, in case we do not succeed in finding the directory
1220             //
1221             if (! input_name)
1222             {
1223                 input_name = new wchar_t[input_name_length + 1];
1224                 for (int j = 0; j < input_name_length; j++)
1225                     input_name[j] = path_name[j];
1226                 input_name[input_name_length] = U_NULL;
1227             }
1228 
1229             // reset the current directory on disk
1230             option.ResetCurrentDirectoryOnDisk(disk);
1231             // reset the real current directory...
1232             option.SetMainCurrentDirectory();
1233 #endif // WIN32_FILE_SYSTEM
1234 
1235             //
1236             //
1237             //
1238             if (input_name_length > 0)
1239             {
1240                 NameSymbol* name_symbol = FindOrInsertName(path_name, path_name_length);
1241 
1242                 //
1243                 // If a directory is specified more than once, ignore the duplicates.
1244                 //
1245                 if (classpath_table.FindPathSymbol(name_symbol))
1246                 {
1247                     if (name_symbol == dot_name_symbol)
1248                     {
1249                         dot_classpath_index = classpath.Length(); // next index
1250                         classpath.Next() = classpath[0]; // share "." directory
1251                         unnamed_package -> directory.Next() =
1252                             classpath[0] -> RootDirectory();
1253                     }
1254                     continue;
1255                 }
1256 
1257                 //
1258                 // Check whether or not the path points to a system directory.
1259                 // If not, assume it's a zip file.
1260                 //
1261                 if (SystemIsDirectory(head))
1262                 {
1263                     // This is the sourcepath, so pass true
1264                     DirectorySymbol* dot_directory =
1265                         ProcessSubdirectories(input_name, input_name_length,
1266                                               true);
1267                     unnamed_package -> directory.Next() = dot_directory;
1268                     classpath.Next() =
1269                         classpath_table.InsertPathSymbol(name_symbol,
1270                                                          dot_directory);
1271                 }
1272                 else
1273                 {
1274                     // We don't process zip files as source directories
1275                     wchar_t* name = new wchar_t[input_name_length + 1];
1276                     for (int i = 0; i < input_name_length; i++)
1277                         name[i] = input_name[i];
1278                     name[input_name_length] = U_NULL;
1279                     bad_dirnames.Next() = name;
1280                 }
1281             }
1282         }
1283 
1284 #ifdef WIN32_FILE_SYSTEM
1285         delete [] full_directory_name;
1286         delete [] input_name;
1287 #endif
1288 
1289         delete [] path_name;
1290     }
1291 }
1292 
GetPrimitiveType(const char * name,char signature)1293 TypeSymbol* Control::GetPrimitiveType(const char* name, char signature)
1294 {
1295     NameSymbol* name_symbol = FindOrInsertSystemName(name);
1296     TypeSymbol* type = unnamed_package -> InsertSystemTypeSymbol(name_symbol);
1297     char sig[2] = { signature, U_NU };
1298     type -> SetSignature(Utf8_pool.FindOrInsert(sig, 1));
1299     type -> outermost_type = type;
1300     type -> SetOwner(unnamed_package);
1301     type -> SetACC_PUBLIC();
1302     type -> MarkPrimitive();
1303     return type;
1304 }
1305 
1306 
ProcessSystemInformation()1307 void Control::ProcessSystemInformation()
1308 {
1309     //
1310     // Add entry for system package
1311     //
1312     lang_package = ProcessPackage(US_java_SL_lang);
1313 
1314     //
1315     // Create an entry for each primitive type. Note that the type void is
1316     // treated as a primitive. We do not set up any subtyping relationships,
1317     // as that would violate the assumptions made elsewhere.
1318     //
1319     void_type = GetPrimitiveType("void", U_V);
1320     boolean_type = GetPrimitiveType("boolean", U_Z);
1321     byte_type = GetPrimitiveType("byte", U_B);
1322     char_type = GetPrimitiveType("char", U_C);
1323     short_type = GetPrimitiveType("short", U_S);
1324     int_type = GetPrimitiveType("int", U_I);
1325     long_type = GetPrimitiveType("long", U_J);
1326     float_type = GetPrimitiveType("float", U_F);
1327     double_type = GetPrimitiveType("double", U_D);
1328 }
1329 
1330 
1331 //
1332 // Find the given system type.
1333 //
ProcessSystemType(PackageSymbol * package,const char * name)1334 TypeSymbol* Control::ProcessSystemType(PackageSymbol* package,
1335                                        const char* name)
1336 {
1337     NameSymbol* name_symbol = FindOrInsertSystemName(name);
1338     TypeSymbol* type = package -> FindTypeSymbol(name_symbol);
1339 
1340     if (! type)
1341     {
1342         Control& control = *this;
1343         FileSymbol* file_symbol = GetFile(control, package, name_symbol);
1344         type = system_semantic -> ReadType(file_symbol, package,
1345                                            name_symbol, 0);
1346     }
1347     else if (type -> SourcePending())
1348         ProcessHeaders(type -> file_symbol);
1349     return type;
1350 }
1351 
1352 
1353 //
1354 // Find the given system method.
1355 //
ProcessSystemMethod(TypeSymbol * type,const char * name,const char * descriptor)1356 MethodSymbol* Control::ProcessSystemMethod(TypeSymbol* type,
1357                                            const char* name,
1358                                            const char* descriptor)
1359 {
1360     NameSymbol* name_symbol = FindOrInsertSystemName(name);
1361     MethodSymbol* method = NULL;
1362     if (! type -> Bad())
1363     {
1364         for (method = type -> FindMethodSymbol(name_symbol);
1365              method; method = method -> next_method)
1366         {
1367             if (! strcmp(descriptor, method -> SignatureString()))
1368                 break;
1369         }
1370     }
1371     if (! method)
1372     {
1373         if (! type -> Bad())
1374         {
1375             system_semantic ->
1376                 ReportSemError(SemanticError::NON_STANDARD_LIBRARY_TYPE,
1377                                BAD_TOKEN, type -> ContainingPackageName(),
1378                                type -> ExternalName());
1379             return NULL;
1380         }
1381         method = type -> InsertMethodSymbol(name_symbol);
1382         method -> SetType(no_type);
1383         method -> SetContainingType(type);
1384         method -> SetSignature(FindOrInsertSystemName(descriptor) ->
1385                                Utf8_literal);
1386     }
1387     return method;
1388 }
1389 
1390 
1391 //
1392 // Find the given system field.
1393 //
ProcessSystemField(TypeSymbol * type,const char * name,const char * descriptor)1394 VariableSymbol* Control::ProcessSystemField(TypeSymbol* type,
1395                                             const char* name,
1396                                             const char* descriptor)
1397 {
1398     NameSymbol* name_symbol = FindOrInsertSystemName(name);
1399     VariableSymbol* field = NULL;
1400     if (! type -> Bad())
1401     {
1402         field = type -> FindVariableSymbol(name_symbol);
1403         if (! field -> IsTyped())
1404             field -> ProcessVariableSignature(system_semantic, BAD_TOKEN);
1405         field -> MarkInitialized();
1406     }
1407     if (! field)
1408     {
1409         if (! type -> Bad())
1410         {
1411             system_semantic ->
1412                 ReportSemError(SemanticError::NON_STANDARD_LIBRARY_TYPE,
1413                                BAD_TOKEN, type -> ContainingPackageName(),
1414                                type -> ExternalName());
1415             return NULL;
1416         }
1417         field = type -> InsertVariableSymbol(name_symbol);
1418         field -> SetType(no_type);
1419         field -> SetOwner(type);
1420         field -> MarkInitialized();
1421         Utf8LiteralValue* utf8 =
1422             FindOrInsertSystemName(descriptor) -> Utf8_literal;
1423         field -> SetSignatureString(utf8 -> value, utf8 -> length);
1424     }
1425     return field;
1426 }
1427 
1428 
GetOutputDirectory(FileSymbol * file_symbol)1429 DirectorySymbol* Control::GetOutputDirectory(FileSymbol* file_symbol)
1430 {
1431     DirectorySymbol* directory_symbol;
1432 
1433     // A FileSymbol for a .class file has a NULL semantic.
1434     if (file_symbol -> semantic == NULL ||
1435         (file_symbol -> semantic -> control).option.directory == NULL) {
1436         directory_symbol = file_symbol -> directory_symbol;
1437     }
1438     else
1439     {
1440         Control& control = file_symbol -> semantic -> control;
1441         char* directory_prefix = control.option.directory;
1442         int directory_prefix_length = strlen(directory_prefix);
1443         int utf8_name_length =
1444             file_symbol -> package -> PackageNameLength() * 3;
1445         // +1 for slash
1446         int estimated_length = directory_prefix_length + utf8_name_length + 1;
1447 
1448         char* directory_name = new char[estimated_length + 1];
1449 
1450         strcpy(directory_name, directory_prefix);
1451 
1452         if (file_symbol -> package != control.unnamed_package)
1453         {
1454             // If there was a package declaration, then...
1455             if (directory_prefix[directory_prefix_length - 1] != U_SLASH)
1456                 strcat(directory_name, StringConstant::U8S_SL);
1457             char* utf8_name = new char[utf8_name_length + 1];
1458             ConvertUnicodeToUtf8(file_symbol -> package -> PackageName(),
1459                                  utf8_name);
1460             strcat(directory_name, utf8_name);
1461             delete [] utf8_name;
1462 
1463             if (! SystemIsDirectory(directory_name))
1464             {
1465                 // The directory does not yet exist.
1466                 for (char* ptr = &directory_name[directory_prefix_length + 1];
1467                      *ptr; ptr++)
1468                 {
1469                     // all the slashes in a package_name are forward slashes
1470                     if (*ptr == U_SLASH)
1471                     {
1472                         *ptr = U_NULL;
1473                         if (! SystemIsDirectory(directory_name))
1474                             SystemMkdir(directory_name);
1475                         *ptr = U_SLASH; // restore slash
1476                     }
1477                 }
1478                 SystemMkdir(directory_name);
1479             }
1480         }
1481 
1482         //
1483         // Read the directory and insert the directory symbol. Note that since
1484         // the original length computation was an estimate, we compute the real
1485         // length here.
1486         //
1487         int length = strlen(directory_name);
1488         wchar_t* name = new wchar_t[length + 1];
1489         for (int i = 0; i < length; i++)
1490             name[i] = directory_name[i];
1491         name[length] = U_NULL;
1492 
1493         // This is the output directory, so unless it's added to the
1494         // classpath, it won't matter whether it's a sourcedir or not.
1495         directory_symbol = control.ProcessSubdirectories(name, length, false);
1496 
1497         delete [] name;
1498         delete [] directory_name;
1499     }
1500     return directory_symbol;
1501 }
1502 
1503 
GetJavaFile(PackageSymbol * package,const NameSymbol * name_symbol)1504 FileSymbol* Control::GetJavaFile(PackageSymbol* package,
1505                                  const NameSymbol* name_symbol)
1506 {
1507     FileSymbol* file_symbol = NULL;
1508 
1509     //
1510     //
1511     //
1512     int length = name_symbol -> Utf8NameLength() +
1513         FileSymbol::java_suffix_length;
1514     char* full_filename = new char[length + 1]; // +1 for \0
1515     strcpy(full_filename, name_symbol -> Utf8Name());
1516     strcat(full_filename, FileSymbol::java_suffix);
1517 
1518     DirectoryEntry* entry = NULL;
1519     DirectorySymbol* directory_symbol = NULL;
1520     for (unsigned k = 0; k < package -> directory.Length(); k++)
1521     {
1522         directory_symbol = package -> directory[k];
1523         if ((entry = directory_symbol -> FindEntry(full_filename, length)))
1524             break;
1525     }
1526 
1527     if (entry)
1528     {
1529         PathSymbol* path_symbol = directory_symbol -> PathSym();
1530 
1531         file_symbol = directory_symbol -> FindFileSymbol(name_symbol);
1532         if (! ((file_symbol && file_symbol -> IsJava()) ||
1533                path_symbol -> IsZip()))
1534         {
1535             file_symbol = directory_symbol -> InsertFileSymbol(name_symbol);
1536 
1537             file_symbol -> directory_symbol = directory_symbol;
1538             file_symbol -> SetJava();
1539             file_symbol -> mtime = entry -> Mtime();
1540         }
1541     }
1542 
1543     delete [] full_filename;
1544     return file_symbol;
1545 }
1546 
1547 
GetFile(Control & control,PackageSymbol * package,const NameSymbol * name_symbol)1548 FileSymbol* Control::GetFile(Control& control, PackageSymbol* package,
1549                              const NameSymbol* name_symbol)
1550 {
1551     return control.option.old_classpath_search_order
1552         ? GetFileFirst(control, package, name_symbol)
1553         : GetFileBoth(control, package, name_symbol);
1554 }
1555 
GetFileBoth(Control & control,PackageSymbol * package,const NameSymbol * name_symbol)1556 FileSymbol* Control::GetFileBoth(Control& control, PackageSymbol* package,
1557                                  const NameSymbol* name_symbol)
1558 {
1559     FileSymbol* java_file_symbol = NULL;
1560     FileSymbol* class_file_symbol = NULL;
1561 
1562     //
1563     // calculate a length that is large enough...
1564     //
1565     int class_length = name_symbol -> Utf8NameLength() +
1566         FileSymbol::class_suffix_length;
1567     int java_length = name_symbol -> Utf8NameLength() +
1568         FileSymbol::java_suffix_length;
1569 
1570     char* class_name = new char[class_length + 1]; // +1 for \0
1571     strcpy(class_name, name_symbol -> Utf8Name());
1572     strcat(class_name, FileSymbol::class_suffix);
1573 
1574     char* java_name = new char[java_length + 1]; // +1 for \0
1575     strcpy(java_name, name_symbol -> Utf8Name());
1576     strcat(java_name, FileSymbol::java_suffix);
1577 
1578     for (unsigned k = 0; k < package -> directory.Length(); k++)
1579     {
1580         DirectorySymbol* directory_symbol = package -> directory[k];
1581         bool foundBothEntries = false;
1582         FileSymbol* file_symbol =
1583             directory_symbol -> FindFileSymbol(name_symbol);
1584         if (! file_symbol)
1585         {
1586             PathSymbol* path_symbol = directory_symbol -> PathSym();
1587             if (! path_symbol -> IsZip())
1588             {
1589                 DirectoryEntry* java_entry =
1590                     directory_symbol -> FindEntry(java_name, java_length),
1591                 *class_entry = (((! control.option.depend ||
1592                                   java_entry == NULL) &&
1593                                  (! directory_symbol -> IsSourceDirectory()))
1594                                 ? directory_symbol -> FindEntry(class_name,
1595                                                                 class_length)
1596                                 : (DirectoryEntry*) NULL);
1597 
1598                 if (java_entry || class_entry)
1599                 {
1600                     file_symbol =
1601                         directory_symbol -> InsertFileSymbol(name_symbol);
1602                     file_symbol -> directory_symbol = directory_symbol;
1603 
1604                     if (java_entry &&
1605                         (! class_entry ||
1606                          class_entry -> Mtime() < java_entry -> Mtime()))
1607                     {
1608                         file_symbol -> SetJava();
1609                         file_symbol -> mtime = java_entry -> Mtime();
1610                     }
1611                     else
1612                     {
1613                         if (java_entry)
1614                             file_symbol -> SetClass();
1615                         else file_symbol -> SetClassOnly();
1616                         file_symbol -> mtime = class_entry -> Mtime();
1617                     }
1618                 }
1619 
1620                 // Flag case where both .java and class found in same path.
1621                 if (java_entry && class_entry)
1622                     foundBothEntries = true;
1623             }
1624         }
1625 
1626         if (file_symbol)
1627         {
1628             // If no .java file seen yet, note this one.
1629             if (file_symbol -> IsJava() && ! java_file_symbol)
1630                 java_file_symbol = file_symbol;
1631             // If no .class file seen yet, note this one.
1632             else if (! class_file_symbol)
1633                 class_file_symbol = file_symbol;
1634 
1635 
1636             if (foundBothEntries == true ||
1637                 (java_file_symbol && class_file_symbol))
1638             {
1639                 // Both .java and .class seen, so no point in continuing the
1640                 // search.
1641                 break;
1642             }
1643         }
1644     }
1645 
1646     delete [] java_name;
1647     delete [] class_name;
1648 
1649     //
1650     // If both .java and .class seen, do a mod time check to decide which one
1651     // to deliver. Otherwise just return whichever kind we found, or NULL.
1652     //
1653     if (java_file_symbol &&
1654         (! class_file_symbol ||
1655          class_file_symbol -> mtime < java_file_symbol -> mtime))
1656     {
1657         return java_file_symbol;
1658     }
1659     return class_file_symbol;
1660 }
1661 
GetFileFirst(Control & control,PackageSymbol * package,const NameSymbol * name_symbol)1662 FileSymbol* Control::GetFileFirst(Control& control, PackageSymbol* package,
1663                                   const NameSymbol* name_symbol)
1664 {
1665     FileSymbol* file_symbol = NULL;
1666 
1667     //
1668     // calculate a length that is large enough...
1669     //
1670     int class_length = name_symbol -> Utf8NameLength() +
1671         FileSymbol::class_suffix_length;
1672     int java_length = name_symbol -> Utf8NameLength() +
1673         FileSymbol::java_suffix_length;
1674 
1675     char* class_name = new char[class_length + 1]; // +1 for \0
1676     strcpy(class_name, name_symbol -> Utf8Name());
1677     strcat(class_name, FileSymbol::class_suffix);
1678 
1679     char* java_name = new char[java_length + 1]; // +1 for \0
1680     strcpy(java_name, name_symbol -> Utf8Name());
1681     strcat(java_name, FileSymbol::java_suffix);
1682 
1683     for (unsigned k = 0; k < package -> directory.Length(); k++)
1684     {
1685         DirectorySymbol* directory_symbol = package -> directory[k];
1686         file_symbol = directory_symbol -> FindFileSymbol(name_symbol);
1687         if (file_symbol)
1688              break;
1689 
1690         PathSymbol* path_symbol = directory_symbol -> PathSym();
1691         if (! path_symbol -> IsZip())
1692         {
1693             DirectoryEntry* java_entry =
1694                 directory_symbol -> FindEntry(java_name, java_length);
1695             DirectoryEntry* class_entry = ((! control.option.depend ||
1696                                             (java_entry == NULL))
1697                                            ? directory_symbol -> FindEntry(class_name,
1698                                                                            class_length)
1699                                            : (DirectoryEntry*) NULL);
1700 
1701             if (java_entry || class_entry)
1702             {
1703                 file_symbol =
1704                     directory_symbol -> InsertFileSymbol(name_symbol);
1705                 file_symbol -> directory_symbol = directory_symbol;
1706 
1707                 if (java_entry &&
1708                     (! class_entry ||
1709                      class_entry -> Mtime() < java_entry -> Mtime()))
1710                 {
1711                     file_symbol -> SetJava();
1712                     file_symbol -> mtime = java_entry -> Mtime();
1713                 }
1714                 else
1715                 {
1716                     if (java_entry)
1717                          file_symbol -> SetClass();
1718                     else file_symbol -> SetClassOnly();
1719                     file_symbol -> mtime = class_entry -> Mtime();
1720                 }
1721                 break;
1722             }
1723         }
1724     }
1725 
1726     delete [] java_name;
1727     delete [] class_name;
1728     return file_symbol;
1729 }
1730 
1731 
1732 #ifdef HAVE_JIKES_NAMESPACE
1733 } // Close namespace Jikes block
1734 #endif
1735 
1736