A complete rewrite of simple console
..that is not using `TerminalView`. The original (previous) implementation
had various problems that were hard to fix, namely loosing some
stream output in some cases.
New (current) implementation uses custom console view (1VDBSimpleDebuggerConsoleView`)
based on `TextCollector` rather than `TerminalView`. The resulting code is
much much simpler, it does not use internal pipes nor REPL / pipe reader processes.
Whole REPL runs completely in UI process.
"
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:'Standalone'
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 cmd noPTY replay
programExecutable programArgs programPid attach
debugger debuggerApp |
"/ This is awkward. We HAVE TO load prefetences when VDB is compiled standalone
"/ application or run from a command line (`--load jv:vdb` --run VDBStarup`.
"/ We MUST NOT load preferences when `VDBStarup main` is run from running IDE.
"/ for example while developing.
"/
"/ The trick is that there's no good and easy way to check this, so we have to
"/ check whether this method is called from `Smalltalk >> start`. Bleh.
Standalone := Smalltalk isStandAloneApp
or:[ thisContext sender method == (Smalltalk class compiledMethodAt: #start) ].
settingsSuppressed := Standalone not.
noPTY := 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: #('-d' '--gdb') do:[ :str |
cmd := str
];
on: #('--no-pty') do:[
noPTY := 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.
noPTY ifTrue:[
debugger := GDBDebugger newWithProcess: (GDBStXSimpleProcess newWithCommand: cmd).
] ifFalse:[
debugger := GDBDebugger newWithProcess: (GDBLocalProcess newWithCommand: cmd).
].
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: / 13-12-2018 / 15:32:32 / Jan Vrany <jan.vrany@fit.cvut.cz>"
!
usage
Transcript nextPutAll:'usage: '; nextPutAll: self applicationName; nextPutAll: ' [OPTIONS] [PROGRAM [ARGS]] '; cr.
Transcript nextPutAll:' '; nextPutAll: self applicationName; nextPutAll: ' [OPTIONS] [PID]'; cr.
"|"
Transcript nextPutLine:'
options:
--replay ..................... replay last rr record
--no-pty ..................... do not use PTY-based GDB console even if current
platform supports it.
-d | --gdb CMD ............... use CMD to launch GDB (instead of platform
default).
--preference FILE ............ read user settings from FILE
--no-preferences ............. do not read user settings at all
--help ....................... output this message
'.
Standalone ifTrue:[
Smalltalk exit: 0.
].
"Modified: / 13-12-2018 / 15:29:43 / Jan Vrany <jan.vrany@fit.cvut.cz>"
! !
!VDBStartup class methodsFor:'documentation'!
version_HG
^ '$Changeset: <not expanded> $'
! !