VDBStartup.st
changeset 107 d98c11f9a7f5
parent 83 101ff2210613
child 116 d0d6da74ead3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VDBStartup.st	Sun Sep 23 07:03:34 2018 +0100
@@ -0,0 +1,257 @@
+"
+jv:vdb - Visual / VM Debugger
+Copyright (C) 2015-now Jan Vrany
+
+This software is licensed under 'Creative Commons Attribution-NonCommercial 4.0 International License'
+
+You may find a full license text in LICENSE.txt or at http://creativecommons.org/licenses/by-nc/4.0/
+"
+"{ Package: 'jv:vdb/application' }"
+
+"{ NameSpace: Smalltalk }"
+
+StandaloneStartup subclass:#VDBStartup
+	instanceVariableNames:''
+	classVariableNames:''
+	poolDictionaries:''
+	category:'VDB-UI'
+!
+
+!VDBStartup class methodsFor:'documentation'!
+
+copyright
+"
+jv:vdb - Visual / VM Debugger
+Copyright (C) 2015-now Jan Vrany
+
+This software is licensed under 'Creative Commons Attribution-NonCommercial 4.0 International License'
+
+You may find a full license text in LICENSE.txt or at http://creativecommons.org/licenses/by-nc/4.0/
+"
+! !
+
+!VDBStartup class methodsFor:'constants & defaults'!
+
+applicationRegistryPath
+    "the key under which this application stores its process ID in the registry
+     as a collection of path-components.
+     i.e. if #('foo' 'bar' 'baz') is returned here, the current applications ID will be stored
+     in HKEY_CURRENT_USER\Software\foo\bar\baz\CurrentID.
+     (would also be used as a relative path for a temporary lock file under unix).
+     Used to detect if another instance of this application is already running."
+
+    ^ #('vdb')
+
+    "Modified: / 21-09-2014 / 01:29:12 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+applicationUUID
+    "answer an application-specific unique uuid.
+     This is used as the name of some exclusive OS-resource, which is used to find out,
+     if another instance of this application is already running.
+     Under win32, a mutex is used; under unix, an exclusive file in the tempDir could be used.
+     If redefined, please return a real UUID (i.e. UUID fromString:'.....') and not a string or
+     similar possibly conflicting identifier.
+     You can paste a fresh worldwide unique id via the editor's more-misc-paste UUID menuFunction."
+
+    ^ UUID fromString:'57b09330-4126-11e4-a80f-606720e43e2c'
+
+    "Modified: / 21-09-2014 / 01:29:30 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!VDBStartup class methodsFor:'defaults'!
+
+allowDebugOption
+    "enable/disable the --debug startup option.
+     Can be redefined in subclasses to enable it"
+
+    ^ true
+
+    "Created: / 08-09-2014 / 19:30:40 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!VDBStartup class methodsFor:'private'!
+
+loadPreferenceFile: file
+
+    "Created: / 07-06-2017 / 09:49:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!VDBStartup class methodsFor:'queries'!
+
+applicationName
+    ^ 'vdb'
+
+    "Created: / 06-06-2017 / 22:50:44 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!VDBStartup class methodsFor:'startup'!
+
+main:argv
+    "Application entry point. `argv` is the array of command arguments (as Array of Strings)"
+
+    | optparser positional settingsFile settingsSuppressed replay 
+      programExecutable programArgs programPid attach 
+      debugger debuggerApp |
+
+    settingsSuppressed := false.
+    replay := false.
+    attach := false.
+
+    "/ Parse options...
+    optparser := CmdLineParser new
+                    ignoreUnknownOptions: true;
+                    on: #('--help') do:[
+                        self usage
+                    ];
+                    on: #('--preferences') do:[:filename |
+                        | file |
+
+                        file := filename asFilename.
+                        file isReadable ifFalse:[
+                            self error: 'preference file does not exists or not readable: ' , filename.
+                        ].
+                        file isRegularFile ifFalse:[
+                            self error: 'preference file is not a regular file: ' , filename.
+                        ].
+                        settingsFile := file.
+                    ];
+                    on: #('--no-preferences') do:[
+                        settingsSuppressed := true
+                    ];
+                    on: #('--replay') do:[
+                        replay := true
+                    ];
+                    yourself.
+    [
+        positional := optparser parse:argv.
+    ] on: CmdLineOptionError do:[:ex |
+        self error: ex description.
+    ].
+
+
+    "/ Now validate and process options
+    settingsSuppressed ifFalse:[
+        | settings |
+
+        settingsFile notNil ifTrue:[
+            settingsFile exists ifFalse:[
+                self error: 'preference file does not exist: ', settingsFile pathName
+            ].
+            settingsFile isDirectory ifTrue:[
+                self error: 'preference file is not a regular file: ', settingsFile pathName
+            ].
+            settingsFile isReadable ifFalse:[
+                self error: 'preference file is not a readable (check permissions): ', settingsFile pathName
+            ].
+            settings := UserPreferences loadSettingsFrom: settingsFile.
+        ] ifFalse:[
+            settings := UserPreferences loadSettings.
+        ].
+        UserPreferences setCurrent: settings.
+    ].
+
+    replay ifTrue:[ 
+        OperatingSystem isLinuxLike ifFalse:[ 
+            self error: 'replay not supported on this platform'.
+        ].
+        RR available ifFalse:[ 
+            self error: 'cannot replay because rr not available'
+        ].
+    ].
+
+    "/ Parse positional arguments - there are two forms:
+    "/
+    "/   vdb [OPTIONS] [PROGRAM [ARGS]]
+    "/   vdb [OPTIONS] [PID]
+    "/
+    "/ [OPTIONS] have already been processed, the rest is in `positional`
+    "/ variable
+
+    positional notEmpty ifTrue:[
+        programExecutable := positional first.
+        programExecutable asFilename exists ifFalse:[
+            "Try to find the executable in PATH..."
+
+            | path |
+
+            path := OperatingSystem pathOfCommand: programExecutable.
+            path notNil ifTrue:[
+                programExecutable := path.
+            ].
+        ].
+        programPid := Integer fromString: positional first onError: [ nil ].
+        programArgs := positional copyFrom: 2.
+
+        replay ifTrue:[ 
+            programArgs notEmptyOrNil ifTrue:[ 
+                self error: 'cannot specify program args when replaying'.
+            ].
+        ] ifFalse:[
+            "/ If * programExecutable does not exists
+            "/    * AND programPid is not nil (i.e., first positional argument can be converted to an integer)
+            "/    * AND programArguments are empty
+            "/ then interpret positional argument as PID and attach to it.
+            "/ Otherwise, interpret positional arguments
+            (programExecutable asFilename exists not and: [ programPid notNil and: [ programArgs isEmpty ]]) ifTrue:[
+                attach := true.
+            ] ifFalse:[
+                programExecutable asFilename exists ifFalse:[
+                    self error: 'cannot find program executable: ', programExecutable.
+                ].
+            ].
+        ].
+    ].
+
+    Debugger := DebugView ? MiniDebugger.
+    Inspector := InspectorView ? MiniInspector.
+
+    debugger := GDBDebugger new.
+    attach ifTrue:[
+        debugger attach: programPid
+    ] ifFalse:[
+        programExecutable notNil ifTrue:[
+            debugger executable: programExecutable arguments: programArgs.
+        ].
+    ].
+    Smalltalk openDisplay.
+    debuggerApp := VDBDebuggerApplication new.
+    debuggerApp debugger: debugger.
+    debuggerApp open.
+    replay ifTrue:[ 
+        debuggerApp doAttachToRR
+    ]. 
+
+    "
+        VDBStartup main: #()
+        VDBStartup main: #('ls')
+        VDBStartup main: #('/bin/ls' '/tmp')
+    "
+
+    "Modified: / 29-07-2018 / 08:51:58 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+!
+
+usage
+    Stdout nextPutAll:'usage: '; nextPutAll: self applicationName; nextPutAll: ' [OPTIONS] [PROGRAM [ARGS]] '; cr.
+    Stdout nextPutAll:'       '; nextPutAll: self applicationName; nextPutAll: ' [OPTIONS] [PID]'; cr.
+                                                                          "|"
+    Stdout nextPutLine:'
+options:
+ --replay ..................... replay last rr record
+ --preference FILE ............ read user settings from FILE
+ --no-preferences ............. do not read user settings at all
+ --help ....................... output this message
+'.
+
+    Smalltalk exitIfStandalone: 0.
+
+    "Modified: / 29-07-2018 / 08:55:19 / Jan Vrany <jan.vrany@fit.cvut.cz>"
+! !
+
+!VDBStartup class methodsFor:'documentation'!
+
+version_HG
+
+    ^ '$Changeset: <not expanded> $'
+! !
+