'From Squeak3.2alpha of 4 October 2001 [latest update: #4423] on 16 October 2001 at 7:45:43 pm'! "Change Set: logError-tk Date: 16 October 2001 Author: Ted Kaehler Combine the code that prints the stack in the file 'SqueakDebug.log' and in a mail message via #mailOutBugReport. For the first four contexts, print the instance vars and the temp vars (and the arguments). This should be much more useful for figuring out what happened when the report is emailed to someone. If you have an error reporting system that depended on the exact format of the email produced by #mailOutBugReport, please talk to me."! !Object methodsFor: 'printing' stamp: 'tk 10/16/2001 19:41'! longPrintString "Answer a String whose characters are a description of the receiver." | str | str _ String streamContents: [:aStream | self longPrintOn: aStream]. "Objects without inst vars should return something" ^ str isEmpty ifTrue: [self printString, String cr] ifFalse: [str]! ! !Behavior methodsFor: 'printing' stamp: 'tk 10/16/2001 19:35'! longPrintOn: aStream "Append to the argument, aStream, the names and values of all of the receiver's instance variables. But, not useful for a class with a method dictionary." aStream nextPutAll: '<>'; cr.! ! !ContextPart methodsFor: 'debugger access' stamp: 'tk 10/16/2001 19:28'! errorReportOn: strm "Write a detailed error report on the stack (above me) on a stream. For both the error file, and emailing a bug report. Suppress any errors while getting printStrings. Limit the length." | cnt aContext | strm print: Date today; space; print: Time now; cr. strm cr. strm nextPutAll: 'VM: '; nextPutAll: Smalltalk platformName asString; nextPutAll: ' - '; nextPutAll: Smalltalk vmVersion asString; cr. strm nextPutAll: 'Image: '; nextPutAll: Smalltalk version asString; nextPutAll: ' ['; nextPutAll: Smalltalk lastUpdateString asString; nextPutAll: ']'; cr. strm cr. "Note: The following is an open-coded version of ContextPart>>stackOfSize: since this method may be called during a low space condition and we might run out of space for allocating the full stack." cnt _ 0. aContext _ self. [aContext == nil] whileFalse: [ (cnt _ cnt + 1) < 5 ifTrue: [aContext printDetails: strm. "variable values" strm cr] ifFalse: [ cnt = 5 ifTrue: [strm nextPutAll: '--- The rest of the stack ---'; cr]. strm print: aContext; cr]. "just class>>selector" strm position > 5000 ifTrue: [strm nextPutAll: '...'. ^ self]. "exit early" cnt > 60 ifTrue: [strm nextPutAll: '-- and more not shown --'. ^ self]. aContext _ aContext sender]. ! ! !ContextPart methodsFor: 'printing' stamp: 'tk 10/16/2001 19:43'! printDetails: strm "Put my class>>selector and arguments and temporaries on the stream. Protect against errors during printing." | str | self printOn: strm. strm cr; tab; nextPutAll: 'Arguments and temporary variables: '; cr; tab; tab. str _ [self tempsAndValues padded: #right to: 1 with: $x] ifError: [:err :rcvr | '<>']. strm nextPutAll: (str allButLast copyReplaceAll: String cr with: String cr, String tab, String tab). strm cr.! ! !Debugger methodsFor: 'context stack menu' stamp: 'tk 10/16/2001 19:00'! mailOutBugReport "Compose a useful bug report showing the state of the process as well as vital image statistics as suggested by Chris Norton - 'Squeak could pre-fill the bug form with lots of vital, but oft-repeated, information like what is the image version, last update number, VM version, platform, available RAM, author...' and address it to the list with the appropriate subject prefix." | messageStrm | (Smalltalk includesKey: #Celeste) ifFalse: [^ self inform: 'no mail reader present']. Cursor write showWhile: ["Prepare the message" messageStrm _ WriteStream on: (String new: 1500). messageStrm nextPutAll: 'From: '; nextPutAll: Celeste userName; cr; nextPutAll: 'To: squeak-dev@lists.squeakfoundation.org'; cr; nextPutAll: 'Subject: '; nextPutAll: '[BUG]'; nextPutAll: self interruptedContext printString; cr;cr; nextPutAll: 'here insert explanation of what you were doing, suspect changes you''ve made and so forth.';cr;cr. self interruptedContext errorReportOn: messageStrm. CelesteComposition openForCeleste: Celeste current initialText: messageStrm contents]. ! ! !MethodContext methodsFor: 'printing' stamp: 'tk 10/16/2001 19:45'! printDetails: strm "Put my class>>selector and instance variables and arguments and temporaries on the stream. Protect against errors during printing." | pe str | self printOn: strm. strm cr. strm tab; nextPutAll: 'Receiver: '. pe _ '<>'. [receiver printOn: strm] ifError: [:err :rcvr | pe]. strm cr; tab; nextPutAll: 'Arguments and temporary variables: '; cr; tab; tab. str _ [self tempsAndValues padded: #right to: 1 with: $x] ifError: [:err :rcvr | pe]. strm nextPutAll: (str allButLast copyReplaceAll: String cr with: String cr, String tab, String tab). strm cr; tab; nextPutAll: 'Receiver''s instance variables: '; cr; tab; tab. str _ [receiver longPrintString padded: #right to: 1 with: $x] ifError: [:err :rcvr | pe]. strm nextPutAll: (str allButLast copyReplaceAll: String cr with: String cr, String tab, String tab). strm cr.! ! !SystemDictionary methodsFor: 'miscellaneous' stamp: 'tk 10/16/2001 19:24'! logError: errMsg inContext: aContext to: aFilename "Log the error message and a stack trace to the given file." | ff | FileDirectory default deleteFileNamed: aFilename ifAbsent: []. (ff _ FileStream fileNamed: aFilename) ifNil: [^ self "avoid recursive errors"]. ff nextPutAll: errMsg; cr. aContext errorReportOn: ff. ff close.! !