VDBStartup.st
author Jan Vrany <jan.vrany@fit.cvut.cz>
Fri, 05 Oct 2018 09:11:56 +0100
changeset 117 1ae8e04f5feb
parent 116 d0d6da74ead3
child 119 be31a77e2d9c
permissions -rw-r--r--
UI: add option to change debugger layout and preference to set the default layout

"
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' }"

"{ 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 gdb 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
                    ];
                    on: #('--gdb') do:[ :path |
                        gdb := path asFilename.
                        gdb exists ifFalse:[ 
                            self error: 'No such file: ', gdb pathName
                        ].
                        gdb isExecutable ifFalse:[ 
                            self error: 'Not an executable program: ', gdb pathName
                        ].
                    ];
                    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.
    ].

    gdb notNil ifTrue:[
        GDBProcess gdbExecutable: gdb.
    ].

    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: / 04-10-2018 / 15:40:52 / 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
 --gdb GDB .................... use GDB instead if default one (overrides 
                                preferences)
 --preference FILE ............ read user settings from FILE
 --no-preferences ............. do not read user settings at all
 --help ....................... output this message
'.

    Smalltalk exitIfStandalone: 0.

    "Modified: / 04-10-2018 / 15:14:49 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !

!VDBStartup class methodsFor:'documentation'!

version_HG

    ^ '$Changeset: <not expanded> $'
! !