356 xmlStream* xtty; |
356 xmlStream* xtty; |
357 outputStream* tty; |
357 outputStream* tty; |
358 outputStream* gclog_or_tty; |
358 outputStream* gclog_or_tty; |
359 extern Mutex* tty_lock; |
359 extern Mutex* tty_lock; |
360 |
360 |
|
361 #define EXTRACHARLEN 32 |
|
362 #define CURRENTAPPX ".current" |
|
363 #define FILENAMEBUFLEN 1024 |
|
364 // convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS |
|
365 char* get_datetime_string(char *buf, size_t len) { |
|
366 os::local_time_string(buf, len); |
|
367 int i = (int)strlen(buf); |
|
368 while (i-- >= 0) { |
|
369 if (buf[i] == ' ') buf[i] = '_'; |
|
370 else if (buf[i] == ':') buf[i] = '-'; |
|
371 } |
|
372 return buf; |
|
373 } |
|
374 |
|
375 static const char* make_log_name_internal(const char* log_name, const char* force_directory, |
|
376 int pid, const char* tms) { |
|
377 const char* basename = log_name; |
|
378 char file_sep = os::file_separator()[0]; |
|
379 const char* cp; |
|
380 char pid_text[32]; |
|
381 |
|
382 for (cp = log_name; *cp != '\0'; cp++) { |
|
383 if (*cp == '/' || *cp == file_sep) { |
|
384 basename = cp + 1; |
|
385 } |
|
386 } |
|
387 const char* nametail = log_name; |
|
388 // Compute buffer length |
|
389 size_t buffer_length; |
|
390 if (force_directory != NULL) { |
|
391 buffer_length = strlen(force_directory) + strlen(os::file_separator()) + |
|
392 strlen(basename) + 1; |
|
393 } else { |
|
394 buffer_length = strlen(log_name) + 1; |
|
395 } |
|
396 |
|
397 // const char* star = strchr(basename, '*'); |
|
398 const char* pts = strstr(basename, "%p"); |
|
399 int pid_pos = (pts == NULL) ? -1 : (pts - nametail); |
|
400 |
|
401 if (pid_pos >= 0) { |
|
402 jio_snprintf(pid_text, sizeof(pid_text), "pid%u", pid); |
|
403 buffer_length += strlen(pid_text); |
|
404 } |
|
405 |
|
406 pts = strstr(basename, "%t"); |
|
407 int tms_pos = (pts == NULL) ? -1 : (pts - nametail); |
|
408 if (tms_pos >= 0) { |
|
409 buffer_length += strlen(tms); |
|
410 } |
|
411 |
|
412 // Create big enough buffer. |
|
413 char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); |
|
414 |
|
415 strcpy(buf, ""); |
|
416 if (force_directory != NULL) { |
|
417 strcat(buf, force_directory); |
|
418 strcat(buf, os::file_separator()); |
|
419 nametail = basename; // completely skip directory prefix |
|
420 } |
|
421 |
|
422 // who is first, %p or %t? |
|
423 int first = -1, second = -1; |
|
424 const char *p1st = NULL; |
|
425 const char *p2nd = NULL; |
|
426 |
|
427 if (pid_pos >= 0 && tms_pos >= 0) { |
|
428 // contains both %p and %t |
|
429 if (pid_pos < tms_pos) { |
|
430 // case foo%pbar%tmonkey.log |
|
431 first = pid_pos; |
|
432 p1st = pid_text; |
|
433 second = tms_pos; |
|
434 p2nd = tms; |
|
435 } else { |
|
436 // case foo%tbar%pmonkey.log |
|
437 first = tms_pos; |
|
438 p1st = tms; |
|
439 second = pid_pos; |
|
440 p2nd = pid_text; |
|
441 } |
|
442 } else if (pid_pos >= 0) { |
|
443 // contains %p only |
|
444 first = pid_pos; |
|
445 p1st = pid_text; |
|
446 } else if (tms_pos >= 0) { |
|
447 // contains %t only |
|
448 first = tms_pos; |
|
449 p1st = tms; |
|
450 } |
|
451 |
|
452 int buf_pos = (int)strlen(buf); |
|
453 const char* tail = nametail; |
|
454 |
|
455 if (first >= 0) { |
|
456 tail = nametail + first + 2; |
|
457 strncpy(&buf[buf_pos], nametail, first); |
|
458 strcpy(&buf[buf_pos + first], p1st); |
|
459 buf_pos = (int)strlen(buf); |
|
460 if (second >= 0) { |
|
461 strncpy(&buf[buf_pos], tail, second - first - 2); |
|
462 strcpy(&buf[buf_pos + second - first - 2], p2nd); |
|
463 tail = nametail + second + 2; |
|
464 } |
|
465 } |
|
466 strcat(buf, tail); // append rest of name, or all of name |
|
467 return buf; |
|
468 } |
|
469 |
|
470 // log_name comes from -XX:LogFile=log_name or -Xloggc:log_name |
|
471 // in log_name, %p => pid1234 and |
|
472 // %t => YYYY-MM-DD_HH-MM-SS |
|
473 static const char* make_log_name(const char* log_name, const char* force_directory) { |
|
474 char timestr[32]; |
|
475 get_datetime_string(timestr, sizeof(timestr)); |
|
476 return make_log_name_internal(log_name, force_directory, os::current_process_id(), |
|
477 timestr); |
|
478 } |
|
479 |
|
480 #ifndef PRODUCT |
|
481 void test_loggc_filename() { |
|
482 int pid; |
|
483 char tms[32]; |
|
484 char i_result[FILENAMEBUFLEN]; |
|
485 const char* o_result; |
|
486 get_datetime_string(tms, sizeof(tms)); |
|
487 pid = os::current_process_id(); |
|
488 |
|
489 // test.log |
|
490 jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test.log", tms); |
|
491 o_result = make_log_name_internal("test.log", NULL, pid, tms); |
|
492 assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)"); |
|
493 FREE_C_HEAP_ARRAY(char, o_result, mtInternal); |
|
494 |
|
495 // test-%t-%p.log |
|
496 jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%s-pid%u.log", tms, pid); |
|
497 o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms); |
|
498 assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)"); |
|
499 FREE_C_HEAP_ARRAY(char, o_result, mtInternal); |
|
500 |
|
501 // test-%t%p.log |
|
502 jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%spid%u.log", tms, pid); |
|
503 o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms); |
|
504 assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)"); |
|
505 FREE_C_HEAP_ARRAY(char, o_result, mtInternal); |
|
506 |
|
507 // %p%t.log |
|
508 jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u%s.log", pid, tms); |
|
509 o_result = make_log_name_internal("%p%t.log", NULL, pid, tms); |
|
510 assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)"); |
|
511 FREE_C_HEAP_ARRAY(char, o_result, mtInternal); |
|
512 |
|
513 // %p-test.log |
|
514 jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u-test.log", pid); |
|
515 o_result = make_log_name_internal("%p-test.log", NULL, pid, tms); |
|
516 assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)"); |
|
517 FREE_C_HEAP_ARRAY(char, o_result, mtInternal); |
|
518 |
|
519 // %t.log |
|
520 jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "%s.log", tms); |
|
521 o_result = make_log_name_internal("%t.log", NULL, pid, tms); |
|
522 assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)"); |
|
523 FREE_C_HEAP_ARRAY(char, o_result, mtInternal); |
|
524 } |
|
525 #endif // PRODUCT |
|
526 |
361 fileStream::fileStream(const char* file_name) { |
527 fileStream::fileStream(const char* file_name) { |
362 _file = fopen(file_name, "w"); |
528 _file = fopen(file_name, "w"); |
363 _need_close = true; |
529 if (_file != NULL) { |
|
530 _need_close = true; |
|
531 } else { |
|
532 warning("Cannot open file %s due to %s\n", file_name, strerror(errno)); |
|
533 _need_close = false; |
|
534 } |
364 } |
535 } |
365 |
536 |
366 fileStream::fileStream(const char* file_name, const char* opentype) { |
537 fileStream::fileStream(const char* file_name, const char* opentype) { |
367 _file = fopen(file_name, opentype); |
538 _file = fopen(file_name, opentype); |
368 _need_close = true; |
539 if (_file != NULL) { |
|
540 _need_close = true; |
|
541 } else { |
|
542 warning("Cannot open file %s due to %s\n", file_name, strerror(errno)); |
|
543 _need_close = false; |
|
544 } |
369 } |
545 } |
370 |
546 |
371 void fileStream::write(const char* s, size_t len) { |
547 void fileStream::write(const char* s, size_t len) { |
372 if (_file != NULL) { |
548 if (_file != NULL) { |
373 // Make an unused local variable to avoid warning from gcc 4.x compiler. |
549 // Make an unused local variable to avoid warning from gcc 4.x compiler. |
424 size_t count = ::write(_fd, s, (int)len); |
600 size_t count = ::write(_fd, s, (int)len); |
425 } |
601 } |
426 update_position(s, len); |
602 update_position(s, len); |
427 } |
603 } |
428 |
604 |
429 rotatingFileStream::~rotatingFileStream() { |
605 // dump vm version, os version, platform info, build id, |
|
606 // memory usage and command line flags into header |
|
607 void gcLogFileStream::dump_loggc_header() { |
|
608 if (is_open()) { |
|
609 print_cr(Abstract_VM_Version::internal_vm_info_string()); |
|
610 os::print_memory_info(this); |
|
611 print("CommandLine flags: "); |
|
612 CommandLineFlags::printSetFlags(this); |
|
613 } |
|
614 } |
|
615 |
|
616 gcLogFileStream::~gcLogFileStream() { |
430 if (_file != NULL) { |
617 if (_file != NULL) { |
431 if (_need_close) fclose(_file); |
618 if (_need_close) fclose(_file); |
432 _file = NULL; |
619 _file = NULL; |
|
620 } |
|
621 if (_file_name != NULL) { |
433 FREE_C_HEAP_ARRAY(char, _file_name, mtInternal); |
622 FREE_C_HEAP_ARRAY(char, _file_name, mtInternal); |
434 _file_name = NULL; |
623 _file_name = NULL; |
435 } |
624 } |
436 } |
625 } |
437 |
626 |
438 rotatingFileStream::rotatingFileStream(const char* file_name) { |
627 gcLogFileStream::gcLogFileStream(const char* file_name) { |
439 _cur_file_num = 0; |
628 _cur_file_num = 0; |
440 _bytes_written = 0L; |
629 _bytes_written = 0L; |
441 _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); |
630 _file_name = make_log_name(file_name, NULL); |
442 jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); |
631 |
443 _file = fopen(_file_name, "w"); |
632 // gc log file rotation |
444 _need_close = true; |
633 if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) { |
445 } |
634 char tempbuf[FILENAMEBUFLEN]; |
446 |
635 jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num); |
447 rotatingFileStream::rotatingFileStream(const char* file_name, const char* opentype) { |
636 _file = fopen(tempbuf, "w"); |
448 _cur_file_num = 0; |
637 } else { |
449 _bytes_written = 0L; |
638 _file = fopen(_file_name, "w"); |
450 _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); |
639 } |
451 jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); |
640 if (_file != NULL) { |
452 _file = fopen(_file_name, opentype); |
641 _need_close = true; |
453 _need_close = true; |
642 dump_loggc_header(); |
454 } |
643 } else { |
455 |
644 warning("Cannot open file %s due to %s\n", _file_name, strerror(errno)); |
456 void rotatingFileStream::write(const char* s, size_t len) { |
645 _need_close = false; |
|
646 } |
|
647 } |
|
648 |
|
649 void gcLogFileStream::write(const char* s, size_t len) { |
457 if (_file != NULL) { |
650 if (_file != NULL) { |
458 size_t count = fwrite(s, 1, len, _file); |
651 size_t count = fwrite(s, 1, len, _file); |
459 _bytes_written += count; |
652 _bytes_written += count; |
460 } |
653 } |
461 update_position(s, len); |
654 update_position(s, len); |
482 #endif |
680 #endif |
483 if (NumberOfGCLogFiles == 1) { |
681 if (NumberOfGCLogFiles == 1) { |
484 // rotate in same file |
682 // rotate in same file |
485 rewind(); |
683 rewind(); |
486 _bytes_written = 0L; |
684 _bytes_written = 0L; |
|
685 jio_snprintf(time_msg, sizeof(time_msg), "File %s rotated at %s\n", |
|
686 _file_name, os::local_time_string((char *)time_str, sizeof(time_str))); |
|
687 write(time_msg, strlen(time_msg)); |
|
688 dump_loggc_header(); |
487 return; |
689 return; |
488 } |
690 } |
489 |
691 |
490 // rotate file in names file.0, file.1, file.2, ..., file.<MaxGCLogFileNumbers-1> |
692 #if defined(_WINDOWS) |
491 // close current file, rotate to next file |
693 #ifndef F_OK |
|
694 #define F_OK 0 |
|
695 #endif |
|
696 #endif // _WINDOWS |
|
697 |
|
698 // rotate file in names extended_filename.0, extended_filename.1, ..., |
|
699 // extended_filename.<NumberOfGCLogFiles - 1>. Current rotation file name will |
|
700 // have a form of extended_filename.<i>.current where i is the current rotation |
|
701 // file number. After it reaches max file size, the file will be saved and renamed |
|
702 // with .current removed from its tail. |
|
703 size_t filename_len = strlen(_file_name); |
492 if (_file != NULL) { |
704 if (_file != NULL) { |
493 _cur_file_num ++; |
705 jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d", |
494 if (_cur_file_num >= NumberOfGCLogFiles) _cur_file_num = 0; |
706 _file_name, _cur_file_num); |
495 jio_snprintf(_file_name, strlen(Arguments::gc_log_filename()) + 10, "%s.%d", |
707 jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX, |
496 Arguments::gc_log_filename(), _cur_file_num); |
708 _file_name, _cur_file_num); |
|
709 jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file has reached the" |
|
710 " maximum size. Saved as %s\n", |
|
711 os::local_time_string((char *)time_str, sizeof(time_str)), |
|
712 renamed_file_name); |
|
713 write(time_msg, strlen(time_msg)); |
|
714 |
497 fclose(_file); |
715 fclose(_file); |
498 _file = NULL; |
716 _file = NULL; |
499 } |
717 |
500 _file = fopen(_file_name, "w"); |
718 bool can_rename = true; |
|
719 if (access(current_file_name, F_OK) != 0) { |
|
720 // current file does not exist? |
|
721 warning("No source file exists, cannot rename\n"); |
|
722 can_rename = false; |
|
723 } |
|
724 if (can_rename) { |
|
725 if (access(renamed_file_name, F_OK) == 0) { |
|
726 if (remove(renamed_file_name) != 0) { |
|
727 warning("Could not delete existing file %s\n", renamed_file_name); |
|
728 can_rename = false; |
|
729 } |
|
730 } else { |
|
731 // file does not exist, ok to rename |
|
732 } |
|
733 } |
|
734 if (can_rename && rename(current_file_name, renamed_file_name) != 0) { |
|
735 warning("Could not rename %s to %s\n", _file_name, renamed_file_name); |
|
736 } |
|
737 } |
|
738 |
|
739 _cur_file_num++; |
|
740 if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0; |
|
741 jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX, |
|
742 _file_name, _cur_file_num); |
|
743 _file = fopen(current_file_name, "w"); |
|
744 |
501 if (_file != NULL) { |
745 if (_file != NULL) { |
502 _bytes_written = 0L; |
746 _bytes_written = 0L; |
503 _need_close = true; |
747 _need_close = true; |
|
748 // reuse current_file_name for time_msg |
|
749 jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, |
|
750 "%s.%d", _file_name, _cur_file_num); |
|
751 jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n", |
|
752 os::local_time_string((char *)time_str, sizeof(time_str)), |
|
753 current_file_name); |
|
754 write(time_msg, strlen(time_msg)); |
|
755 dump_loggc_header(); |
|
756 // remove the existing file |
|
757 if (access(current_file_name, F_OK) == 0) { |
|
758 if (remove(current_file_name) != 0) { |
|
759 warning("Could not delete existing file %s\n", current_file_name); |
|
760 } |
|
761 } |
504 } else { |
762 } else { |
505 tty->print_cr("failed to open rotation log file %s due to %s\n", |
763 warning("failed to open rotation log file %s due to %s\n" |
|
764 "Turned off GC log file rotation\n", |
506 _file_name, strerror(errno)); |
765 _file_name, strerror(errno)); |
507 _need_close = false; |
766 _need_close = false; |
|
767 FLAG_SET_DEFAULT(UseGCLogFileRotation, false); |
508 } |
768 } |
509 } |
769 } |
510 |
770 |
511 defaultStream* defaultStream::instance = NULL; |
771 defaultStream* defaultStream::instance = NULL; |
512 int defaultStream::_output_fd = 1; |
772 int defaultStream::_output_fd = 1; |
531 // if a VM error has been reported. |
791 // if a VM error has been reported. |
532 if (!_inited && !is_error_reported()) init(); |
792 if (!_inited && !is_error_reported()) init(); |
533 return _log_file != NULL; |
793 return _log_file != NULL; |
534 } |
794 } |
535 |
795 |
536 static const char* make_log_name(const char* log_name, const char* force_directory) { |
|
537 const char* basename = log_name; |
|
538 char file_sep = os::file_separator()[0]; |
|
539 const char* cp; |
|
540 for (cp = log_name; *cp != '\0'; cp++) { |
|
541 if (*cp == '/' || *cp == file_sep) { |
|
542 basename = cp+1; |
|
543 } |
|
544 } |
|
545 const char* nametail = log_name; |
|
546 |
|
547 // Compute buffer length |
|
548 size_t buffer_length; |
|
549 if (force_directory != NULL) { |
|
550 buffer_length = strlen(force_directory) + strlen(os::file_separator()) + |
|
551 strlen(basename) + 1; |
|
552 } else { |
|
553 buffer_length = strlen(log_name) + 1; |
|
554 } |
|
555 |
|
556 const char* star = strchr(basename, '*'); |
|
557 int star_pos = (star == NULL) ? -1 : (star - nametail); |
|
558 int skip = 1; |
|
559 if (star == NULL) { |
|
560 // Try %p |
|
561 star = strstr(basename, "%p"); |
|
562 if (star != NULL) { |
|
563 skip = 2; |
|
564 } |
|
565 } |
|
566 star_pos = (star == NULL) ? -1 : (star - nametail); |
|
567 |
|
568 char pid[32]; |
|
569 if (star_pos >= 0) { |
|
570 jio_snprintf(pid, sizeof(pid), "%u", os::current_process_id()); |
|
571 buffer_length += strlen(pid); |
|
572 } |
|
573 |
|
574 // Create big enough buffer. |
|
575 char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); |
|
576 |
|
577 strcpy(buf, ""); |
|
578 if (force_directory != NULL) { |
|
579 strcat(buf, force_directory); |
|
580 strcat(buf, os::file_separator()); |
|
581 nametail = basename; // completely skip directory prefix |
|
582 } |
|
583 |
|
584 if (star_pos >= 0) { |
|
585 // convert foo*bar.log or foo%pbar.log to foo123bar.log |
|
586 int buf_pos = (int) strlen(buf); |
|
587 strncpy(&buf[buf_pos], nametail, star_pos); |
|
588 strcpy(&buf[buf_pos + star_pos], pid); |
|
589 nametail += star_pos + skip; // skip prefix and pid format |
|
590 } |
|
591 |
|
592 strcat(buf, nametail); // append rest of name, or all of name |
|
593 return buf; |
|
594 } |
|
595 |
|
596 void defaultStream::init_log() { |
796 void defaultStream::init_log() { |
597 // %%% Need a MutexLocker? |
797 // %%% Need a MutexLocker? |
598 const char* log_name = LogFile != NULL ? LogFile : "hotspot.log"; |
798 const char* log_name = LogFile != NULL ? LogFile : "hotspot_%p.log"; |
599 const char* try_name = make_log_name(log_name, NULL); |
799 const char* try_name = make_log_name(log_name, NULL); |
600 fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); |
800 fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); |
601 if (!file->is_open()) { |
801 if (!file->is_open()) { |
602 // Try again to open the file. |
802 // Try again to open the file. |
603 char warnbuf[O_BUFLEN*2]; |
803 char warnbuf[O_BUFLEN*2]; |
604 jio_snprintf(warnbuf, sizeof(warnbuf), |
804 jio_snprintf(warnbuf, sizeof(warnbuf), |
605 "Warning: Cannot open log file: %s\n", try_name); |
805 "Warning: Cannot open log file: %s\n", try_name); |
606 // Note: This feature is for maintainer use only. No need for L10N. |
806 // Note: This feature is for maintainer use only. No need for L10N. |
607 jio_print(warnbuf); |
807 jio_print(warnbuf); |
608 FREE_C_HEAP_ARRAY(char, try_name, mtInternal); |
808 FREE_C_HEAP_ARRAY(char, try_name, mtInternal); |
609 try_name = make_log_name("hs_pid%p.log", os::get_temp_directory()); |
809 try_name = make_log_name(log_name, os::get_temp_directory()); |
610 jio_snprintf(warnbuf, sizeof(warnbuf), |
810 jio_snprintf(warnbuf, sizeof(warnbuf), |
611 "Warning: Forcing option -XX:LogFile=%s\n", try_name); |
811 "Warning: Forcing option -XX:LogFile=%s\n", try_name); |
612 jio_print(warnbuf); |
812 jio_print(warnbuf); |
613 delete file; |
813 delete file; |
614 file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); |
814 file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); |
615 FREE_C_HEAP_ARRAY(char, try_name, mtInternal); |
815 } |
616 } |
816 FREE_C_HEAP_ARRAY(char, try_name, mtInternal); |
|
817 |
617 if (file->is_open()) { |
818 if (file->is_open()) { |
618 _log_file = file; |
819 _log_file = file; |
619 xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file); |
820 xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file); |
620 _outer_xmlStream = xs; |
821 _outer_xmlStream = xs; |
621 if (this == tty) xtty = xs; |
822 if (this == tty) xtty = xs; |