232 |
234 |
233 enteringContext := dot := aContext. |
235 enteringContext := dot := aContext. |
234 nesting := 0. |
236 nesting := 0. |
235 c := aContext. |
237 c := aContext. |
236 [c notNil] whileTrue:[ |
238 [c notNil] whileTrue:[ |
237 c selector == #enter:mayProceed: ifTrue:[ |
239 c selector == #enter:mayProceed: ifTrue:[ |
238 nesting := nesting + 1. |
240 nesting := nesting + 1. |
239 ]. |
241 ]. |
240 c := c sender. |
242 c := c sender. |
241 ]. |
243 ]. |
242 |
244 |
243 stillHere := true. |
245 stillHere := true. |
244 [stillHere] whileTrue:[ |
246 [stillHere] whileTrue:[ |
245 AbortOperationRequest handle:[:ex | |
247 AbortOperationRequest handle:[:ex | |
246 '** Abort caught - back in previous debugLevel' errorPrintCR. |
248 '** Abort caught - back in previous debugLevel' errorPrintCR. |
247 ] do:[ |
249 ] do:[ |
248 Error handle:[:ex | |
250 Error handle:[:ex | |
249 StreamError handle:[:ex| |
251 StreamError handle:[:ex| |
250 "You won't see this probably - but you will see it when doing a syscall trace" |
252 "You won't see this probably - but you will see it when doing a syscall trace" |
251 'Error while processing error in MiniDebugger (Stdout closed?):' errorPrintCR. |
253 'Error while processing error in MiniDebugger (Stdout closed?):' errorPrintCR. |
252 ex description errorPrintCR. |
254 ex description errorPrintCR. |
253 OperatingSystem exit:10. |
255 OperatingSystem exit:10. |
254 ] do:[ |
256 ] do:[ |
255 'Error while executing MiniDebugger command: ' errorPrint. |
257 'Error while executing MiniDebugger command: ' errorPrint. |
256 ex description errorPrintCR. |
258 ex description errorPrintCR. |
257 yesNo := self getCommand:'- (i)gnore / (p)roceed / (d)ebug / b(acktrace) ? '. |
259 yesNo := self getCommand:'- (i)gnore / (p)roceed / (d)ebug / b(acktrace) ? '. |
258 yesNo == $d ifTrue:[ |
260 yesNo == $d ifTrue:[ |
259 MiniDebugger enterWithMessage:'Debugging debugger' mayProceed:true. |
261 MiniDebugger enterWithMessage:'Debugging debugger' mayProceed:true. |
260 ex proceed |
262 ex proceed |
261 ]. |
263 ]. |
262 yesNo == $p ifTrue:[ |
264 yesNo == $p ifTrue:[ |
263 ex proceed |
265 ex proceed |
264 ]. |
266 ]. |
265 yesNo == $b ifTrue:[ |
267 yesNo == $b ifTrue:[ |
266 ex suspendedContext fullPrintAll. |
268 ex suspendedContext fullPrintAll. |
267 ex proceed |
269 ex proceed |
268 ]. |
270 ]. |
269 ]. |
271 ]. |
270 ] do:[ |
272 ] do:[ |
271 [ |
273 [ |
272 leaveCmd := self commandLoop. |
274 leaveCmd := self commandLoop. |
273 ] valueUnpreemptively. |
275 ] valueUnpreemptively. |
274 ]. |
276 ]. |
275 ]. |
277 ]. |
276 |
278 |
277 (leaveCmd == $s) ifTrue: [ |
279 (leaveCmd == $s) ifTrue: [ |
278 self stepping. |
280 self stepping. |
279 ObjectMemory flushInlineCaches. |
281 ObjectMemory flushInlineCaches. |
280 ObjectMemory stepInterruptHandler:self. |
282 ObjectMemory stepInterruptHandler:self. |
281 stillHere := false. |
283 stillHere := false. |
282 StepInterruptPending := 1. |
284 StepInterruptPending := 1. |
283 InterruptPending := 1 |
285 InterruptPending := 1 |
284 ]. |
286 ]. |
285 (leaveCmd == $t) ifTrue: [ |
287 (leaveCmd == $t) ifTrue: [ |
286 traceBlock := [:where | where fullPrint]. |
288 traceBlock := [:where | where fullPrint]. |
287 ObjectMemory flushInlineCaches. |
289 ObjectMemory flushInlineCaches. |
288 ObjectMemory stepInterruptHandler:self. |
290 ObjectMemory stepInterruptHandler:self. |
289 stillHere := false. |
291 stillHere := false. |
290 StepInterruptPending := 1. |
292 StepInterruptPending := 1. |
291 InterruptPending := 1 |
293 InterruptPending := 1 |
292 ]. |
294 ]. |
293 (leaveCmd == $c) ifTrue: [ |
295 (leaveCmd == $c) ifTrue: [ |
294 traceBlock := nil. |
296 traceBlock := nil. |
295 ObjectMemory flushInlineCaches. |
297 ObjectMemory flushInlineCaches. |
296 ObjectMemory stepInterruptHandler:nil. |
298 ObjectMemory stepInterruptHandler:nil. |
297 stillHere := false. |
299 stillHere := false. |
298 stepping := false. |
300 stepping := false. |
299 tracing := false. |
301 tracing := false. |
300 StepInterruptPending := nil. |
302 StepInterruptPending := nil. |
301 InterruptPending := nil |
303 InterruptPending := nil |
302 ]. |
304 ]. |
303 (leaveCmd == $a) ifTrue: [ |
305 ((leaveCmd == $a) or:[(leaveCmd == $Y)]) ifTrue: [ |
304 "abort" |
306 "abort" |
305 traceBlock := nil. |
307 traceBlock := nil. |
306 ObjectMemory flushInlineCaches. |
308 ObjectMemory flushInlineCaches. |
307 ObjectMemory stepInterruptHandler:nil. |
309 ObjectMemory stepInterruptHandler:nil. |
308 stepping := false. |
310 stepping := false. |
309 tracing := false. |
311 tracing := false. |
310 StepInterruptPending := nil. |
312 StepInterruptPending := nil. |
311 InterruptPending := nil. |
313 InterruptPending := nil. |
312 self doAbort. |
314 self doAbort. |
313 stillHere := true. |
315 stillHere := true. |
314 "failed abort" |
316 "failed abort" |
315 ]. |
317 ]. |
316 ]. |
318 ]. |
317 enteringContext := dot := nil. |
319 enteringContext := dot := nil. |
318 ^ nil |
320 ^ nil |
319 |
321 |
320 "Modified (comment): / 29-09-2011 / 09:05:57 / cg" |
322 "Modified (comment): / 29-09-2011 / 09:05:57 / cg" |
572 return true, if command loop should be finished" |
574 return true, if command loop should be finished" |
573 |
575 |
574 |id proc bool| |
576 |id proc bool| |
575 |
577 |
576 commandArg notEmptyOrNil ifTrue:[ |
578 commandArg notEmptyOrNil ifTrue:[ |
577 id := Number readFrom:commandArg onError:nil. |
579 id := Number readFrom:commandArg onError:nil. |
578 id notNil ifTrue:[ |
580 id notNil ifTrue:[ |
579 proc := Process allSubInstances detect:[:p | p id == id] ifNone:nil. |
581 proc := Process allSubInstances detect:[:p | p id == id] ifNone:nil. |
580 proc == Processor activeProcess ifTrue:[ |
582 proc == Processor activeProcess ifTrue:[ |
581 id := proc := nil |
583 id := proc := nil |
582 ] |
584 ] |
583 ] ifFalse:[ |
585 ] ifFalse:[ |
584 commandArg = '-' ifTrue:[ |
586 commandArg = '-' ifTrue:[ |
585 bool := false |
587 bool := false |
586 ] ifFalse:[ |
588 ] ifFalse:[ |
587 commandArg = '+' ifTrue:[ |
589 commandArg = '+' ifTrue:[ |
588 bool := true |
590 bool := true |
589 ] |
591 ] |
590 ] |
592 ] |
591 ] |
593 ] |
592 ]. |
594 ]. |
593 |
595 |
594 (cmd == $w) ifTrue:[ |
596 (cmd == $w) ifTrue:[ |
595 proc notNil ifTrue:[ |
597 proc notNil ifTrue:[ |
596 '-------- walkback of process ' errorPrint. id errorPrint. ' -------' errorPrintCR. |
598 '-------- walkback of process ' errorPrint. id errorPrint. ' -------' errorPrintCR. |
597 self printBacktraceFrom:(proc suspendedContext) |
599 self printBacktraceFrom:(proc suspendedContext) |
598 ] ifFalse:[ |
600 ] ifFalse:[ |
599 id notNil ifTrue:[ |
601 id notNil ifTrue:[ |
600 'no process with id: ' errorPrint. id errorPrintCR. |
602 'no process with id: ' errorPrint. id errorPrintCR. |
601 ] ifFalse:[ |
603 ] ifFalse:[ |
602 '-------- walkback of current process -------' errorPrintCR. |
604 '-------- walkback of current process -------' errorPrintCR. |
603 self printBacktraceFrom:(self getContext) |
605 self printBacktraceFrom:(self getContext) |
604 ] |
606 ] |
605 ]. |
607 ]. |
606 ^ false |
608 ^ false |
607 ]. |
609 ]. |
608 |
610 |
609 (cmd == $b) ifTrue:[ |
611 (cmd == $b) ifTrue:[ |
610 proc notNil ifTrue:[ |
612 proc notNil ifTrue:[ |
611 '-------- VM walkback of process ' errorPrint. id errorPrint. ' -------' errorPrintCR. |
613 '-------- VM walkback of process ' errorPrint. id errorPrint. ' -------' errorPrintCR. |
612 ObjectMemory printStackBacktraceFrom:(proc suspendedContext) |
614 ObjectMemory printStackBacktraceFrom:(proc suspendedContext) |
613 ] ifFalse:[ |
615 ] ifFalse:[ |
614 id notNil ifTrue:[ |
616 id notNil ifTrue:[ |
615 'no process with id: ' errorPrint. id errorPrintCR. |
617 'no process with id: ' errorPrint. id errorPrintCR. |
616 ] ifFalse:[ |
618 ] ifFalse:[ |
617 '-------- VM walkback of current process -------' errorPrintCR. |
619 '-------- VM walkback of current process -------' errorPrintCR. |
618 ObjectMemory printStackBacktrace |
620 ObjectMemory printStackBacktrace |
619 ] |
621 ] |
620 ]. |
622 ]. |
621 ^ false |
623 ^ false |
622 ]. |
624 ]. |
623 |
625 |
624 (cmd == $S) ifTrue:[ |
626 (cmd == $S) ifTrue:[ |
625 'saving "crash.img"...' errorPrint. |
627 'saving "crash.img"...' errorPrint. |
626 ObjectMemory writeCrashImage. |
628 ObjectMemory writeCrashImage. |
627 'done.' errorPrintCR. |
629 'done.' errorPrintCR. |
628 ^ false |
630 ^ false |
629 ]. |
631 ]. |
630 (cmd == $C) ifTrue:[ |
632 (cmd == $C) ifTrue:[ |
631 |changesFilename| |
633 |changesFilename| |
632 |
634 |
633 changesFilename := Timestamp now |
635 changesFilename := Timestamp now |
634 printStringFormat:'changes_%(year)-%(month)-%(day)__%h:%m:%s.chg'. |
636 printStringFormat:'changes_%(year)-%(month)-%(day)__%h:%m:%s.chg'. |
635 OperatingSystem isMSWINDOWSlike ifTrue:[ changesFilename replaceAll:$: with:$_ ]. |
637 OperatingSystem isMSWINDOWSlike ifTrue:[ changesFilename replaceAll:$: with:$_ ]. |
636 |
638 |
637 ChangeSet current fileOutAs: changesFilename. |
639 ChangeSet current fileOutAs: changesFilename. |
638 ('saved session changes to "',changesFilename,'".') errorPrintCR. |
640 ('saved session changes to "',changesFilename,'".') errorPrintCR. |
639 ^ false |
641 ^ false |
640 ]. |
642 ]. |
641 |
643 |
642 (cmd == $B) ifTrue:[ |
644 (cmd == $B) ifTrue:[ |
643 self printAllBacktraces. |
645 self printAllBacktraces. |
644 ^ false |
646 ^ false |
645 ]. |
647 ]. |
646 |
648 |
647 (cmd == $P) ifTrue:[ |
649 (cmd == $P) ifTrue:[ |
648 self showProcesses:#all. |
650 self showProcesses:#all. |
649 ^ false |
651 ^ false |
650 ]. |
652 ]. |
651 (cmd == $p) ifTrue:[ |
653 (cmd == $p) ifTrue:[ |
652 self showProcesses:#live. |
654 self showProcesses:#live. |
653 ^ false |
655 ^ false |
654 ]. |
656 ]. |
655 |
657 |
656 (cmd == $r) ifTrue:[ |
658 (cmd == $r) ifTrue:[ |
657 dot receiver errorPrintCR. |
659 dot receiver errorPrintCR. |
658 ^ false |
660 ^ false |
659 ]. |
661 ]. |
660 |
662 |
661 (cmd == $i) ifTrue:[ |
663 (cmd == $i) ifTrue:[ |
662 (commandArg ? '') withoutSeparators notEmpty ifTrue:[ |
664 (commandArg ? '') withoutSeparators notEmpty ifTrue:[ |
663 MiniInspector openOn:(Parser evaluate:commandArg). |
665 MiniInspector openOn:(Parser evaluate:commandArg). |
664 ] ifFalse:[ |
666 ] ifFalse:[ |
665 MiniInspector openOn:(dot receiver). |
667 MiniInspector openOn:(dot receiver). |
666 ]. |
668 ]. |
667 ^ false |
669 ^ false |
668 ]. |
670 ]. |
669 |
671 |
670 (cmd == $I) ifTrue:[ |
672 (cmd == $I) ifTrue:[ |
671 self interpreterLoopWith:nil. |
673 self interpreterLoopWith:nil. |
672 ^ false |
674 ^ false |
673 ]. |
675 ]. |
674 (cmd == $E) ifTrue:[ |
676 (cmd == $E) ifTrue:[ |
675 Parser evaluate:commandArg. |
677 Parser evaluate:commandArg. |
676 ^ false |
678 ^ false |
677 ]. |
679 ]. |
678 (cmd == $e) ifTrue:[ |
680 (cmd == $e) ifTrue:[ |
679 (Parser evaluate:commandArg) errorPrintCR. |
681 (Parser evaluate:commandArg) errorPrintCR. |
680 ^ false |
682 ^ false |
681 ]. |
683 ]. |
682 |
684 |
683 (cmd == $c) ifTrue:[^ true]. |
685 (cmd == $c) ifTrue:[^ true]. |
684 (cmd == $s) ifTrue:[^ true]. |
686 (cmd == $s) ifTrue:[^ true]. |
685 (cmd == $t) ifTrue:[^ true]. |
687 (cmd == $t) ifTrue:[^ true]. |
686 (cmd == $a) ifTrue:[^ true]. |
688 (cmd == $a) ifTrue:[^ true]. |
687 |
689 |
688 (cmd == $u) ifTrue:[ |
690 (cmd == $u) ifTrue:[ |
689 stepping := false. |
691 stepping := false. |
690 tracing := false. |
692 tracing := false. |
691 Processor activeProcess vmTrace:false. |
693 Processor activeProcess vmTrace:false. |
692 ^ false |
694 ^ false |
693 ]. |
695 ]. |
694 |
696 |
695 (cmd == $h) ifTrue:[ |
697 (cmd == $h) ifTrue:[ |
696 (bool notNil) ifTrue:[ |
698 (bool notNil) ifTrue:[ |
697 Smalltalk ignoreHalt:bool not. |
699 Smalltalk ignoreHalt:bool not. |
698 ]. |
700 ]. |
699 'halts are ' errorPrint. (Smalltalk ignoreHalt ifTrue:['disabled'] ifFalse:['enabled']) errorPrintCR. |
701 'halts are ' errorPrint. (Smalltalk ignoreHalt ifTrue:['disabled'] ifFalse:['enabled']) errorPrintCR. |
700 ^ false |
702 ^ false |
701 ]. |
703 ]. |
702 |
704 |
703 (cmd == $R) ifTrue:[ |
705 (cmd == $R) ifTrue:[ |
704 proc notNil ifTrue:[ |
706 proc notNil ifTrue:[ |
705 proc resume. |
707 proc resume. |
706 ]. |
708 ]. |
707 ^ false |
709 ^ false |
708 ]. |
710 ]. |
709 |
711 |
710 (cmd == $T) ifTrue:[ |
712 (cmd == $T) ifTrue:[ |
711 proc notNil ifTrue:[ |
713 proc notNil ifTrue:[ |
712 proc terminate. |
714 proc terminate. |
713 ] ifFalse:[ |
715 ] ifFalse:[ |
714 id notNil ifTrue:[ |
716 id notNil ifTrue:[ |
715 'no process with id: ' errorPrint. id errorPrintCR. |
717 'no process with id: ' errorPrint. id errorPrintCR. |
716 ] ifFalse:[ |
718 ] ifFalse:[ |
717 Processor terminateActive |
719 Processor terminateActive |
718 ] |
720 ] |
719 ]. |
721 ]. |
720 ^ false |
722 ^ false |
721 ]. |
723 ]. |
722 |
724 |
723 (cmd == $W) ifTrue:[ |
725 (cmd == $W) ifTrue:[ |
724 proc notNil ifTrue:[ |
726 proc notNil ifTrue:[ |
725 'stopping process id: ' errorPrint. id errorPrintCR. |
727 'stopping process id: ' errorPrint. id errorPrintCR. |
726 proc stop. |
728 proc stop. |
727 ] ifFalse:[ |
729 ] ifFalse:[ |
728 'invalid process id: ' errorPrint. id errorPrintCR. |
730 'invalid process id: ' errorPrint. id errorPrintCR. |
729 ]. |
731 ]. |
730 ^ false |
732 ^ false |
731 ]. |
733 ]. |
732 |
734 |
733 (cmd == $a) ifTrue:[ |
735 (cmd == $a) ifTrue:[ |
734 "without id-arg, this is handled by caller" |
736 "without id-arg, this is handled by caller" |
735 proc notNil ifTrue:[ |
737 proc notNil ifTrue:[ |
736 'aborting process id: ' errorPrint. id errorPrintCR. |
738 'aborting process id: ' errorPrint. id errorPrintCR. |
737 proc interruptWith:[AbortOperationRequest raise] |
739 proc interruptWith:[AbortOperationRequest raise] |
738 ] ifFalse:[ |
740 ] ifFalse:[ |
739 'aborting' errorPrintCR. |
741 'aborting' errorPrintCR. |
740 ]. |
742 ]. |
741 ^ false |
743 ^ false |
742 ]. |
744 ]. |
743 |
745 |
744 (cmd == $Q) ifTrue:[ |
746 (cmd == $Q) ifTrue:[ |
745 proc notNil ifTrue:[ |
747 proc notNil ifTrue:[ |
746 proc terminateNoSignal. |
748 proc terminateNoSignal. |
747 ] ifFalse:[ |
749 ] ifFalse:[ |
748 id notNil ifTrue:[ |
750 id notNil ifTrue:[ |
749 'no process with id: ' errorPrint. id errorPrintCR. |
751 'no process with id: ' errorPrint. id errorPrintCR. |
750 ] ifFalse:[ |
752 ] ifFalse:[ |
751 Processor terminateActiveNoSignal |
753 Processor terminateActiveNoSignal |
752 ] |
754 ] |
753 ]. |
755 ]. |
754 ^ false |
756 ^ false |
755 ]. |
757 ]. |
756 |
758 |
757 (cmd == $g) ifTrue:[ |
759 (cmd == $g) ifTrue:[ |
758 self garbageCollectCommand:id. |
760 self garbageCollectCommand:id. |
759 ^ false |
761 ^ false |
760 ]. |
762 ]. |
761 |
763 |
762 (cmd == $U) ifTrue:[ |
764 (cmd == $U) ifTrue:[ |
763 MessageTracer unwrapAllMethods. |
765 MessageTracer unwrapAllMethods. |
764 ^ false |
766 ^ false |
765 ]. |
767 ]. |
766 (cmd == $D) ifTrue:[ |
768 (cmd == $D) ifTrue:[ |
767 Breakpoint disableAllBreakpoints. |
769 Breakpoint disableAllBreakpoints. |
768 ^ false |
770 ^ false |
769 ]. |
771 ]. |
770 (cmd == $X) ifTrue:[ |
772 (cmd == $X) ifTrue:[ |
771 Smalltalk fatalAbort. |
773 Smalltalk fatalAbort. |
772 "/ not reached |
774 "/ not reached |
773 ^ false |
775 ^ false |
774 ]. |
776 ]. |
775 (cmd == $x) ifTrue:[ |
777 (cmd == $x) ifTrue:[ |
776 OperatingSystem exit. |
778 OperatingSystem exit. |
777 "/ not reached |
779 "/ not reached |
778 ^ false |
780 ^ false |
|
781 ]. |
|
782 (cmd == $Y) ifTrue:[ |
|
783 Smalltalk openDisplay. |
|
784 NewLauncher open. |
|
785 ^ true |
779 ]. |
786 ]. |
780 |
787 |
781 (cmd == $.) ifTrue:[self printDot. ^ false ]. |
788 (cmd == $.) ifTrue:[self printDot. ^ false ]. |
782 (cmd == $l) ifTrue:[self printDotsMethodSource:false. ^ false ]. |
789 (cmd == $l) ifTrue:[self printDotsMethodSource:false. ^ false ]. |
783 (cmd == $L) ifTrue:[self printDotsMethodSource:true. ^ false ]. |
790 (cmd == $L) ifTrue:[self printDotsMethodSource:true. ^ false ]. |
784 (cmd == $-) ifTrue:[self moveDotUp. self printDot. ^ false ]. |
791 (cmd == $-) ifTrue:[self moveDotUp. self printDot. ^ false ]. |
785 (cmd == $+) ifTrue:[self moveDotDown. self printDot. ^ false ]. |
792 (cmd == $+) ifTrue:[self moveDotDown. self printDot. ^ false ]. |
786 (cmd == $?) ifTrue:[ |
793 (cmd == $?) ifTrue:[ |
787 commandArg notEmpty ifTrue:[ |
794 commandArg notEmpty ifTrue:[ |
788 self helpOn:commandArg. ^ false |
795 self helpOn:commandArg. ^ false |
789 ] |
796 ] |
790 ]. |
797 ]. |
791 |
798 |
792 "/ avoid usage print if return was typed ... |
799 "/ avoid usage print if return was typed ... |
793 ((cmd == Character return) |
800 ((cmd == Character return) |
794 or:[cmd == Character linefeed]) ifTrue:[^ false]. |
801 or:[cmd == Character linefeed]) ifTrue:[^ false]. |
1028 g 3 ...... collect all garbage, reclaim symbols and compress |
1035 g 3 ...... collect all garbage, reclaim symbols and compress |
1029 |
1036 |
1030 S ........ save snapshot into "crash.img" |
1037 S ........ save snapshot into "crash.img" |
1031 C ........ save session changes to a separate change file |
1038 C ........ save session changes to a separate change file |
1032 x ........ exit Smalltalk ("X" to exit with core dump) |
1039 x ........ exit Smalltalk ("X" to exit with core dump) |
|
1040 Y ........ reopen display, reopen launcher |
1033 |
1041 |
1034 . ........ print dot (the current context) |
1042 . ........ print dot (the current context) |
1035 - ........ move dot up (sender) |
1043 - ........ move dot up (sender) |
1036 + ........ move dot down (called context) |
1044 + ........ move dot down (called context) |
1037 l ........ list dot''s method source around PC ("L" for full list) |
1045 l ........ list dot''s method source around PC ("L" for full list) |
1038 |
1046 |
1039 r ........ receiver (in dot) printString |
1047 r ........ receiver (in dot) printString |
1040 i [expr] . inspect expression (or receiver in dot) |
1048 i [expr] . inspect expression (or receiver in dot) |
1041 I ........ interpreter (expression evaluator) |
1049 I ........ interpreter (expression evaluator) |
1042 e expr ... evaluate expression & print result ("E" to not print) |
1050 e expr ... evaluate expression & print result ("E" to not print) |
1043 ? c [p] .. help on class c (selectors matching p) |
1051 ? c [p] .. help on class c (selectors matching p) |
1044 ' errorPrintCR. |
1052 ' errorPrintCR. |
1045 |
1053 |
1046 (XWorkstation notNil and:[ Screen default isKindOf:XWorkstation ]) ifTrue:[ |
1054 (XWorkstation notNil and:[ Screen default isKindOf:XWorkstation ]) ifTrue:[ |
1047 ' To repair a broken X-Connection, enter an interpreter (enter "I") and evaluate: |
1055 ' To repair a broken X-Connection, enter an interpreter (enter "I") and evaluate: |
1048 Display := XWorkstation new. |
1056 Display := XWorkstation new. |