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