3582 maxLevels:15 |
3569 maxLevels:15 |
3583 noAutoload:false |
3570 noAutoload:false |
3584 packageTop:'../../..'. |
3571 packageTop:'../../..'. |
3585 ]. |
3572 ]. |
3586 |
3573 |
3587 "/ old scheme: look for a single file called 'abbrev.stc' in the |
|
3588 "/ include directory. This will vanish. |
|
3589 |
|
3590 "/ ('Smalltalk [info]: installing autoloaded classes from ''include/abbrev.stc''') infoPrintCR. |
|
3591 "/ self installAutoloadedClassesFrom:'include/abbrev.stc' |
|
3592 |
|
3593 " |
3574 " |
3594 Smalltalk installAutoloadedClasses |
3575 Smalltalk installAutoloadedClasses |
3595 " |
3576 " |
3596 |
3577 |
3597 "Created: / 14.2.1997 / 17:32:57 / cg" |
3578 "Created: / 14.2.1997 / 17:32:57 / cg" |
3598 "Modified: / 13.12.1999 / 11:56:50 / cg" |
3579 "Modified: / 13.12.1999 / 11:56:50 / cg" |
3599 ! |
3580 ! |
3600 |
3581 |
3601 dedClassesFrom:aPath |
3582 installAutoloadedClassesFrom:anAbbrevFilePath |
3602 rememberIn:dirsConsulted |
3583 "read the given abbreviation file; install all classes found there as |
3603 maxLevels:15 |
3584 autoloaded. This takes some time ..." |
3604 noAutoload:false |
3585 |
3605 packageTop:aPath. |
3586 |f s| |
3606 ] |
3587 |
3607 ]. |
3588 f := self getSystemFileName:anAbbrevFilePath. |
3608 p size == 0 ifTrue:[ |
3589 f isNil ifTrue:[f := self getPackageFileName:anAbbrevFilePath]. |
3609 ('Smalltalk [info]: installing autoloaded classes found under ''../../..''') infoPrintCR. |
3590 |
3610 self |
3591 f notNil ifTrue:[ |
3611 recursiveInstallAutoloadedClassesFrom:'../../..' |
3592 f := f asFilename. |
3612 rememberIn:dirsConsulted |
3593 f isDirectory ifTrue:[ |
3613 maxLevels:15 |
3594 f := f construct:'abbrev.stc' |
3614 noAutoload:false |
3595 ]. |
3615 packageTop:'../../..'. |
3596 [ |
3616 ]. |
3597 s := f readStream. |
3617 |
3598 self installAutoloadedClassesFromStream:s. |
3618 "/ old scheme: look for a single file called 'abbrev.stc' in the |
3599 s close. |
3619 "/ include directory. This will vanish. |
3600 ] on:FileStream openErrorSignal do:[:ex| "do nothing"]. |
3620 |
3601 ] |
3621 "/ ('Smalltalk [info]: installing autoloaded classes from ''include/abbrev.stc''') infoPrintCR. |
3602 |
3622 "/ self installAutoloadedClassesFrom:'include/abbrev.stc' |
3603 " |
3623 |
3604 Smalltalk installAutoloadedClassesFrom:'include/abbrev.stc' |
3624 " |
3605 " |
3625 Smalltalk installAutoloadedClasses |
3606 |
3626 " |
3607 "Modified: / 5.11.1998 / 15:10:51 / cg" |
3627 |
3608 ! |
3628 "Created: / 14.2.1997 / 17:32:57 / cg" |
3609 |
3629 "Modified: / 13.12.1999 / 11:56:50 / cg" |
3610 installAutoloadedClassesFromStream:anAbbrevFileStream |
3630 ! |
3611 "read the given abbreviation file; |
3631 |
3612 install all classes found there as autoloaded, and also update the |
3632 " |
3613 abbreviation (className-to-fileName mapping) table. |
3633 Smalltalk installAutoloadedClasses |
3614 This takes some time ..." |
3634 " |
3615 |
3635 |
3616 |s2 l clsName abbrev package cat numClassInstVars cls words w abbrevs oldAbbrev nameKey| |
3636 "Created: / 14.2.1997 / 17:32:57 / cg" |
3617 |
3637 "Modified: / 13.12.1999 / 11:56:50 / cg" |
3618 "/ on the fly, update the abbreviations |
3638 ! |
3619 |
3639 |
3620 CachedAbbreviations isNil ifTrue:[ |
3640 ' , cls name , ' in ' , (anAbbrevFileStream pathName)) infoPrintCR. |
3621 CachedAbbreviations := IdentityDictionary new. |
|
3622 ]. |
|
3623 abbrevs := CachedAbbreviations. |
|
3624 |
|
3625 KnownPackages isNil ifTrue:[ |
|
3626 KnownPackages := Set new. |
|
3627 ]. |
|
3628 |
|
3629 "/ yes, create any required nameSpace, without asking user. |
|
3630 Class createNameSpaceQuerySignal answer:true do:[ |
|
3631 |
|
3632 [anAbbrevFileStream atEnd] whileFalse:[ |
|
3633 l := anAbbrevFileStream nextLine withoutSeparators. |
|
3634 l notEmpty ifTrue:[ |
|
3635 "/ must do it manually, caring for quoted strings. |
|
3636 "/ words := line asCollectionOfWords. |
|
3637 |
|
3638 words := OrderedCollection new. |
|
3639 s2 := l readStream. |
|
3640 [s2 atEnd] whileFalse:[ |
|
3641 s2 skipSeparators. |
|
3642 s2 peek == $' ifTrue:[ |
|
3643 s2 next. |
|
3644 w := s2 upTo:$'. |
|
3645 s2 skipSeparators. |
|
3646 ] ifFalse:[ |
|
3647 w := s2 upToSeparator |
|
3648 ]. |
|
3649 words add:w |
|
3650 ]. |
|
3651 words size < 3 ifTrue:[ |
|
3652 'Smalltalk [warning]: bad abbrev entry' errorPrint. |
|
3653 anAbbrevFileStream isFileStream ifTrue:[ |
|
3654 ' (in ''' errorPrint. |
|
3655 anAbbrevFileStream pathName errorPrint. |
|
3656 ''')' errorPrint |
|
3657 ]. |
|
3658 ': ' errorPrint. l errorPrintCR |
|
3659 ] ifFalse:[ |
|
3660 clsName := (words at:1) asSymbol. |
|
3661 abbrev := (words at:2). |
|
3662 package := (words at:3) asSymbol. |
|
3663 cat := words at:4 ifAbsent:nil. |
|
3664 numClassInstVars := words at:5 ifAbsent:'0'. |
|
3665 numClassInstVars := Integer readFrom:numClassInstVars onError:[0]. |
|
3666 |
|
3667 "/ KnownPackages add:package. |
|
3668 |
|
3669 (cat size == 0) ifTrue:[ |
|
3670 cat := 'autoloaded' |
|
3671 ]. |
|
3672 |
|
3673 "/ on the fly, update the abbreviations |
|
3674 clsName ~= abbrev ifTrue:[ |
|
3675 nameKey := clsName asSymbol. |
|
3676 oldAbbrev := abbrevs at:nameKey ifAbsent:nil. |
|
3677 (oldAbbrev notNil and:[oldAbbrev ~= abbrev]) ifTrue:[ |
|
3678 StandAlone ifFalse:[ |
|
3679 ('Smalltalk [warning]: conflict for: ' , clsName , ' in ' , (anAbbrevFileStream pathName)) infoPrintCR. |
|
3680 ('Smalltalk [warning]: (' , oldAbbrev , ' <-> ' , abbrev , ')') infoPrintCR |
|
3681 ]. |
|
3682 ] ifFalse:[ |
|
3683 cls := self classNamed:abbrev. |
|
3684 cls notNil ifTrue:[ |
|
3685 cls name ~= clsName ifTrue:[ |
|
3686 "/ ok, there is a class named after this abbrev ... |
|
3687 "/ this is only a conflict, if the other class has no |
|
3688 "/ abbreviation (or the same). |
|
3689 (abbrevs at:(cls name asSymbol) ifAbsent:cls name) = abbrev ifTrue:[ |
|
3690 cls isNameSpace ifFalse:[ |
|
3691 package = cls package ifTrue:[ |
|
3692 StandAlone ifFalse:[ |
|
3693 ('Smalltalk [warning]: conflict for: ' , cls name , ' in ' , (anAbbrevFileStream pathName)) infoPrintCR. |
3641 ('Smalltalk [warning]: (' , clsName , ' -> ' , abbrev , ')') infoPrintCR |
3694 ('Smalltalk [warning]: (' , clsName , ' -> ' , abbrev , ')') infoPrintCR |
3642 ] |
3695 ] |
3643 ] |
3696 ] |
3644 ] |
3697 ] |
3645 ] |
3698 ] |
3706 LoadBinaries := false |
3733 LoadBinaries := false |
3707 |
3734 |
3708 "Modified: 10.1.1997 / 15:11:00 / cg" |
3735 "Modified: 10.1.1997 / 15:11:00 / cg" |
3709 ! |
3736 ! |
3710 |
3737 |
3711 ts := false |
3738 logDoits |
|
3739 "return true if doits should go into the changes file |
|
3740 as well as changes - by default, this is off, since |
|
3741 it can blow up the changes file enormously ... |
|
3742 " |
|
3743 |
|
3744 ^ LogDoits |
|
3745 |
|
3746 " |
|
3747 LogDoits := false |
3712 LogDoits := true |
3748 LogDoits := true |
3713 " |
3749 " |
3714 ! |
3750 ! |
3715 |
3751 |
3716 :[:ex| "ignore this file"]. |
3752 logDoits:aBoolean |
|
3753 "{ Pragma: +optSpace }" |
|
3754 |
|
3755 "turn on/off logging of doits in the changes file. |
|
3756 By default, this is off, since it can blow up the |
|
3757 changes file enormously ... |
|
3758 " |
|
3759 |
|
3760 LogDoits := aBoolean |
|
3761 |
|
3762 ! |
|
3763 |
|
3764 makeBytecodeMethods |
|
3765 "{ Pragma: +optSpace }" |
|
3766 |
|
3767 "walk over all methods and make each a bytecode method |
|
3768 iff it does not contain primitive C code. |
|
3769 Experimental and not yet used." |
|
3770 |
|
3771 Method allSubInstancesDo:[:aMethod | |
|
3772 |newMethod| |
|
3773 |
|
3774 aMethod hasPrimitiveCode ifFalse:[ |
|
3775 newMethod := aMethod asByteCodeMethod. |
|
3776 newMethod ~~ aMethod ifTrue:[ |
|
3777 aMethod becomeSameAs:newMethod |
|
3778 ] |
|
3779 ]. |
|
3780 ]. |
|
3781 |
|
3782 " |
|
3783 Smalltalk makeBytecodeMethods |
|
3784 " |
|
3785 |
|
3786 "Modified: 16.1.1997 / 01:25:58 / cg" |
|
3787 "Created: 17.10.1997 / 13:52:19 / cg" |
|
3788 ! |
|
3789 |
|
3790 recursiveInstallAutoloadedClassesFrom:aDirectory rememberIn:dirsConsulted maxLevels:maxLevels noAutoload:noAutoloadIn packageTop:packageTopPath |
|
3791 "read all abbrev.stc files from and under aDirectory |
|
3792 and install autoloaded classes. |
|
3793 If a file called NOAUTOLOAD is found, no classes there and below are installed as autoloaded |
|
3794 (however, the directories are searched for packages) |
|
3795 If a file called NOPACKAGES is found, no further searching is done in that directory or below." |
|
3796 |
|
3797 |abbrevStream dir noAutoloadHere dirName pkgName directoryContents| |
|
3798 |
|
3799 maxLevels == 0 ifTrue:[ |
|
3800 "/ 'Smalltalk [warning]: max directory nesting reached.' infoPrintCR. |
|
3801 ^ self |
|
3802 ]. |
|
3803 |
|
3804 dir := aDirectory asFilename. |
|
3805 |
|
3806 (dirsConsulted includes:dir pathName) ifTrue:[ |
|
3807 ^ self |
|
3808 ]. |
|
3809 dirsConsulted add:dir pathName. |
|
3810 |
|
3811 (dir construct:'NOPACKAGES') exists ifTrue:[ |
|
3812 ^ self. |
|
3813 ]. |
|
3814 (dir construct:'NOSUBAUTOLOAD') exists ifTrue:[ |
|
3815 ^ self. |
|
3816 ]. |
|
3817 noAutoloadHere := noAutoloadIn. |
|
3818 noAutoloadHere ifFalse:[ |
|
3819 (dir construct:'NOAUTOLOAD') exists ifTrue:[ |
|
3820 noAutoloadHere := true. |
|
3821 ]. |
|
3822 ] ifTrue:[ |
|
3823 (dir construct:'AUTOLOAD') exists ifTrue:[ |
|
3824 noAutoloadHere := false. |
|
3825 ]. |
|
3826 ]. |
|
3827 |
|
3828 ((dir construct:'loadAll') exists |
|
3829 or:[(dir construct:'abbrev.stc') exists |
|
3830 or:[(dir construct:(dir baseName , '.prj')) exists]]) ifTrue:[ |
|
3831 KnownPackages isNil ifTrue:[ |
|
3832 KnownPackages := Set new. |
|
3833 ]. |
|
3834 dirName := dir pathName. |
|
3835 pkgName := dirName copyFrom:(packageTopPath asFilename pathName) size + 1 + 1. |
|
3836 KnownPackages add:pkgName |
|
3837 ]. |
|
3838 |
|
3839 "/ |
|
3840 "/ suppress installation as autoloaded in this and everything |
|
3841 "/ below; however, still traverse the directories to find packages ... |
|
3842 "/ |
|
3843 noAutoloadHere ifFalse:[ |
|
3844 [ |
|
3845 abbrevStream := (dir construct:'abbrev.stc') asFilename readStream. |
|
3846 self installAutoloadedClassesFromStream:abbrevStream. |
|
3847 abbrevStream close. |
|
3848 ] on:FileStream openErrorSignal do:[:ex| "ignore this file"]. |
3717 ]. |
3849 ]. |
3718 |
3850 |
3719 [ |
3851 [ |
3720 directoryContents := dir directoryContents. |
3852 directoryContents := dir directoryContents. |
3721 ] on:FileStream openErrorSignal do:[:ex| |
3853 ] on:FileStream openErrorSignal do:[:ex| |
3759 " |
3891 " |
3760 Smalltalk installAutoloadedClasses |
3892 Smalltalk installAutoloadedClasses |
3761 " |
3893 " |
3762 ! |
3894 ! |
3763 |
3895 |
3764 e) ifFalse:[ |
3896 replaceReferencesTo:anObject with:newRef |
3765 ((dir baseName ~= 'stx') |
3897 |toAdd| |
3766 or:[ |
3898 |
3767 (#( |
3899 toAdd := OrderedCollection new. |
3768 'configurations' |
3900 self keysAndValuesDo:[:key :val | |
3769 'include' |
3901 (key == anObject) ifTrue:[ |
3770 'rules' |
|
3771 'stc' |
|
3772 'support' |
|
3773 ) includes:aFilename) not]) |
|
3774 ifTrue:[ |
|
3775 f := dir construct:aFilename. |
|
3776 f isDirectory ifTrue:[ |
|
3777 self |
|
3778 recursiveInstallAutoloadedClassesFrom:f |
|
3779 rememberIn:dirsConsulted |
|
3780 maxLevels:maxLevels-1 |
|
3781 noAutoload:noAutoloadHere |
|
3782 packageTop:packageTopPath. |
|
3783 ] |
|
3784 ] |
|
3785 ]. |
|
3786 ]. |
|
3787 |
|
3788 " |
|
3789 Smalltalk installAutoloadedClasses |
|
3790 " |
|
3791 ! |
|
3792 |
|
3793 True:[ |
|
3794 self shouldImplement. |
3902 self shouldImplement. |
3795 ]. |
3903 ]. |
3796 (val == anObject ) ifTrue:[ |
3904 (val == anObject ) ifTrue:[ |
3797 toAdd add:(key -> newRef) |
3905 toAdd add:(key -> newRef) |
3798 ]. |
3906 ]. |
3799 ]. |
3907 ]. |
3800 toAdd do:[:each | |
3908 toAdd do:[:each | |
3801 self at:(each key) put:(each value) |
3909 self at:(each key) put:(each value) |
3802 ]. |
3910 ]. |
3803 ! ! |
3911 ! |
3804 |
3912 |
3805 !Smalltalk class methodsFor:'system management-fileIn'! |
3913 saveEmergencyImage:aBoolean |
3806 |
3914 "set/clear the flag which controls if ST/X should save an |
3807 windowManager." |
3915 emergency image in case of a broken display connection. |
|
3916 The default is true. |
|
3917 This may be useful, if you work with an unsecure display |
|
3918 (serial line), and want to have a chance of proceeding after |
|
3919 a crash. In multiheaded applications, this only affects |
|
3920 crashes of the master Display connection (the initial connection); |
|
3921 errors on other displays are reported to the views and treated |
|
3922 like window destroy from the windowManager." |
3808 |
3923 |
3809 SaveEmergencyImage := aBoolean |
3924 SaveEmergencyImage := aBoolean |
3810 |
3925 |
3811 "Modified: / 24.10.1997 / 18:22:26 / cg" |
3926 "Modified: / 24.10.1997 / 18:22:26 / cg" |
3812 ! |
3927 ! |
3813 |
3928 |
3814 in SystemOrganizer for more info." |
3929 systemOrganization |
|
3930 "for partial ST80 compatibility; |
|
3931 In ST80, Smalltalk organization returns a systemOrganizer, which |
|
3932 keeps track of class-categories, while all classes return a classOrganizer |
|
3933 from #organization, which keeps track of method categories of that class. |
|
3934 Since in ST/X, Smalltalk is a class, there is now a conflict. |
|
3935 To make a workaround possible, use #systemOrganization when porting |
|
3936 VW apps to ST/X to get the class-categories. |
|
3937 Read the documentation in SystemOrganizer for more info." |
3815 |
3938 |
3816 ^ SystemOrganizer for:nil |
3939 ^ SystemOrganizer for:nil |
3817 |
3940 |
3818 "Created: / 20.6.1998 / 12:24:02 / cg" |
3941 "Created: / 20.6.1998 / 12:24:02 / cg" |
3819 "Modified: / 20.6.1998 / 12:41:34 / cg" |
3942 "Modified: / 20.6.1998 / 12:41:34 / cg" |
3820 ! |
3943 ! ! |
3821 |
3944 |
3822 This method can load almost anything which makes sense: |
3945 !Smalltalk class methodsFor:'system management-fileIn'! |
|
3946 |
|
3947 fileIn:aFileName |
|
3948 "read in the named file - look for it in some standard places; |
|
3949 return true if ok, false if failed. |
|
3950 This method can load almost anything which makes sense: |
3823 .st - source files |
3951 .st - source files |
3824 .cls - binary smalltalk bytecode files |
3952 .cls - binary smalltalk bytecode files |
3825 .so - binary compiled machine code class libraries |
3953 .so - binary compiled machine code class libraries |
3826 [.class - java bytecode -- soon to come]" |
3954 [.class - java bytecode -- soon to come]" |
3827 |
3955 |
3834 " |
3962 " |
3835 |
3963 |
3836 "Created: 28.10.1995 / 17:06:28 / cg" |
3964 "Created: 28.10.1995 / 17:06:28 / cg" |
3837 ! |
3965 ! |
3838 |
3966 |
3839 ^ false]. |
3967 fileIn:aFileName inPackage:aPackageID |
|
3968 "read in the named file in a packages directory." |
|
3969 |
|
3970 |dir| |
|
3971 |
|
3972 dir := self getPackageDirectoryForPackage:aPackageID. |
|
3973 dir isNil ifTrue:[^ false]. |
3840 |
3974 |
3841 dir := dir asFilename. |
3975 dir := dir asFilename. |
3842 ^ (self fileIn:(dir construct:aFileName)) |
3976 ^ (self fileIn:(dir construct:aFileName)) |
3843 or:[ self fileIn:((dir construct:'source') construct:aFileName) ] |
3977 or:[ self fileIn:((dir construct:'source') construct:aFileName) ] |
3844 ! |
3978 ! |
3845 |
3979 |
3846 acToe.st' lazy:true |
3980 fileIn:aFileName lazy:lazy |
|
3981 "read in the named file - look for it in some standard places; |
|
3982 return true if ok, false if failed. |
|
3983 If lazy is true, no code is generated for methods, instead stubs |
|
3984 are created which compile themself when first executed. This allows |
|
3985 for much faster fileIn (but slows down the first execution later). |
|
3986 Since no syntax checks are done when doing lazy fileIn, use this only for |
|
3987 code which is known to be syntactically correct." |
|
3988 |
|
3989 ^ self fileIn:aFileName lazy:lazy silent:nil logged:false |
|
3990 |
|
3991 " |
|
3992 Smalltalk fileIn:'source/TicTacToe.st' lazy:true |
3847 " |
3993 " |
3848 |
3994 |
3849 "Created: 28.10.1995 / 17:06:36 / cg" |
3995 "Created: 28.10.1995 / 17:06:36 / cg" |
3850 ! |
3996 ! |
3851 |
3997 |
3852 mFileStreamFor:fileNameString. |
3998 fileIn:aFileName lazy:lazy silent:silent |
|
3999 "read in the named file - look for it in some standard places; |
|
4000 return true if ok, false if failed. |
|
4001 If lazy is true, no code is generated for methods, instead stubs |
|
4002 are created which compile themself when first executed. This allows |
|
4003 for much faster fileIn (but slows down the first execution later). |
|
4004 Since no syntax checks are done when doing lazy fileIn, use this only for |
|
4005 code which is known to be syntactically correct. |
|
4006 If silent is true, no compiler messages are output to the transcript. |
|
4007 Giving nil for silent/lazy will use the current settings." |
|
4008 |
|
4009 ^ self fileIn:aFileName lazy:lazy silent:silent logged:false |
|
4010 |
|
4011 "Created: 28.10.1995 / 17:06:41 / cg" |
|
4012 ! |
|
4013 |
|
4014 fileIn:aFileNameOrString lazy:lazy silent:silent logged:logged |
|
4015 "read in the named file - look for it in some standard places; |
|
4016 return true if ok, false if failed. |
|
4017 If lazy is true, no code is generated for methods, instead stubs |
|
4018 are created which compile themself when first executed. This allows |
|
4019 for much faster fileIn (but slows down the first execution later). |
|
4020 Since no syntax checks are done when doing lazy fileIn, use this only for |
|
4021 code which is known to be syntactically correct. |
|
4022 If silent is true, no compiler messages are output to the transcript. |
|
4023 Giving nil for silent/lazy will use the current settings. |
|
4024 This method can load almost anything which makes sense: |
|
4025 .st - source files |
|
4026 .cls - binary smalltalk bytecode files |
|
4027 .so - binary compiled machine code class libraries |
|
4028 [.class - java bytecode -- soon to come]" |
|
4029 |
|
4030 |fileNameString aStream path morePath bos| |
|
4031 |
|
4032 fileNameString := aFileNameOrString asString. |
|
4033 |
|
4034 " |
|
4035 an object or shared object ? |
|
4036 " |
|
4037 (ObjectFileLoader notNil |
|
4038 and:[ObjectFileLoader hasValidBinaryExtension:fileNameString]) ifTrue:[ |
|
4039 "/ LoadBinaries ifFalse:[^ false]. |
|
4040 path := self getBinaryFileName:fileNameString. |
|
4041 path isNil ifTrue:[ |
|
4042 path := self getSystemFileName:fileNameString. |
|
4043 ]. |
|
4044 path isNil ifTrue:[^ false]. |
|
4045 ^ (ObjectFileLoader loadObjectFile:path) notNil |
|
4046 ]. |
|
4047 |
|
4048 (fileNameString asFilename hasSuffix:'cls') ifTrue:[ |
|
4049 BinaryObjectStorage notNil ifTrue:[ |
|
4050 aStream := self systemFileStreamFor:fileNameString. |
|
4051 "/ path := self getBinaryFileName:fileNameString. |
|
4052 "/ path isNil ifTrue:[^ false]. |
|
4053 "/ aStream := path asFilename readStream. |
|
4054 aStream notNil ifTrue:[ |
|
4055 aStream binary. |
|
4056 bos := BinaryObjectStorage onOld:aStream. |
|
4057 bos next. |
|
4058 bos close. |
|
4059 ^ true |
|
4060 ]. |
|
4061 ^ false |
|
4062 ] |
|
4063 ]. |
|
4064 |
|
4065 (fileNameString startsWith:'source/') ifTrue:[ |
|
4066 aStream := self sourceFileStreamFor:(fileNameString copyFrom:8) |
|
4067 ] ifFalse:[ |
|
4068 (fileNameString startsWith:'fileIn/') ifTrue:[ |
|
4069 aStream := self fileInFileStreamFor:(fileNameString copyFrom:8) |
|
4070 ] ifFalse:[ |
|
4071 aStream := self systemFileStreamFor:fileNameString. |
3853 aStream isNil ifTrue:[ |
4072 aStream isNil ifTrue:[ |
3854 OperatingSystem isUNIXlike ifTrue:[ |
4073 OperatingSystem isUNIXlike ifTrue:[ |
3855 (fileNameString startsWith:'/') ifFalse:[ |
4074 (fileNameString startsWith:'/') ifFalse:[ |
3856 aStream := self systemFileStreamFor:('lib/' , fileNameString). |
4075 aStream := self systemFileStreamFor:('lib/' , fileNameString). |
3857 ] |
4076 ] |
3989 silent:beSilent |
4221 silent:beSilent |
3990 |
4222 |
3991 "Modified: / 9.1.1998 / 14:42:28 / cg" |
4223 "Modified: / 9.1.1998 / 14:42:28 / cg" |
3992 ! |
4224 ! |
3993 |
4225 |
3994 ]. |
4226 fileInClass:aClassName package:package initialize:doInit lazy:loadLazy silent:beSilent |
|
4227 "find a source/object file for aClassName and -if found - load it. |
|
4228 This is the workhorse for autoloading. |
|
4229 Search is in some standard places, trying driver-file (.ld), object-file (.so / .o) and |
|
4230 finally source file (.st), in that order. |
|
4231 The file is first searched for using the class name, then the abbreviated name. |
|
4232 The argument doInit controlls if the class should be sent a #initialize after the |
|
4233 load; loadLazy tells if it should be loaded lazyly. beSilent tells if the compiler |
|
4234 should not send notes to the transcript; it can be true, false or nil, where |
|
4235 nil uses the value from SilentLoading." |
|
4236 |
|
4237 |shortName longName libName newClass ok wasLazy wasSilent sharedLibExtension inStream mgr |
|
4238 fn packageDir packageFile bos| |
|
4239 |
|
4240 wasLazy := Compiler compileLazy:loadLazy. |
|
4241 beSilent notNil ifTrue:[ |
|
4242 wasSilent := self silentLoading:beSilent. |
|
4243 ]. |
|
4244 |
|
4245 longName := Smalltalk fileNameForClass:aClassName. |
|
4246 longName := longName copyReplaceAll:$: with:$_. |
|
4247 |
|
4248 [ |
|
4249 Class withoutUpdatingChangesDo: |
|
4250 [ |
|
4251 |zarFn zar entry| |
|
4252 |
|
4253 ok := false. |
|
4254 |
|
4255 shortName := self fileNameForClass:aClassName. |
|
4256 package notNil ifTrue:[ |
|
4257 packageDir := package asString. |
|
4258 packageDir := packageDir copyReplaceAll:$: with:$/. |
|
4259 ]. |
|
4260 |
|
4261 Class packageQuerySignal answer:package |
|
4262 do:[ |
|
4263 |
|
4264 " |
|
4265 first, look for a loader-driver file (in fileIn/xxx.ld) |
|
4266 " |
|
4267 (ok := self fileIn:('fileIn/' , shortName , '.ld') lazy:loadLazy silent:beSilent) |
|
4268 ifFalse:[ |
|
4269 " |
|
4270 try abbreviated driver-file (in fileIn/xxx.ld) |
|
4271 " |
|
4272 shortName ~= aClassName ifTrue:[ |
|
4273 ok := self fileIn:('fileIn/' , longName , '.ld') lazy:loadLazy silent:beSilent |
|
4274 ]. |
|
4275 ok ifFalse:[ |
|
4276 " |
|
4277 then, if dynamic linking is available, |
|
4278 " |
|
4279 (LoadBinaries and:[ObjectFileLoader notNil]) ifTrue:[ |
|
4280 sharedLibExtension := ObjectFileLoader sharedLibraryExtension. |
|
4281 |
|
4282 " |
|
4283 first look for a class packages shared binary in binary/xxx.o |
|
4284 " |
|
4285 libName := self libraryFileNameOfClass:aClassName. |
|
4286 libName notNil ifTrue:[ |
|
4287 (ok := self fileInClass:aClassName fromObject:(libName, sharedLibExtension)) |
|
4288 ifFalse:[ |
|
4289 sharedLibExtension ~= '.o' ifTrue:[ |
|
4290 ok := self fileInClass:aClassName fromObject:(libName, '.o') |
|
4291 ] |
|
4292 ]. |
|
4293 ]. |
|
4294 |
|
4295 " |
|
4296 then, look for a shared binary in binary/xxx.o |
|
4297 " |
|
4298 ok ifFalse:[ |
|
4299 (ok := self fileInClass:aClassName fromObject:(shortName, sharedLibExtension)) |
|
4300 ifFalse:[ |
|
4301 sharedLibExtension ~= '.o' ifTrue:[ |
|
4302 ok := self fileInClass:aClassName fromObject:(shortName, '.o') |
|
4303 ]. |
|
4304 ok ifFalse:[ |
|
4305 shortName ~= aClassName ifTrue:[ |
|
4306 (ok := self fileInClass:aClassName fromObject:(longName, sharedLibExtension)) |
|
4307 ifFalse:[ |
|
4308 sharedLibExtension ~= '.o' ifTrue:[ |
|
4309 ok := self fileInClass:aClassName fromObject:(longName, '.o') |
|
4310 ] |
|
4311 ] |
|
4312 ]. |
|
4313 ]. |
|
4314 ]. |
|
4315 ]. |
|
4316 ]. |
|
4317 |
|
4318 " |
|
4319 if that did not work, look for a compiled-bytecode file ... |
|
4320 " |
|
4321 ok ifFalse:[ |
|
4322 (ok := self fileIn:(shortName , '.cls') lazy:loadLazy silent:beSilent) |
|
4323 ifFalse:[ |
|
4324 shortName ~= aClassName ifTrue:[ |
|
4325 ok := self fileIn:(longName , '.cls') lazy:loadLazy silent:beSilent |
|
4326 ] |
|
4327 ] |
|
4328 ]. |
|
4329 " |
|
4330 if that did not work, and the classes package is known, |
|
4331 look for an st-cls file |
|
4332 in a package subdir of the source-directory ... |
|
4333 " |
|
4334 ok ifFalse:[ |
|
4335 (packageDir notNil and:[BinaryObjectStorage notNil]) ifTrue:[ |
|
4336 packageFile := self getPackageFileName:(packageDir , '/classes/' , shortName , '.cls'). |
|
4337 packageFile isNil ifTrue:[ |
|
4338 packageFile := (packageDir , '/classes/' , shortName , '.cls'). |
|
4339 ]. |
|
4340 (ok := self fileIn:packageFile lazy:loadLazy silent:beSilent) |
|
4341 ifFalse:[ |
|
4342 shortName ~= aClassName ifTrue:[ |
|
4343 packageFile := self getPackageFileName:(packageDir , '/classes/' , longName , '.cls'). |
|
4344 packageFile isNil ifTrue:[ |
|
4345 packageFile := (packageDir , '/classes/' , longName , '.cls'). |
|
4346 ]. |
|
4347 ok := self fileIn:packageFile lazy:loadLazy silent:beSilent |
|
4348 ] |
|
4349 ]. |
|
4350 |
|
4351 zarFn := self getPackageFileName:(packageDir , '/classes.zip'). |
|
4352 zarFn notNil ifTrue:[ |
|
4353 zar := ZipArchive oldFileNamed:zarFn. |
|
4354 zar notNil ifTrue:[ |
|
4355 entry := zar extract:(shortName , '.cls'). |
|
4356 (entry isNil and:[shortName ~= longName]) ifTrue:[ |
|
4357 entry := zar extract:(longName , '.cls'). |
|
4358 ]. |
|
4359 entry notNil ifTrue:[ |
|
4360 bos := BinaryObjectStorage onOld:(entry asByteArray readStream). |
|
4361 bos next. |
|
4362 bos close. |
|
4363 ok := true |
|
4364 ]. |
|
4365 ] |
|
4366 ] |
|
4367 ] |
|
4368 ]. |
|
4369 |
|
4370 " |
|
4371 if that did not work, look for an st-source file ... |
|
4372 " |
|
4373 ok ifFalse:[ |
|
4374 fn := shortName , '.st'. |
|
4375 (ok := self fileIn:fn lazy:loadLazy silent:beSilent) |
|
4376 ifFalse:[ |
|
4377 shortName ~= longName ifTrue:[ |
|
4378 fn := longName , '.st'. |
|
4379 ok := self fileIn:fn lazy:loadLazy silent:beSilent |
|
4380 ]. |
|
4381 ok ifFalse:[ |
|
4382 " |
|
4383 ... and in the standard source-directory |
|
4384 " |
|
4385 fn := 'source/' , shortName , '.st'. |
|
4386 (ok := self fileIn:fn lazy:loadLazy silent:beSilent) |
|
4387 ifFalse:[ |
|
4388 shortName ~= longName ifTrue:[ |
|
4389 fn := 'source/' , longName , '.st'. |
|
4390 ok := self fileIn:fn lazy:loadLazy silent:beSilent |
|
4391 ] |
|
4392 ] |
|
4393 ] |
|
4394 ]. |
|
4395 " |
|
4396 if that did not work, and the classes package is known, |
|
4397 look for an st-source file |
|
4398 in a package subdir of the source-directory ... |
|
4399 " |
|
4400 ok ifFalse:[ |
|
4401 packageDir notNil ifTrue:[ |
|
4402 packageFile := self getPackageFileName:(packageDir , '/source/' , shortName , '.st'). |
|
4403 packageFile isNil ifTrue:[ |
|
4404 packageFile := (packageDir , '/source/' , shortName , '.st'). |
|
4405 ]. |
|
4406 fn := packageFile. |
|
4407 (ok := self fileIn:packageFile lazy:loadLazy silent:beSilent) |
|
4408 ifFalse:[ |
|
4409 shortName ~= aClassName ifTrue:[ |
|
4410 packageFile := self getPackageFileName:(packageDir , '/source/' , longName , '.st'). |
|
4411 packageFile isNil ifTrue:[ |
|
4412 packageFile := (packageDir , '/source/' , longName , '.st'). |
|
4413 ]. |
|
4414 fn := packageFile. |
|
4415 ok := self fileIn:packageFile lazy:loadLazy silent:beSilent |
|
4416 ]. |
|
4417 ok ifFalse:[ |
|
4418 |
|
4419 packageFile := self getPackageFileName:(packageDir , '/' , shortName , '.st'). |
|
4420 packageFile isNil ifTrue:[ |
|
4421 packageFile := (packageDir , '/' , shortName , '.st'). |
|
4422 ]. |
|
4423 fn := packageFile. |
|
4424 (ok := self fileIn:packageFile lazy:loadLazy silent:beSilent) |
|
4425 ifFalse:[ |
|
4426 shortName ~= aClassName ifTrue:[ |
|
4427 packageFile := self getPackageFileName:(packageDir , '/' , longName , '.st'). |
|
4428 packageFile isNil ifTrue:[ |
|
4429 packageFile := (packageDir , '/' , longName , '.st'). |
|
4430 ]. |
|
4431 fn := packageFile. |
|
4432 ok := self fileIn:packageFile lazy:loadLazy silent:beSilent |
|
4433 ]. |
|
4434 ok ifFalse:[ |
|
4435 " |
|
4436 ... and in the standard source-directory |
|
4437 " |
|
4438 fn := 'source/' , packageDir , '/' , shortName , '.st'. |
|
4439 (ok := self fileIn:fn lazy:loadLazy silent:beSilent) |
|
4440 ifFalse:[ |
|
4441 shortName ~= aClassName ifTrue:[ |
|
4442 fn := 'source/' , packageDir , '/' , longName , '.st'. |
|
4443 ok := self fileIn:fn lazy:loadLazy silent:beSilent |
|
4444 ] |
|
4445 ] |
|
4446 ] |
|
4447 ]. |
|
4448 ]. |
|
4449 ]. |
|
4450 ] |
|
4451 ]. |
|
4452 " |
|
4453 if that did not work, and the classes package is known, |
|
4454 look for a zipArchive containing a class entry. |
|
4455 " |
|
4456 ok ifFalse:[ |
|
4457 packageDir notNil ifTrue:[ |
|
4458 zarFn := self getPackageFileName:(packageDir , '/source.zip'). |
|
4459 zarFn isNil ifTrue:[ |
|
4460 zarFn := packageDir asFilename withSuffix:'zip'. |
|
4461 zarFn := self getSourceFileName:zarFn. |
|
4462 ]. |
|
4463 zarFn notNil ifTrue:[ |
|
4464 zar := ZipArchive oldFileNamed:zarFn. |
|
4465 zar notNil ifTrue:[ |
|
4466 entry := zar extract:(shortName , '.st'). |
|
4467 (entry isNil and:[shortName ~= longName]) ifTrue:[ |
|
4468 entry := zar extract:(longName , '.st'). |
|
4469 ]. |
|
4470 entry notNil ifTrue:[ |
|
4471 fn := zarFn. |
|
4472 ok := self |
|
4473 fileInStream:(entry asString readStream) |
|
4474 lazy:loadLazy |
|
4475 silent:beSilent |
|
4476 logged:false |
|
4477 addPath:nil |
|
4478 ]. |
|
4479 ] |
|
4480 ] |
|
4481 ] |
|
4482 ]. |
|
4483 |
|
4484 " |
|
4485 if that did not work, |
|
4486 look for a zipArchive containing a class entry. |
|
4487 " |
|
4488 ok ifFalse:[ |
|
4489 zarFn := self getSourceFileName:'source.zip'. |
|
4490 zarFn notNil ifTrue:[ |
|
4491 zar := ZipArchive oldFileNamed:zarFn. |
|
4492 zar notNil ifTrue:[ |
|
4493 entry := zar extract:(zarFn := shortName , '.st'). |
|
4494 (entry isNil and:[shortName ~= longName]) ifTrue:[ |
|
4495 entry := zar extract:(zarFn := longName , '.st'). |
|
4496 ]. |
|
4497 entry notNil ifTrue:[ |
|
4498 fn := zarFn. |
|
4499 ok := self |
|
4500 fileInStream:(entry asString readStream) |
|
4501 lazy:loadLazy |
|
4502 silent:beSilent |
|
4503 logged:false |
|
4504 addPath:nil |
|
4505 ]. |
|
4506 ] |
|
4507 ] |
|
4508 ]. |
|
4509 ok ifFalse:[ |
|
4510 " |
|
4511 new: if there is a sourceCodeManager, ask it for the classes sourceCode |
|
4512 " |
|
4513 (mgr := Smalltalk at:#SourceCodeManager) notNil ifTrue:[ |
|
4514 inStream := mgr getMostRecentSourceStreamForClassNamed:aClassName. |
|
4515 inStream notNil ifTrue:[ |
|
4516 fn := nil. |
|
4517 ok := self fileInStream:inStream lazy:loadLazy silent:beSilent logged:false addPath:nil. |
|
4518 ] |
|
4519 ]. |
3995 ]. |
4520 ]. |
3996 ]. |
4521 ]. |
3997 ]. |
4522 ]. |
3998 ] |
4523 ] |
3999 ] |
4524 ] |
4159 Smalltalk loadClassLibraryIfAbsent:'libbasic' |
4703 Smalltalk loadClassLibraryIfAbsent:'libbasic' |
4160 Smalltalk loadClassLibraryIfAbsent:'libwidg3' |
4704 Smalltalk loadClassLibraryIfAbsent:'libwidg3' |
4161 " |
4705 " |
4162 |
4706 |
4163 "Modified: 31.10.1996 / 16:57:24 / cg" |
4707 "Modified: 31.10.1996 / 16:57:24 / cg" |
|
4708 ! |
|
4709 |
|
4710 secureFileIn:aFileName |
|
4711 "read in the named file, looking for it at standard places. |
|
4712 Catch any error during fileIn. Return true if ok, false if failed" |
|
4713 |
|
4714 |retVal| |
|
4715 |
|
4716 retVal := false. |
|
4717 |
|
4718 (SignalSet with:AbortSignal with:Process terminateSignal) |
|
4719 handle:[:ex | |
|
4720 ex return |
|
4721 ] do:[ |
|
4722 retVal := self fileIn:aFileName |
|
4723 ]. |
|
4724 ^ retVal |
|
4725 ! |
|
4726 |
|
4727 silentFileIn:aFilename |
|
4728 "same as fileIn:, but do not output 'compiled...'-messages on Transcript. |
|
4729 Main use is during startup." |
|
4730 |
|
4731 |wasSilent| |
|
4732 |
|
4733 wasSilent := self silentLoading:true. |
|
4734 [ |
|
4735 self fileIn:aFilename |
|
4736 ] ensure:[ |
|
4737 self silentLoading:wasSilent |
|
4738 ] |
4164 ! ! |
4739 ! ! |
4165 |
4740 |
4166 !Smalltalk class methodsFor:'system management-files'! |
4741 !Smalltalk class methodsFor:'system management-files'! |
4167 |
4742 |
4168 LibraryIfAbsent:'libbasic' |
4743 bitmapFileStreamFor:aFileName |
4169 Smalltalk loadClassLibraryIfAbsent:'libwidg3' |
4744 "search aFileName in some standard places; |
4170 " |
4745 return a readonly fileStream or nil if not found. |
4171 |
4746 Searches in subdirectories named 'bitmaps' in the SystemPath. |
4172 "Modified: 31.10.1996 / 16:57:24 / cg" |
4747 Notice: this does not look in the package-specific bitmaps directories." |
4173 ! |
4748 |
4174 |
4749 |aString| |
4175 retVal := self fileIn:aFileName |
4750 |
4176 ]. |
4751 aString := self getBitmapFileName:aFileName. |
4177 ^ retVal |
4752 aString notNil ifTrue:[ |
4178 ! |
4753 ^ aString asFilename readStreamOrNil |
4179 |
4754 ]. |
4180 ment-files' |
4755 ^ nil |
4181 ! |
4756 ! |
4182 |
4757 |
4183 pFromFileNamed:aFileName forClass:aClass |
4758 bitmapFromFileNamed:aFileName forClass:aClass |
4184 "search aFileName in some standard places: |
4759 "search aFileName in some standard places: |
4185 first in the redefinable bitmaps path, |
4760 first in the redefinable bitmaps path, |
4186 then in the classes own package directory if existing. |
4761 then in the classes own package directory if existing. |
4187 Return an image or nil." |
4762 Return an image or nil." |
4188 |
4763 |
4213 " |
4804 " |
4214 |
4805 |
4215 "Modified: 11.12.1995 / 14:51:10 / cg" |
4806 "Modified: 11.12.1995 / 14:51:10 / cg" |
4216 ! |
4807 ! |
4217 |
4808 |
4218 classNameForFile:'ArrColl.chg' |
4809 constructPathFor:aDirectoryName |
4219 " |
4810 "search for aDirectory in SystemPath; |
4220 |
4811 return a collection of pathes which include that directory." |
4221 "Modified: 11.12.1995 / 14:51:10 / cg" |
4812 |
4222 ! |
4813 ^ self realSystemPath select:[:dirName | |
4223 |
4814 |fullPath| |
4224 fTrue:[^ abbrev]. |
4815 |
|
4816 fullPath := dirName asFilename construct:aDirectoryName. |
|
4817 "/ fullPath exists and:[fullPath isDirectory and:[fullPath isReadable]] |
|
4818 fullPath isDirectory and:[fullPath isReadable] |
|
4819 ]. |
|
4820 ! |
|
4821 |
|
4822 fileInFileStreamFor:aFileName |
|
4823 "search aFileName in some standard places; |
|
4824 return a readonly fileStream or nil if not found. |
|
4825 Searches in subdirectories named 'fileIn' in SystemPath" |
|
4826 |
|
4827 |aString| |
|
4828 |
|
4829 aString := self getFileInFileName:aFileName. |
|
4830 aString notNil ifTrue:[ |
|
4831 ^ aString asFilename readStreamOrNil |
|
4832 ]. |
|
4833 ^ nil |
|
4834 ! |
|
4835 |
|
4836 fileNameForClass:aClassOrClassName |
|
4837 "return a filename for aClassOrClassName" |
|
4838 |
|
4839 |cls nm1 nm2| |
|
4840 |
|
4841 aClassOrClassName isBehavior ifTrue:[ |
|
4842 nm1 := aClassOrClassName theNonMetaclass name. |
|
4843 nm2 := aClassOrClassName theNonMetaclass nameWithoutPrefix. |
|
4844 ] ifFalse:[ |
|
4845 cls := Smalltalk classNamed:aClassOrClassName. |
|
4846 cls notNil ifTrue:[ |
|
4847 nm1 := cls theNonMetaclass name. |
|
4848 nm2 := cls theNonMetaclass nameWithoutPrefix. |
|
4849 ] ifFalse:[ |
|
4850 nm1 := aClassOrClassName. |
|
4851 nm2 := (aClassOrClassName copyFrom:(aClassOrClassName lastIndexOf:$:)+1). |
|
4852 ]. |
|
4853 ]. |
|
4854 nm1 := nm1 asSymbol. |
|
4855 nm2 := nm2 asSymbol. |
|
4856 |
|
4857 CachedAbbreviations notNil ifTrue:[ |
|
4858 (CachedAbbreviations includesKey:nm1) ifTrue:[ |
|
4859 ^ CachedAbbreviations at:nm1 |
|
4860 ]. |
|
4861 nm2 notNil ifTrue:[ |
|
4862 ^ CachedAbbreviations at:nm2 ifAbsent:nm1 |
|
4863 ]. |
|
4864 ]. |
|
4865 ^ nm1 |
|
4866 |
|
4867 "/ "return a good filename for aClassOrClassName - |
|
4868 "/ using the abbreviation file if there is one" |
|
4869 "/ |
|
4870 "/ |fileName abbrev cls fullClassName shortClassName| |
|
4871 "/ |
|
4872 "/ aClassOrClassName isBehavior ifTrue:[ |
|
4873 "/ cls := aClassOrClassName theNonMetaclass. |
|
4874 "/ fullClassName := cls name. |
|
4875 "/ shortClassName := cls nameWithoutPrefix. |
|
4876 "/ ] ifFalse:[ |
|
4877 "/ fullClassName := shortClassName := aClassOrClassName. |
|
4878 "/ shortClassName := shortClassName copyFrom:(shortClassName lastIndexOf:$:)+1. |
|
4879 "/ ]. |
|
4880 "/ |
|
4881 "/ fileName := fullClassName asSymbol. |
|
4882 "/ |
|
4883 "/ "look for abbreviation" |
|
4884 "/ |
|
4885 "/ abbrev := self filenameAbbreviations at:fileName ifAbsent:[nil]. |
|
4886 "/ abbrev notNil ifTrue:[^ abbrev]. |
4225 "/ |
4887 "/ |
4226 "/ "no abbreviation found - if its a short name, take it" |
4888 "/ "no abbreviation found - if its a short name, take it" |
4227 "/ |
4889 "/ |
4228 "/ OperatingSystem maxFileNameLength < (fileName size + 3) ifTrue:[ |
4890 "/ OperatingSystem maxFileNameLength < (fileName size + 3) ifTrue:[ |
4229 "/ "this will only be triggered on sys5.3/DOS type systems" |
4891 "/ "this will only be triggered on sys5.3/DOS type systems" |
4638 Smalltalk packagePath addLast:'/opt/smalltalk' |
5373 Smalltalk packagePath addLast:'/opt/smalltalk' |
4639 Smalltalk packagePath addFirst:'/usr/local/otherPackages' |
5374 Smalltalk packagePath addFirst:'/usr/local/otherPackages' |
4640 " |
5375 " |
4641 ! |
5376 ! |
4642 |
5377 |
4643 packagePath addFirst:'/usr/local/otherPackages' |
5378 packagePath:aPath |
4644 " |
5379 "set the packagePath; |
4645 ! |
5380 a collection of additional directorynames, where smalltalk |
4646 |
5381 looks for package directories. |
4647 il]. |
5382 Notice, that directories named 'packages' under the systemPath are |
|
5383 always consulted - even if not in the packagePath" |
|
5384 |
|
5385 PackagePath := aPath asOrderedCollection |
|
5386 |
|
5387 " |
|
5388 Smalltalk packagePath:#( '.' '/opt/stx' '/opt/smalltalk' '/usr/local/otherPackages') |
|
5389 " |
|
5390 ! |
|
5391 |
|
5392 projectDirectoryForClass:aClass |
|
5393 "given a class, return the path to its package directory; |
|
5394 nil if not found." |
|
5395 |
|
5396 |pkg| |
|
5397 |
|
5398 pkg := aClass package. |
|
5399 pkg isNil ifTrue:[^ nil]. |
4648 |
5400 |
4649 ^ self projectDirectoryForPackage:pkg. |
5401 ^ self projectDirectoryForPackage:pkg. |
4650 |
5402 |
4651 " |
5403 " |
4652 Smalltalk projectDirectoryForClass:Array |
5404 Smalltalk projectDirectoryForClass:Array |
4653 Smalltalk projectDirectoryForClass:View |
5405 Smalltalk projectDirectoryForClass:View |
4654 " |
5406 " |
4655 ! |
5407 ! |
4656 |
5408 |
4657 iations found under ''' , aPath ,'''') infoPrintCR. |
5409 projectDirectoryForPackage:aPackage |
|
5410 "given a packageID, return the path to its package directory; |
|
5411 nil if not found." |
|
5412 |
|
5413 |prj prjDir| |
|
5414 |
|
5415 "/ there might be a package specific resource directory ... |
|
5416 "/ in the directory, from which the project was loaded |
|
5417 prj := Project projectWithId:aPackage. |
|
5418 prj notNil ifTrue:[ |
|
5419 prjDir := prj directory. |
|
5420 ]. |
|
5421 (prjDir notNil and:[prjDir asFilename exists]) ifFalse:[ |
|
5422 prjDir := Smalltalk getPackageFileName:(aPackage copyReplaceAll:$: with:$/). |
|
5423 ]. |
|
5424 ^ prjDir |
|
5425 |
|
5426 " |
|
5427 Smalltalk projectDirectoryForPackage:'stx:libbasic' |
|
5428 Smalltalk projectDirectoryForPackage:'exept:smartcard' |
|
5429 " |
|
5430 ! |
|
5431 |
|
5432 readAbbreviations |
|
5433 "read classname to filename mappings from include/abbrev.stc. |
|
5434 sigh - all for those poor sys5.3 or MSDOS people with short filenames ..." |
|
5435 |
|
5436 "since installAutoloadedClasses also reads all abbreviations, use it" |
|
5437 |
|
5438 CachedAbbreviations := IdentityDictionary new. |
|
5439 self installAutoloadedClasses. |
|
5440 ^ CachedAbbreviations. |
|
5441 |
|
5442 "/ |aStream f dirsConsulted| |
|
5443 "/ |
|
5444 "/ CachedAbbreviations := IdentityDictionary new. |
|
5445 "/ |
|
5446 "/ "/ new scheme: look for a directory called 'packages' |
|
5447 "/ "/ and enumerate its abbrev.stc files... |
|
5448 "/ dirsConsulted := Set new. |
|
5449 "/ f := Smalltalk getSystemFileName:'packages'. |
|
5450 "/ f notNil ifTrue:[ |
|
5451 "/ f := f asFilename. |
|
5452 "/ f isDirectory ifTrue:[ |
|
5453 "/ ('Smalltalk [info]: reading all class abbreviations found under ''' , f pathName ,'''') infoPrintCR. |
|
5454 "/ self recursiveReadAllAbbreviationsFrom:f. |
|
5455 "/ dirsConsulted add:f pathName. |
|
5456 "/ ]. |
|
5457 "/ ]. |
|
5458 "/ |
|
5459 "/ "/ and along the package-path |
|
5460 "/ self packagePath do:[:aPath | |
|
5461 "/ (dirsConsulted includes:aPath) ifFalse:[ |
|
5462 "/ ('Smalltalk [info]: reading all class abbreviations found under ''' , aPath ,'''') infoPrintCR. |
4658 "/ self recursiveReadAllAbbreviationsFrom:aPath. |
5463 "/ self recursiveReadAllAbbreviationsFrom:aPath. |
4659 "/ dirsConsulted add:aPath |
5464 "/ dirsConsulted add:aPath |
4660 "/ ] |
5465 "/ ] |
4661 "/ ]. |
5466 "/ ]. |
4662 "/ |
5467 "/ |
4678 " |
5483 " |
4679 |
5484 |
4680 "Modified: / 10.12.1999 / 17:48:53 / cg" |
5485 "Modified: / 10.12.1999 / 17:48:53 / cg" |
4681 ! |
5486 ! |
4682 |
5487 |
4683 :[ |
5488 readAbbreviationsFromStream:aStream |
|
5489 "read classname to filename mappings from aStream. |
|
5490 sigh - all for those poor sys5.3 or MSDOS people with short filenames ..." |
|
5491 |
|
5492 |abbrevs line words nm abbrev pkg key oldAbbrev cls s w| |
|
5493 |
|
5494 abbrevs := CachedAbbreviations. |
|
5495 |
|
5496 [aStream atEnd] whileFalse:[ |
|
5497 line := aStream nextLine. |
|
5498 line notNil ifTrue:[ |
|
5499 (line startsWith:'#') ifFalse:[ |
|
5500 |
|
5501 "/ must do it manually, caring for quoted strings. |
|
5502 "/ words := line asCollectionOfWords. |
|
5503 |
|
5504 words := OrderedCollection new. |
|
5505 s := line readStream. |
|
5506 [s atEnd] whileFalse:[ |
|
5507 s skipSeparators. |
|
5508 s peek == $' ifTrue:[ |
|
5509 s next. |
|
5510 w := s upTo:$'. |
|
5511 s skipSeparators. |
|
5512 ] ifFalse:[ |
|
5513 w := s upToSeparator |
|
5514 ]. |
|
5515 words add:w |
|
5516 ]. |
|
5517 words size >= 3 ifTrue:[ |
|
5518 nm := (words at:1) withoutSeparators. |
|
5519 abbrev := (words at:2) withoutSeparators. |
|
5520 pkg := (words at:3) withoutSeparators. |
|
5521 nm ~= abbrev ifTrue:[ |
|
5522 key := nm asSymbol. |
|
5523 oldAbbrev := abbrevs at:key ifAbsent:nil. |
|
5524 oldAbbrev notNil ifTrue:[ |
|
5525 oldAbbrev ~= abbrev ifTrue:[ |
|
5526 StandAlone ifFalse:[ |
|
5527 ('Smalltalk [warning]: conflict for: ' , nm , ' in ' , (aStream pathName)) infoPrintCR. |
|
5528 ('Smalltalk [warning]: (' , oldAbbrev , ' <-> ' , abbrev , ')') infoPrintCR |
|
5529 ] |
|
5530 ]. |
|
5531 ] ifFalse:[ |
|
5532 cls := self classNamed:abbrev. |
|
5533 |
|
5534 cls notNil ifTrue:[ |
4684 cls name ~= nm ifTrue:[ |
5535 cls name ~= nm ifTrue:[ |
4685 "/ ok, there is a class named after this abbrev ... |
5536 "/ ok, there is a class named after this abbrev ... |
4686 "/ this is only a conflict, if the other class has no |
5537 "/ this is only a conflict, if the other class has no |
4687 "/ abbreviation (or the same). |
5538 "/ abbreviation (or the same). |
4688 (abbrevs at:(cls name asSymbol) ifAbsent:cls name) = abbrev ifTrue:[ |
5539 (abbrevs at:(cls name asSymbol) ifAbsent:cls name) = abbrev ifTrue:[ |
4820 ] |
5653 ] |
4821 ]. |
5654 ]. |
4822 ]. |
5655 ]. |
4823 ! |
5656 ! |
4824 |
5657 |
4825 Stream:abbrevStream. |
5658 resourceFileStreamFor:aFileName |
4826 abbrevStream close. |
5659 "search aFileName in some standard places; |
4827 ] on:FileStream openErrorSignal do:[:ex| "ignore this file"]. |
5660 return a readonly fileStream or nil if not found. |
4828 |
5661 Searches in subdirectories named 'resource' in SystemPath" |
4829 [ |
5662 |
4830 directoryContents := dir directoryContents. |
5663 ^ self resourceFileStreamFor:aFileName forClass:nil |
4831 ] on:FileStream openErrorSignal do:[:ex| |
5664 ! |
4832 "non-accessable directory: we are done" |
5665 |
4833 ^ self |
5666 resourceFileStreamFor:aFileName forClass:aClassOrNil |
4834 ]. |
5667 "search aFileName in some standard places and in the classes |
4835 |
5668 package-resource directory. |
4836 directoryContents do:[:aFilename | |
5669 Return a readonly fileStream or nil if not found. |
4837 |f| |
5670 Searches in subdirectories named 'resource' in SystemPath" |
4838 |
5671 |
4839 (#( |
5672 |aString| |
4840 'doc' |
5673 |
4841 'CVS' |
5674 aString := self getResourceFileName:aFileName forClass:aClassOrNil. |
4842 'bitmaps' |
|
4843 'resources' |
|
4844 'source' |
|
4845 ) includes:aFilename) ifFalse:[ |
|
4846 f := dir construct:aFilename. |
|
4847 f isDirectory ifTrue:[ |
|
4848 self recursiveReadAllAbbreviationsFrom:f maxLevels:maxLevels-1 |
|
4849 ] |
|
4850 ]. |
|
4851 ]. |
|
4852 ! |
|
4853 |
|
4854 me. |
|
4855 f isDirectory ifTrue:[ |
|
4856 self recursiveReadAllAbbreviationsFrom:f maxLevels:maxLevels-1 |
|
4857 ] |
|
4858 ]. |
|
4859 ]. |
|
4860 ! |
|
4861 |
|
4862 Name forClass:aClassOrNil. |
|
4863 aString notNil ifTrue:[ |
5675 aString notNil ifTrue:[ |
4864 ^ aString asFilename readStreamOrNil |
5676 ^ aString asFilename readStreamOrNil |
4865 ]. |
5677 ]. |
4866 ^ nil |
5678 ^ nil |
4867 ! |
5679 ! |
4868 |
5680 |
4869 fileName. |
5681 searchPath:aPath for:aFileName in:aDirName |
|
5682 "search aPath for a subdirectory named aDirectory with a file |
|
5683 named aFileName" |
|
5684 |
|
5685 |f| |
|
5686 |
|
5687 ((f := aFileName asFilename) isAbsolute |
|
5688 or:[f isExplicitRelative]) ifTrue:[ |
|
5689 "/ |
|
5690 "/ dont use path for absolute or explicit .-relative file names |
|
5691 "/ |
|
5692 ^ aFileName |
|
5693 ]. |
|
5694 |
|
5695 aPath notNil ifTrue:[ |
|
5696 aPath do:[:dirName | |
|
5697 |realName dir| |
|
5698 |
|
5699 dir := dirName asFilename. |
|
5700 aDirName notNil ifTrue:[ |
|
5701 realName := (dir construct:aDirName) construct:aFileName. |
|
5702 ] ifFalse:[ |
|
5703 realName := dir construct:aFileName. |
|
5704 ]. |
|
5705 (realName isReadable) ifTrue:[ |
|
5706 ^ realName name |
|
5707 ] |
|
5708 ]. |
|
5709 ]. |
|
5710 |
|
5711 ^ nil. |
|
5712 |
|
5713 "Modified: / 29.4.1999 / 15:06:43 / cg" |
|
5714 ! |
|
5715 |
|
5716 sourceDirectoryNameOfClass:aClassOrClassName |
|
5717 "for a given class, return the pathname relative to TOP of the classes source code. |
|
5718 Read the files 'abbrev.stc' and 'liblist.stc' (which are created during the compilation process) |
|
5719 for an entry for aClassOrClassName. |
|
5720 Search for the className in the first col, and return the value found in |
|
5721 the 3rd col. |
|
5722 Return nil if no entry is found." |
|
5723 |
|
5724 |aStream line words n aClassName| |
|
5725 |
|
5726 aClassOrClassName isBehavior ifTrue:[ |
|
5727 aClassName := aClassOrClassName name |
|
5728 ] ifFalse:[ |
|
5729 aClassName := aClassOrClassName |
|
5730 ]. |
|
5731 aClassName := aClassName asString. |
|
5732 |
|
5733 #('include/abbrev.stc' 'include/liblist.stc') "/ filenames |
|
5734 with:#(3 2) "/ column |
|
5735 do:[:fileName :col | |
|
5736 |
|
5737 aStream := self systemFileStreamFor:fileName. |
4870 aStream notNil ifTrue:[ |
5738 aStream notNil ifTrue:[ |
4871 [aStream atEnd] whileFalse:[ |
5739 [aStream atEnd] whileFalse:[ |
4872 line := aStream nextLine. |
5740 line := aStream nextLine. |
4873 line notNil ifTrue:[ |
5741 line notNil ifTrue:[ |
4874 (line startsWith:'#') ifFalse:[ |
5742 (line startsWith:'#') ifFalse:[ |
4900 "Created: 6.11.1995 / 15:43:30 / cg" |
5768 "Created: 6.11.1995 / 15:43:30 / cg" |
4901 "Modified: 9.12.1995 / 23:54:14 / cg" |
5769 "Modified: 9.12.1995 / 23:54:14 / cg" |
4902 "Modified: 3.1.1997 / 11:26:44 / stefan" |
5770 "Modified: 3.1.1997 / 11:26:44 / stefan" |
4903 ! |
5771 ! |
4904 |
5772 |
4905 houtSeparators |
5773 sourceFileStreamFor:aFileName |
4906 ] |
5774 "search aFileName in some standard places; |
4907 ] |
5775 return a readonly fileStream or nil if not found. |
4908 ] |
5776 Searches in subdirectories named 'source' in SystemPath" |
4909 ] |
|
4910 ] |
|
4911 ]. |
|
4912 aStream close |
|
4913 ]. |
|
4914 ]. |
|
4915 |
|
4916 ^ nil |
|
4917 |
|
4918 " |
|
4919 Smalltalk sourceDirectoryNameOfClass:'ClockView' |
|
4920 Smalltalk sourceDirectoryNameOfClass:'Bag' |
|
4921 Smalltalk sourceDirectoryNameOfClass:'GLWireCubeDemoView' |
|
4922 Smalltalk sourceDirectoryNameOfClass:'SomeNonExistingClass' |
|
4923 " |
|
4924 |
|
4925 "Created: 6.11.1995 / 15:43:30 / cg" |
|
4926 "Modified: 9.12.1995 / 23:54:14 / cg" |
|
4927 "Modified: 3.1.1997 / 11:26:44 / stefan" |
|
4928 ! |
|
4929 |
|
4930 lass' |
|
4931 " |
|
4932 |
|
4933 "Created: 6.11.1995 / 15:43:30 / cg" |
|
4934 "Modified: 9.12.1995 / 23:54:14 / cg" |
|
4935 "Modified: 3.1.1997 / 11:26:44 / stefan" |
|
4936 ! |
|
4937 |
|
4938 Path" |
|
4939 |
5777 |
4940 |aString| |
5778 |aString| |
4941 |
5779 |
4942 aString := self getSourceFileName:aFileName. |
5780 aString := self getSourceFileName:aFileName. |
4943 aString notNil ifTrue:[ |
5781 aString notNil ifTrue:[ |
4944 ^ aString asFilename readStreamOrNil |
5782 ^ aString asFilename readStreamOrNil |
4945 ]. |
5783 ]. |
4946 ^ nil |
5784 ^ nil |
4947 ! ! |
5785 ! |
4948 |
5786 |
4949 !Smalltalk class methodsFor:'system management-packages'! |
5787 systemFileStreamFor:aFileName |
4950 |
5788 "search aFileName in some standard places; |
4951 mOrNil |
5789 return a readonly fileStream or nil if not found. |
|
5790 see comment in Smalltalk>>initSystemPath" |
|
5791 |
|
5792 |aString| |
|
5793 |
|
5794 aString := self getSystemFileName:aFileName. |
|
5795 aString notNil ifTrue:[ |
|
5796 ^ aString asFilename readStreamOrNil |
4952 ]. |
5797 ]. |
4953 ^ nil |
5798 ^ nil |
4954 ! |
5799 ! |
4955 |
5800 |
4956 return a collection of directorynames, where smalltalk |
5801 systemPath |
|
5802 "return a collection of directorynames, where smalltalk |
4957 looks for system files |
5803 looks for system files |
4958 (usually in subdirs such as resources, bitmaps, source etc.) |
5804 (usually in subdirs such as resources, bitmaps, source etc.) |
4959 see comment in Smalltalk>>initSystemPath." |
5805 see comment in Smalltalk>>initSystemPath." |
4960 |
5806 |
4961 ^ SystemPath |
5807 ^ SystemPath |
4964 Smalltalk systemPath |
5810 Smalltalk systemPath |
4965 Smalltalk systemPath addLast:'someOtherDirectoryPath' |
5811 Smalltalk systemPath addLast:'someOtherDirectoryPath' |
4966 " |
5812 " |
4967 ! |
5813 ! |
4968 |
5814 |
4969 OtherDirectoryPath' |
5815 systemPath:aPath |
4970 " |
5816 "set the collection of directorynames, where smalltalk |
4971 ! |
5817 looks for system files |
4972 |
5818 (usually in subdirs such as resources, bitmaps, source etc.) |
4973 alk systemPath |
5819 see comment in Smalltalk>>initSystemPath." |
|
5820 |
|
5821 SystemPath := aPath. |
|
5822 self flushPathCaches |
|
5823 |
|
5824 " |
|
5825 Smalltalk systemPath |
4974 Smalltalk systemPath:(Smalltalk systemPath copy addLast:'someOtherDirectoryPath') |
5826 Smalltalk systemPath:(Smalltalk systemPath copy addLast:'someOtherDirectoryPath') |
4975 " |
5827 " |
4976 ! |
5828 ! ! |
4977 |
5829 |
4978 ! |
5830 !Smalltalk class methodsFor:'system management-packages'! |
4979 |
5831 |
4980 t:[ |
5832 knownPackages |
|
5833 ^ KnownPackages ? #() |
|
5834 ! |
|
5835 |
|
5836 loadExtensionsForPackage:aPackageId |
|
5837 |packageDirName| |
|
5838 |
|
5839 packageDirName := aPackageId copyReplaceAll:$: with:$/. |
|
5840 |
|
5841 packageDirName := self getPackageFileName:packageDirName. |
|
5842 packageDirName isNil ifTrue:[ |
|
5843 ^ false |
|
5844 ]. |
|
5845 ^ self loadExtensionsFromDirectory:packageDirName |
|
5846 ! |
|
5847 |
|
5848 loadExtensionsFromDirectory:packageDirOrString |
|
5849 |packageDir f| |
|
5850 |
|
5851 packageDir := packageDirOrString asFilename. |
|
5852 |
|
5853 f := packageDir construct:'extensions.st'. |
|
5854 f exists ifTrue:[ |
|
5855 f fileIn. |
|
5856 SilentLoading ifFalse:[ |
|
5857 Transcript showCR:('loaded extensions: ' , f pathName). |
|
5858 ]. |
|
5859 ^ true |
|
5860 ]. |
|
5861 ^ false |
|
5862 ! |
|
5863 |
|
5864 loadPackage:aPackageIdOrPackage |
|
5865 "make certain, that some particular package is loaded into the system. |
|
5866 Experimental." |
|
5867 |
|
5868 (aPackageIdOrPackage isSymbol |
|
5869 or:[aPackageIdOrPackage isString]) ifTrue:[ |
|
5870 ^ self loadPackageWithId:aPackageIdOrPackage asAutoloaded:false |
|
5871 ]. |
|
5872 self shouldImplement. |
|
5873 |
|
5874 " |
|
5875 Smalltalk loadPackage:'stx:libbasic' |
|
5876 Smalltalk loadPackage:'stx:goodies/persistency' |
|
5877 Smalltalk loadPackage:'cg:cparser' |
|
5878 Smalltalk loadPackage:'cg:rose' |
|
5879 " |
|
5880 ! |
|
5881 |
|
5882 loadPackage:packageId fromAllSourceFilesInDirectory:aDirectory |
|
5883 "load all source files found in aDirectory and treat them like |
|
5884 a package. Allows for initial import of alien ST-code as a new package. |
|
5885 Experimental." |
|
5886 |
|
5887 |p t new anyFail| |
|
5888 |
|
5889 "/ problem: dependencies. |
|
5890 "/ solution: repeat twice, so that superclasses are present the second time |
|
5891 |
|
5892 Class packageQuerySignal answer:packageId asSymbol do:[ |
|
5893 |any| |
|
5894 |
|
5895 2 timesRepeat:[ |
4981 anyFail := false. |
5896 anyFail := false. |
4982 aDirectory directoryContents do:[:file | |
5897 aDirectory directoryContents do:[:file | |
4983 |fn| |
5898 |fn| |
4984 |
5899 |
4985 fn := aDirectory construct:file. |
5900 fn := aDirectory construct:file. |
5013 new ifTrue:[Project addLoadedProject:p]. |
5928 new ifTrue:[Project addLoadedProject:p]. |
5014 ^ anyFail not |
5929 ^ anyFail not |
5015 |
5930 |
5016 ! |
5931 ! |
5017 |
5932 |
5018 p isLoaded:true. |
5933 loadPackage:packageId fromClassLibrary:aFilename |
5019 |
5934 "load a package from a compiled classLib. |
5020 new ifTrue:[Project addLoadedProject:p]. |
5935 Experimental." |
5021 ^ anyFail not |
5936 |
5022 |
5937 |p t new| |
5023 ! |
5938 |
5024 |
5939 (self fileIn:aFilename) ifFalse:[ |
5025 oaded:true. |
5940 (self fileInClassLibrary:aFilename) ifFalse:[ |
|
5941 self warn:'Failed to load the package ', packageId printString. |
|
5942 ^ false. |
|
5943 ] |
|
5944 ]. |
|
5945 |
|
5946 new := (p := Project projectWithId:packageId) isNil. |
|
5947 new ifTrue:[ p := Project new]. |
|
5948 |
|
5949 p name:packageId. |
|
5950 p directory:aFilename directory. |
|
5951 p package:packageId. |
|
5952 t := packageId asCollectionOfSubstringsSeparatedByAny:'/\:'. |
|
5953 p repositoryModule:(t first). |
|
5954 p repositoryDirectory:(packageId copyFrom:t first size + 2). |
|
5955 p isLoaded:true. |
5026 |
5956 |
5027 new ifTrue:[Project addLoadedProject:p]. |
5957 new ifTrue:[Project addLoadedProject:p]. |
5028 ^ true |
5958 ^ true |
5029 ! |
5959 ! |
5030 |
5960 |
|
5961 loadPackage:packageId fromLoadAllFile:aFilename |
|
5962 "load a package from a loadAll - loader script. |
|
5963 Experimental." |
|
5964 |
|
5965 |p t new| |
|
5966 |
|
5967 Metaclass confirmationQuerySignal answer:false |
|
5968 do:[ |
|
5969 (self fileIn:aFilename) ifFalse:[ |
|
5970 self warn:'Failed to load the package ', packageId printString. |
|
5971 ^ false. |
|
5972 ] |
|
5973 ]. |
|
5974 |
|
5975 new := (p := Project projectWithId:packageId) isNil. |
|
5976 new ifTrue:[ p := Project new]. |
|
5977 |
|
5978 p name:packageId. |
|
5979 p directory:aFilename directory. |
|
5980 p package:packageId. |
|
5981 t := packageId asCollectionOfSubstringsSeparatedByAny:'/\:'. |
|
5982 p repositoryModule:(t first). |
|
5983 p repositoryDirectory:(packageId copyFrom:t first size + 2). |
|
5984 p isLoaded:true. |
|
5985 |
|
5986 new ifTrue:[Project addLoadedProject:p]. |
|
5987 ^ true |
|
5988 ! |
|
5989 |
|
5990 loadPackage:aPackageId fromProjectFile:f asAutoloaded:doLoadAsAutoloaded |
|
5991 "load a package from a .prj spec. |
|
5992 Experimental." |
|
5993 |
|
5994 |
|
5995 "/ not yet implemented ... |
|
5996 ^ false. |
|
5997 |
|
5998 "/ |prj fn| |
|
5999 "/ |
|
6000 "/ prj := Project new loadFromProjectFile:f asFilename pathName. |
|
6001 "/ "/ no - also allow for applications to be loaded this way |
|
6002 "/ "/ prj type == #library ifFalse:[ ^ false]. |
|
6003 "/ self halt. |
|
6004 "/ "/ load all prerequisites ... |
|
6005 "/ prj prerequisites do:[:aRequiredPackage | |
|
6006 "/ self halt. |
|
6007 "/ ]. |
|
6008 "/ |
|
6009 "/ "/ see if there is a class library ... |
|
6010 "/ fn := prj directory asFilename construct:(prj name , ObjectFileLoader sharedLibraryExtension). |
|
6011 "/ fn exists ifTrue:[ |
|
6012 "/ "/ load that classLibrary ... |
|
6013 "/ self fileIn:fn pathName. |
|
6014 "/ ]. |
|
6015 "/ |
|
6016 "/ "/ now, for all other classes, file-them in |
5031 "/ "/ or declare as autoloaded ... |
6017 "/ "/ or declare as autoloaded ... |
5032 "/ |
6018 "/ |
5033 "/ prj classes do:[:aClassOrName | |ns| |
6019 "/ prj classes do:[:aClassOrName | |ns| |
5034 "/ aClassOrName isBehavior ifFalse:[ |
6020 "/ aClassOrName isBehavior ifFalse:[ |
5035 "/ ((self includesKey:aClassOrName) not |
6021 "/ ((self includesKey:aClassOrName) not |
5054 fromProjectFile:'../../../exept/osi/asn1/asn1.prj' |
6040 fromProjectFile:'../../../exept/osi/asn1/asn1.prj' |
5055 asAutoloaded:false |
6041 asAutoloaded:false |
5056 " |
6042 " |
5057 ! |
6043 ! |
5058 |
6044 |
5059 ame) not |
6045 loadPackage:aPackageId fromZIPArchive:f asAutoloaded:doLoadAsAutoloaded |
5060 "/ and:[(ns := prj defaultNameSpace) isNil |
6046 "load a package from a .zip delivery file. |
5061 "/ or:[ns == self |
6047 Experimental." |
5062 "/ or:[(ns includesKey:aClassOrName) not]]]) |
6048 |
5063 "/ ifTrue:[ |
6049 "/ not yet implemented ... |
5064 "/ "/ must load a corresponding source or cls-file |
6050 ^ false |
5065 "/ self halt. |
6051 ! |
5066 "/ ] |
6052 |
5067 "/ ] |
6053 loadPackageWithId:aPackageId |
5068 "/ ]. |
6054 "make certain, that some particular package is loaded into the system. |
5069 "/ prj isLoaded:true. |
6055 Experimental." |
5070 "/ prj directory:f asFilename directoryName. |
6056 |
5071 "/ Project addLoadedProject:prj. |
6057 |
5072 "/ ^ true |
6058 ^ self loadPackageWithId:aPackageId asAutoloaded:false |
5073 |
6059 |
5074 " |
6060 " |
5075 Smalltalk loadPackage:'exept:osi/asn1' |
6061 Smalltalk loadPackageWithId:'stx:libbasic' |
5076 Smalltalk |
6062 Smalltalk loadPackageWithId:'stx:goodies/persistency' |
5077 loadPackage:'exept:osi/asn1' |
6063 Smalltalk loadPackageWithId:'cg:cparser' |
5078 fromProjectFile:'../../../exept/osi/asn1/asn1.prj' |
6064 Smalltalk loadPackageWithId:'cg:rose' |
5079 asAutoloaded:false |
6065 Smalltalk loadPackageWithId:'detemobil:smc' |
5080 " |
6066 " |
5081 ! |
6067 ! |
5082 |
6068 |
5083 t:prj. |
6069 loadPackageWithId:aPackageId asAutoloaded:doLoadAsAutoloaded |
5084 "/ ^ true |
6070 "make certain, that some particular package is loaded into the system. |
5085 |
6071 Experimental." |
5086 " |
6072 |
5087 Smalltalk loadPackage:'exept:osi/asn1' |
6073 |pkg packageDirName packageBaseName packageDir| |
5088 Smalltalk |
6074 |
5089 loadPackage:'exept:osi/asn1' |
6075 pkg := Project projectWithId:aPackageId. |
5090 fromProjectFile:'../../../exept/osi/asn1/asn1.prj' |
6076 (pkg notNil and:[pkg isLoaded]) ifTrue:[ |
5091 asAutoloaded:false |
6077 "/ ('Smalltalk [info]: Package ' , aPackageId , ' already loaded.') infoPrintCR. |
5092 " |
6078 (doLoadAsAutoloaded |
5093 ! |
6079 or:[pkg areAllClassesLoaded]) ifTrue:[ |
5094 |
6080 ^ true |
5095 aceAll:$: with:$/. |
6081 ]. |
|
6082 ]. |
|
6083 |
|
6084 "/ ok; not yet loaded. |
|
6085 "/ try to locate the package; try the following: |
|
6086 "/ $(packagePath)/<packageDir>/... |
|
6087 "/ $(SYSPATH)/packages/<packageDir> |
|
6088 |
|
6089 packageDirName := aPackageId copyReplaceAll:$: with:$/. |
5096 packageBaseName := packageDirName asFilename baseName. |
6090 packageBaseName := packageDirName asFilename baseName. |
5097 |
6091 |
5098 packageDir := self getPackageFileName:packageDirName. |
6092 packageDir := self getPackageFileName:packageDirName. |
5099 packageDir isNil ifTrue:[ |
6093 packageDir isNil ifTrue:[ |
5100 "/ for convenience: try ../../.. as well |
6094 "/ for convenience: try ../../.. as well |
5119 " |
6113 " |
5120 Smalltalk loadPackageWithId:'stx:libbasic' |
6114 Smalltalk loadPackageWithId:'stx:libbasic' |
5121 Smalltalk loadPackageWithId:'stx:goodies/persistency' |
6115 Smalltalk loadPackageWithId:'stx:goodies/persistency' |
5122 Smalltalk loadPackageWithId:'exept:ctypes' |
6116 Smalltalk loadPackageWithId:'exept:ctypes' |
5123 " |
6117 " |
5124 ! ! |
6118 ! |
5125 |
6119 |
5126 !Smalltalk class methodsFor:'system management-undeclared variables'! |
6120 loadPackageWithId:aPackageId name:packageName fromDirectory:packageDirOrString asAutoloaded:doLoadAsAutoloaded |
5127 |
6121 |f s packageDir shLibName| |
5128 CR:('loaded package: ' , aPackageId , ' from binary classLib file: ' , aFilename pathName). |
6122 |
|
6123 packageDir := packageDirOrString asFilename. |
|
6124 |
|
6125 "/ .prj ? |
|
6126 f := (packageDir construct:packageName) withSuffix:'prj'. |
|
6127 f exists ifTrue:[ |
|
6128 (self loadPackage:aPackageId fromProjectFile:f asAutoloaded:doLoadAsAutoloaded) ifTrue:[ |
|
6129 SilentLoading ifFalse:[ |
|
6130 Transcript showCR:('Smalltalk [info]: loaded package: ' , aPackageId , ' from project file: ' , f pathName). |
|
6131 ]. |
|
6132 ^ true |
|
6133 ] |
|
6134 ]. |
|
6135 "/ loadAll ? |
|
6136 f := packageDir construct:'loadAll'. |
|
6137 f exists ifTrue:[ |
|
6138 (self loadPackage:aPackageId fromLoadAllFile:f) ifTrue:[ |
|
6139 SilentLoading ifFalse:[ |
|
6140 Transcript showCR:('loaded package: ' , aPackageId , ' from loadAll file: ' , f pathName). |
|
6141 ]. |
|
6142 ^ true |
|
6143 ] |
|
6144 ]. |
|
6145 "/ .zip ? |
|
6146 f := (packageDir construct:packageName) withSuffix:'zip'. |
|
6147 f exists ifTrue:[ |
|
6148 (self loadPackage:aPackageId fromZIPArchive:f asAutoloaded:doLoadAsAutoloaded) ifTrue:[ |
|
6149 SilentLoading ifFalse:[ |
|
6150 Transcript showCR:('loaded package: ' , aPackageId , ' from zip file: ' , f pathName). |
|
6151 ]. |
|
6152 ^ true |
|
6153 ] |
|
6154 ]. |
|
6155 |
|
6156 shLibName := packageName , ObjectFileLoader sharedLibraryExtension. |
|
6157 |
|
6158 "/ .so ? |
|
6159 f := packageDir construct:shLibName. |
|
6160 f exists ifTrue:[ |
|
6161 (self loadPackage:aPackageId fromClassLibrary:f) ifTrue:[ |
|
6162 SilentLoading ifFalse:[ |
|
6163 Transcript showCR:('loaded package: ' , aPackageId , ' from binary classLib file: ' , f pathName). |
|
6164 ]. |
|
6165 doLoadAsAutoloaded ifFalse:[ |
|
6166 "/ force autoloading... |
|
6167 Smalltalk allClassesDo:[:eachClass | |
|
6168 eachClass package == aPackageId ifTrue:[ eachClass autoload]. |
|
6169 ]. |
|
6170 ]. |
|
6171 ^ true |
|
6172 ] |
|
6173 ]. |
|
6174 |
|
6175 "/ abbrev.stc ? |
|
6176 f := packageDir construct:'abbrev.stc'. |
|
6177 f exists ifTrue:[ |
|
6178 Smalltalk installAutoloadedClassesFrom:f pathName. |
|
6179 |
|
6180 doLoadAsAutoloaded ifFalse:[ |
|
6181 "/ force autoloading... |
|
6182 Smalltalk allClassesDo:[:eachClass | |
|
6183 eachClass package == aPackageId ifTrue:[ eachClass autoload]. |
|
6184 ]. |
|
6185 ]. |
|
6186 |
|
6187 self loadExtensionsFromDirectory:packageDirOrString. |
|
6188 SilentLoading ifFalse:[ |
|
6189 Transcript showCR:('loaded package: ' , aPackageId , ' from abbrev file: ' , f pathName). |
|
6190 ]. |
|
6191 ^ true |
|
6192 ]. |
|
6193 |
|
6194 "/ "/ lib/loadAll ? (will vanish) |
|
6195 "/ f := (packageDir construct:'lib') construct:'loadAll'. |
|
6196 "/ f exists ifTrue:[ |
|
6197 "/ (self loadPackage:aPackageId fromLoadAllFile:f) ifTrue:[ |
|
6198 "/ SilentLoading ifFalse:[ |
|
6199 "/ Transcript showCR:('loaded package: ' , aPackageId , ' from loadAll file: ' , f pathName). |
|
6200 "/ ]. |
|
6201 "/ ^ true |
|
6202 "/ ] |
|
6203 "/ ]. |
|
6204 "/ |
|
6205 "/ "/ /lib/.so ? (will vanish) |
|
6206 "/ f := (packageDir construct:'lib') construct:shLibName. |
|
6207 "/ f exists ifTrue:[ |
|
6208 "/ (self loadPackage:aPackageId fromClassLibrary:f) ifTrue:[ |
|
6209 "/ SilentLoading ifFalse:[ |
|
6210 "/ Transcript showCR:('loaded package: ' , aPackageId , ' from binary classLib file: ' , f pathName). |
|
6211 "/ ]. |
|
6212 "/ ^ true |
|
6213 "/ ] |
|
6214 "/ ]. |
|
6215 |
|
6216 "/ any .so ? -> load the first one found (maybe not a good idea) |
|
6217 packageDir directoryContentsAsFilenamesDo:[:aFilename | |
|
6218 (aFilename hasSuffix:ObjectFileLoader sharedLibrarySuffix) ifTrue:[ |
|
6219 (self loadPackage:aPackageId fromClassLibrary:aFilename) ifTrue:[ |
|
6220 SilentLoading ifFalse:[ |
|
6221 Transcript showCR:('loaded package: ' , aPackageId , ' from binary classLib file: ' , aFilename pathName). |
5129 ]. |
6222 ]. |
5130 doLoadAsAutoloaded ifFalse:[ |
6223 doLoadAsAutoloaded ifFalse:[ |
5131 "/ force autoloading... |
6224 "/ force autoloading... |
5132 Smalltalk allClassesDo:[:eachClass | |
6225 Smalltalk allClassesDo:[:eachClass | |
5133 eachClass package == aPackageId ifTrue:[ eachClass autoload]. |
6226 eachClass package == aPackageId ifTrue:[ eachClass autoload]. |
5150 " |
6243 " |
5151 Smalltalk loadPackageWithId:'stx:libbasic' |
6244 Smalltalk loadPackageWithId:'stx:libbasic' |
5152 Smalltalk loadPackageWithId:'stx:goodies/persistency' |
6245 Smalltalk loadPackageWithId:'stx:goodies/persistency' |
5153 Smalltalk loadPackageWithId:'exept:ctypes' |
6246 Smalltalk loadPackageWithId:'exept:ctypes' |
5154 " |
6247 " |
5155 ! |
|
5156 |
|
5157 . |
|
5158 ]. |
|
5159 ]. |
|
5160 ^ true |
|
5161 ] |
|
5162 ] |
|
5163 ]. |
|
5164 |
|
5165 "/ source files |
|
5166 (self loadPackage:aPackageId fromAllSourceFilesInDirectory:packageDir) ifTrue:[ |
|
5167 SilentLoading ifFalse:[ |
|
5168 Transcript showCR:('loaded package: ' , aPackageId , ' from source files in:' , packageDir pathName). |
|
5169 ]. |
|
5170 ^ true |
|
5171 ]. |
|
5172 ^ false |
|
5173 |
|
5174 " |
|
5175 Smalltalk loadPackageWithId:'stx:libbasic' |
|
5176 Smalltalk loadPackageWithId:'stx:goodies/persistency' |
|
5177 Smalltalk loadPackageWithId:'exept:ctypes' |
|
5178 " |
|
5179 ! ! |
6248 ! ! |
5180 |
6249 |
|
6250 !Smalltalk class methodsFor:'system management-undeclared variables'! |
|
6251 |
|
6252 clearUndeclaredVariables |
|
6253 "remove all undeclared variables" |
|
6254 |
|
6255 (Smalltalk at:#Undeclared) do:[:eachKey | |
|
6256 Smalltalk removeKey:(self undeclaredPrefix , eachKey) asSymbol. |
|
6257 ]. |
|
6258 (Smalltalk at:#Undeclared) removeAll. |
|
6259 Smalltalk removeKey:#Undeclared. |
|
6260 ! |
|
6261 |
|
6262 undeclaredPrefix |
|
6263 "the prefix used for undeclared variables" |
|
6264 |
|
6265 ^ 'Undeclared:::' |
|
6266 |
|
6267 "Created: / 31.10.1997 / 01:13:10 / cg" |
|
6268 ! ! |
|
6269 |
5181 !Smalltalk class methodsFor:'time-versions'! |
6270 !Smalltalk class methodsFor:'time-versions'! |
5182 |
6271 |
5183 ript showCR:('loaded package: ' , aPackageId , ' from source files in:' , packageDir pathName). |
6272 configuration |
5184 ]. |
6273 "{ Pragma: +optSpace }" |
5185 ^ true |
6274 |
5186 ]. |
6275 "for developers only: return the configuration, with which |
5187 ^ false |
6276 this smalltalk was compiled." |
5188 |
6277 |
5189 " |
6278 %{ /* NOCONTEXT */ |
5190 Smalltalk loadPackageWithId:'stx:libbasic' |
6279 extern char *__getConfigurationString(); |
5191 Smalltalk loadPackageWithId:'stx:goodies/persistency' |
|
5192 Smalltalk loadPackageWithId:'exept:ctypes' |
|
5193 " |
|
5194 ! |
|
5195 |
|
5196 iables' |
|
5197 ! |
|
5198 |
|
5199 x |
|
5200 "the prefix used for undeclared variables" |
|
5201 |
|
5202 ^ 'Undeclared:::' |
|
5203 |
|
5204 "Created: / 31.10.1997 / 01:13:10 / cg" |
|
5205 ! |
|
5206 |
|
5207 char *__getConfigurationString(); |
|
5208 |
6280 |
5209 RETURN (__MKSTRING(__getConfigurationString() COMMA_SND)); |
6281 RETURN (__MKSTRING(__getConfigurationString() COMMA_SND)); |
5210 %}. |
6282 %}. |
5211 ^ 'unknownOS/unknownCONF:unknownPACK' |
6283 ^ 'unknownOS/unknownCONF:unknownPACK' |
5212 |
6284 |
5213 " |
6285 " |
5214 Smalltalk configuration |
6286 Smalltalk configuration |
5215 " |
6287 " |
5216 ! |
6288 ! |
5217 |
6289 |
5218 tSpace }" |
6290 copyrightString |
|
6291 "{ Pragma: +optSpace }" |
|
6292 |
|
6293 "return a copyright string" |
|
6294 |
|
6295 %{ /* NOCONTEXT */ |
|
6296 #ifndef __getCopyrightString |
|
6297 extern OBJ __getCopyrightString(); |
|
6298 #endif |
|
6299 |
|
6300 RETURN (__getCopyrightString()); |
|
6301 %}. |
|
6302 ^ self primitiveFailed |
|
6303 |
|
6304 " |
|
6305 Smalltalk copyrightString |
|
6306 " |
|
6307 ! |
|
6308 |
|
6309 distributorString |
|
6310 "{ Pragma: +optSpace }" |
5219 |
6311 |
5220 "return a string describing the distributor of this software" |
6312 "return a string describing the distributor of this software" |
5221 |
6313 |
5222 %{ /* NOCONTEXT */ |
6314 %{ /* NOCONTEXT */ |
5223 #ifndef __getDistributorString |
6315 #ifndef __getDistributorString |
5231 " |
6323 " |
5232 Smalltalk distributorString |
6324 Smalltalk distributorString |
5233 " |
6325 " |
5234 ! |
6326 ! |
5235 |
6327 |
5236 ! |
6328 expirationTime |
5237 |
6329 "{ Pragma: +optSpace }" |
5238 ang == #es) ifTrue:[ |
6330 |
|
6331 "for developers only: return the time when the system will expire. |
|
6332 after this time it will not run any longer. |
|
6333 It returns nil, if no expiration time has been set (system runs forever :-))" |
|
6334 |
|
6335 |exp| |
|
6336 |
|
6337 %{ |
|
6338 extern unsigned int __getExpirationTime(); |
|
6339 |
|
6340 exp = __MKUINT(__getExpirationTime()); |
|
6341 %}. |
|
6342 exp == 0 ifTrue:[ |
|
6343 ^ nil |
|
6344 ]. |
|
6345 ^ AbsoluteTime new fromOSTime:(exp * 1000). "OSTime is ms since 1970" |
|
6346 |
|
6347 " |
|
6348 Smalltalk expirationTime |
|
6349 " |
|
6350 ! |
|
6351 |
|
6352 fullVersionString |
|
6353 "{ Pragma: +optSpace }" |
|
6354 |
|
6355 "return a full version string" |
|
6356 |
|
6357 ^ 'Smalltalk/X release ' , self versionString , ' of ' , self versionDate |
|
6358 |
|
6359 " |
|
6360 Smalltalk fullVersionString |
|
6361 " |
|
6362 |
|
6363 "Created: / 27.10.1997 / 17:03:09 / cg" |
|
6364 "Modified: / 27.10.1997 / 17:04:02 / cg" |
|
6365 ! |
|
6366 |
|
6367 hello |
|
6368 "{ Pragma: +optSpace }" |
|
6369 |
|
6370 "return a greeting string" |
|
6371 |
|
6372 "stupid: this should come from a resource file ... |
|
6373 but I dont use it here, to allow mini-systems without |
|
6374 Resource-stuff." |
|
6375 |
|
6376 |proto lang| |
|
6377 |
|
6378 lang := Language. |
|
6379 (lang == #de) ifTrue:[ |
|
6380 proto := 'Willkommen bei %1 (Version %2 vom %3)' |
|
6381 ] ifFalse:[ (lang == #fr) ifTrue:[ |
|
6382 proto := 'Salut, Bienvenue à %1 (version %2 de %3)' |
|
6383 ] ifFalse:[ (lang == #it) ifTrue:[ |
|
6384 proto := 'Ciao, benvenuto al %1 (versione %2 di %3)' |
|
6385 ] ifFalse:[ (lang == #es) ifTrue:[ |
5239 "/ proto := 'Hola, bienvenida a %1 (versión %2 de %3)' |
6386 "/ proto := 'Hola, bienvenida a %1 (versión %2 de %3)' |
5240 ] ifFalse:[ (lang == #es) ifTrue:[ |
6387 ] ifFalse:[ (lang == #es) ifTrue:[ |
5241 "/ proto := 'Oi, benvindo a %1 (versão %2 de %3)' |
6388 "/ proto := 'Oi, benvindo a %1 (versão %2 de %3)' |
5242 ] ifFalse:[ (lang == #no) ifTrue:[ |
6389 ] ifFalse:[ (lang == #no) ifTrue:[ |
5243 proto := 'Hei, verdenmottakelse til %1 (versjon %2 av %3)' |
6390 proto := 'Hei, verdenmottakelse til %1 (versjon %2 av %3)' |
5369 Incremented for releases which fix bugs/add features |
6542 Incremented for releases which fix bugs/add features |
5370 and represent a stable workable version which got published |
6543 and represent a stable workable version which got published |
5371 to the outside world. |
6544 to the outside world. |
5372 |
6545 |
5373 ST/X revision Naming is: |
6546 ST/X revision Naming is: |
5374 <major>.<minor>.<revision>.<release>" |
6547 <major>.<minor>.<revision>.<release>" |
5375 |
6548 |
5376 ^ 5 |
6549 ^ 4 |
5377 |
6550 |
5378 " |
6551 " |
5379 Smalltalk revisionNr |
6552 Smalltalk revisionNr |
5380 Smalltalk hello |
6553 Smalltalk hello |
5381 " |
6554 " |
5382 |
6555 |
5383 "Modified: / 19.6.1998 / 04:29:10 / cg" |
6556 "Modified: / 19.6.1998 / 04:29:10 / cg" |
5384 ! |
6557 ! |
5385 |
6558 |
5386 " |
6559 timeStamp |
5387 Smalltalk releaseIdentification |
6560 "return a string useful for timestamping a file. |
5388 " |
6561 The returned string is padded with spaces for a constant |
5389 ! |
6562 length (to avoid changing a files size in fileOut with unchanged |
5390 |
6563 class)." |
5391 on>.<release>" |
6564 |
5392 |
6565 ^ ('''' , self timeStampString , '''') paddedTo:80 with:(Character space) |
5393 ^ 1 |
6566 ! |
5394 |
6567 |
5395 " |
6568 timeStamp:aStream |
5396 Smalltalk releaseNr |
6569 "write a string useful for timestamping a file onto aStream. |
5397 " |
6570 ST80 compatibility" |
5398 |
6571 |
5399 "Created: 10.12.1995 / 01:42:19 / cg" |
6572 aStream nextPutAll:(self timeStamp). |
5400 ! |
6573 |
5401 |
6574 "Created: / 18.6.1998 / 17:22:58 / cg" |
5402 ed for releases which fix bugs/add features |
6575 ! |
5403 and represent a stable workable version which got published |
6576 |
5404 to the outside world. |
6577 timeStampString |
5405 |
6578 "return a string useful for timestamping a file." |
5406 ST/X revision Naming is: |
6579 |
5407 <major>.<minor>.<revision>.<release>" |
6580 ^ ('From Smalltalk/X, Version:' , (Smalltalk versionString) , ' on ' |
5408 |
6581 , Date today printString , ' at ' , Time now printString |
|
6582 ) |
|
6583 ! |
|
6584 |
|
6585 versionDate |
|
6586 "{ Pragma: +optSpace }" |
|
6587 |
|
6588 "return the executables build date - thats the date when the smalltalk |
|
6589 executable was built" |
|
6590 |
|
6591 %{ /* NOCONTEXT */ |
|
6592 extern char *__getBuildDateString(); |
|
6593 |
|
6594 RETURN (__MKSTRING(__getBuildDateString() COMMA_SND) ); |
|
6595 %}. |
|
6596 ^ 'today' |
|
6597 |
|
6598 " |
|
6599 Smalltalk versionDate |
|
6600 " |
|
6601 ! |
|
6602 |
|
6603 versionString |
|
6604 "{ Pragma: +optSpace }" |
|
6605 |
|
6606 "return the version string" |
|
6607 |
|
6608 ^ (self majorVersionNr printString , |
|
6609 '.', |
|
6610 self minorVersionNr printString , |
|
6611 '.', |
|
6612 self revisionNr printString) |
|
6613 |
|
6614 " |
|
6615 Smalltalk versionString |
|
6616 " |
|
6617 ! |
|
6618 |
|
6619 vmMajorVersionNr |
|
6620 "{ Pragma: +optSpace }" |
|
6621 |
|
6622 "return the VMs major version number." |
|
6623 %{ |
|
6624 RETURN (__MKSMALLINT(4)); |
|
6625 %}. |
5409 ^ 4 |
6626 ^ 4 |
5410 |
6627 |
5411 " |
6628 " |
5412 Smalltalk revisionNr |
6629 Smalltalk vmMajorVersionNr |
5413 Smalltalk hello |
6630 " |
5414 " |
6631 |
5415 |
|
5416 "Modified: / 19.6.1998 / 04:29:10 / cg" |
|
5417 ! |
|
5418 |
|
5419 " |
|
5420 Smalltalk revisionNr |
|
5421 Smalltalk hello |
|
5422 " |
|
5423 |
|
5424 "Modified: / 19.6.1998 / 04:29:10 / cg" |
|
5425 ! |
|
5426 |
|
5427 ('''' , self timeStampString , '''') paddedTo:80 with:(Character space) |
|
5428 ! |
|
5429 |
|
5430 / cg" |
|
5431 ! ! |
6632 ! ! |
5432 |
6633 |
5433 !Smalltalk class methodsFor:'documentation'! |
6634 !Smalltalk class methodsFor:'documentation'! |
5434 |
6635 |
5435 version |
6636 version |
5436 ^ '$Header: /cvs/stx/stx/libbasic/Smalltalk.st,v 1.619 2003-11-18 09:21:53 cg Exp $' |
6637 ^ '$Header: /cvs/stx/stx/libbasic/Smalltalk.st,v 1.620 2003-11-18 13:55:34 penk Exp $' |
5437 ! ! |
6638 ! ! |