home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Programming / GDBbundle-1.0-MIS / src / TextEdit / GdbBundle.bproj / GdbDisplayController.m < prev    next >
Encoding:
Text File  |  1997-08-17  |  14.8 KB  |  536 lines

  1. /* GdbDisplayController.m created by ovidiu on Wed 19-Mar-1997 */
  2.  
  3. #import <Foundation/NSString.h>
  4. #import <Foundation/NSArray.h>
  5. #import <AppKit/NSWindow.h>
  6. #import <AppKit/NSBrowser.h>
  7. #import "GdbDisplayController.h"
  8. #import "../Document.h"
  9. #import "DebuggerController_Protocol.h"
  10. #import "Stack.h"
  11. #import "Frame.h"
  12. #import "Variable.h"
  13. #import "GdbBrowserCell.h"
  14. #import "FrameBrowserCell.h"
  15.  
  16. /* Private class used to store an object and a selector */
  17. @interface ObjectSelector : NSObject
  18. {
  19.   id object;
  20.   SEL selector;
  21. }
  22.  
  23. + (ObjectSelector*)newWithObject:(id)anObject selector:(SEL)aSelector;
  24. - (void)invokeWithArg:(id)gdbOutput type:(GdbOutputType)outputType;
  25.  
  26. @end
  27.  
  28. @implementation ObjectSelector
  29.  
  30. + (ObjectSelector*)newWithObject:(id)anObject selector:(SEL)aSelector
  31. {
  32.   ObjectSelector* obj = [[self new] autorelease];
  33.   obj->object = [anObject retain];
  34.   obj->selector = aSelector;
  35.   return obj;
  36. }
  37.  
  38. - (void)dealloc
  39. {
  40.   [object release];
  41.   [super dealloc];
  42. }
  43.  
  44. - (void)invokeWithArg:(id)gdbOutput type:(GdbOutputType)outputType
  45. {
  46.   IMP imp = [object methodForSelector:selector];
  47.   
  48. //  NSLog (@"%@ output = %@", NSStringFromSelector (_cmd), gdbOutput);
  49.   (*((void (*)(id, SEL, id, GdbOutputType))imp))
  50.     (object, selector, gdbOutput, outputType);
  51. }
  52.  
  53. @end
  54.  
  55.  
  56. @implementation GdbDisplayController
  57.  
  58. static NSString* stackBrowserFrameName = @"Stack Browser Window";
  59. static  NSString* selectionMatrixFrameName = @"Gdb Controller Window";
  60.  
  61. - init
  62. {
  63.   self = [super init];
  64.   stack = [Stack new];
  65.   [stack setGdbController:self];
  66.   objectsToBeNotified = [NSMutableArray new];
  67.   currentFrame = -1;
  68.  
  69.   return self;
  70. }
  71.  
  72. - (void)awakeFromNib
  73. {
  74.   NSWindow* stackBrowserWindow = [stackBrowser window];
  75.   NSWindow* selectionMatrixWindow = [selectionMatrix window];
  76.   NSString* frameString;
  77.  
  78.   NSLog (@"awakeFromNib");
  79.   [stackBrowserWindow setFrameAutosaveName:stackBrowserFrameName];
  80.   [selectionMatrixWindow setFrameAutosaveName:selectionMatrixFrameName];
  81. #if 0
  82.   frameString = [stackBrowserWindow stringWithSavedFrame];
  83.   if (frameString)
  84.     [[stackBrowser window] setFrameFromString:frameString];
  85.   NSLog (@"frame1 = %@", frameString);
  86.  
  87.   frameString = [selectionMatrixWindow stringWithSavedFrame];
  88.   if (frameString)
  89.     [[selectionMatrix window] setFrameFromString:frameString];
  90.   NSLog (@"frame2 = %@/n", frameString);
  91. #endif
  92. }
  93.  
  94. - (void)dealloc
  95. {
  96.   [stack release];
  97.   [objectsToBeNotified release];
  98.   [super dealloc];
  99. }
  100.  
  101. /* GuiDisplayProvider2 protocol methods */
  102. - (oneway void) setDebuggerController:(id)dC
  103. {
  104.   gdbManager = [dC retain];
  105.   [gdbManager executeCmd:@"set print repeats 0"
  106.                  withTty:YES
  107.           withAnnotation:NO
  108.              catchOutput:NO];
  109.   [gdbManager executeCmd:@"set print elements 0"
  110.                  withTty:YES
  111.           withAnnotation:NO
  112.              catchOutput:NO];
  113. }
  114.  
  115. - (oneway void) breakpointChanged:(int)bpNum
  116.                          newState:(BreakpointState)state
  117.                            inFile:(NSString *)fileName
  118.                            atLine:(int)lineNumber
  119. {
  120. //  NSLog (@"%@: bkpNum %d, file %@, line %d",
  121. //         NSStringFromSelector(_cmd), bpNum, fileName, lineNumber);
  122. }
  123.  
  124. - (oneway void) frameChanged:(int)newFrame
  125. {
  126. //  NSLog (@"frameChanged: newFrame %d", newFrame);
  127.   [stackBrowser selectRow:[self browserCellForFrame:newFrame] inColumn:0];
  128.   currentFrame = newFrame;
  129. }
  130.  
  131. - (void)executeGDBCommand:(NSString*)command
  132.                  annotate:(BOOL)flag
  133.              notifyObject:object
  134.                  selector:(SEL)selector
  135. {
  136.   [gdbManager executeCmd:command
  137.                  withTty:YES
  138.           withAnnotation:flag
  139.              catchOutput:YES];
  140.  
  141.   /* Disable all the buttons until we receive the backtrace result */
  142.   [self disableAllButtons];
  143.  
  144.   /* Queue the object and selector. The GDB commands are executed in FIFO
  145.     order, when GDB sends outputFromGDB:type: the first object in array is
  146.     dequeued. */
  147.   [objectsToBeNotified addObject:
  148.     [ObjectSelector newWithObject:object selector:selector]];
  149. }
  150.  
  151. - (oneway void) stackChanged:(int)newSize limitReached:(BOOL)maxedOut
  152. {
  153. //  NSLog (@"%@", NSStringFromSelector(_cmd));
  154.   [self executeGDBCommand:@"backtrace"
  155.                  annotate:YES
  156.              notifyObject:stack
  157.                  selector:@selector(createStackFromGdbBacktrace:type:)];
  158.   [stackBrowser selectRow:[[stackBrowser matrixInColumn:0] numberOfRows] - 1
  159.                  inColumn:0];
  160. }
  161.  
  162. - (oneway void) lineChangedForThread:(int) t
  163.                               inFile:(NSString *)f
  164.                          atStartLine:(int)sl
  165.                            toEndLine:(int)el
  166. {
  167. //  NSLog (@"lineChangedForThread: file = %@, line = %d", f, sl);
  168.   [self selectInFile:f startLine:sl endLine:el];
  169.   if (currentFrame >= 0) {
  170.     [[[stack frames] objectAtIndex:currentFrame]
  171.         setFilename:f startLine:sl endLine:el];
  172.     [stackBrowser selectRow:[self browserCellForFrame:currentFrame]
  173.                    inColumn:0];
  174.   }
  175. }
  176.  
  177. - (oneway void) inferiorStateChanged:(DebuggerState) newState
  178. {
  179. #if 0
  180.   NSString* states[] = {
  181.     @"DBG_STATE_NOT_ACTIVE",
  182.     @"DBG_STATE_ACTIVE",
  183.     @"DBG_STATE_INFERIOR_LOADED",
  184.     @"DBG_STATE_INFERIOR_EXITED",
  185.     @"DBG_STATE_INFERIOR_LOGICALLY_RUNNING",
  186.     @"DBG_STATE_INFERIOR_RUNNING",
  187.     @"DBG_STATE_INFERIOR_STOPPED"
  188.   };
  189.  
  190.   NSLog (@"inferiorStateChanged: %@", states[newState]);
  191. #endif
  192.  
  193.   debuggerState = newState;
  194.   [self setButtonsConformingToState:newState];
  195. }
  196.  
  197. - (int)query:(NSString*)queryString
  198. {
  199. //  NSLog (@"%@", NSStringFromSelector (_cmd));
  200.   return 0;
  201. }
  202.  
  203. - (oneway void) outputFromGDB:(NSString*)output
  204.                          type:(GdbOutputType)outputType
  205. {
  206.   id invoke = [objectsToBeNotified objectAtIndex:0];
  207.  
  208.   [invoke invokeWithArg:output type:outputType];
  209.  
  210.   /* Remove the invocation object when all the output has been received.
  211.     The message with GDB_OUTPUT_ANNOTATION as argument must be the last
  212.     message sent by GDB. */
  213.   if (outputType == GDB_OUTPUT_ANNOTATION)
  214.     [objectsToBeNotified removeObjectAtIndex:0];
  215.  
  216.   /* If all the commands sent to GDB have been executed display the state */
  217.   if (![objectsToBeNotified count])
  218.     [self setButtonsConformingToState:debuggerState];
  219. }
  220.  
  221. /* Our methods */
  222. - (void)display:sender
  223. {
  224.   [[selectionMatrix window] makeKeyAndOrderFront:nil];
  225. }
  226.  
  227. - (void)close
  228. {
  229.   [[selectionMatrix window] orderOut:nil];
  230.   [[stackBrowser window] orderOut:nil];
  231. }
  232.  
  233. - (void)setButtonsConformingToState:(DebuggerState)state
  234. {
  235.   switch (state) {
  236.     case DBG_STATE_NOT_ACTIVE:
  237.     case DBG_STATE_ACTIVE:
  238.       [runButton setEnabled:NO];
  239.       [stopButton setEnabled:NO];
  240.       [quitButton setEnabled:NO];
  241.       [execCmdMatrix setEnabled:NO];
  242.       [lineMatrix setEnabled:NO];
  243.       [selectionMatrix setEnabled:NO];
  244.       break;
  245.  
  246.     case DBG_STATE_INFERIOR_LOADED:
  247.     case DBG_STATE_INFERIOR_EXITED:
  248.       [runButton setEnabled:YES];
  249.       [stopButton setEnabled:NO];
  250.       [quitButton setEnabled:YES];
  251.       [execCmdMatrix setEnabled:NO];
  252.       [lineMatrix setEnabled:YES];
  253.       [selectionMatrix setEnabled:NO];
  254.       break;
  255.  
  256.     case DBG_STATE_INFERIOR_STOPPED:
  257.     case DBG_STATE_INFERIOR_LOGICALLY_RUNNING:
  258.       [runButton setEnabled:YES];
  259.       [stopButton setEnabled:NO];
  260.       [quitButton setEnabled:YES];
  261.       [execCmdMatrix setEnabled:YES];
  262.       [lineMatrix setEnabled:YES];
  263.       [selectionMatrix setEnabled:YES];
  264.       break;
  265.  
  266.     case DBG_STATE_INFERIOR_RUNNING:
  267.       [runButton setEnabled:NO];
  268.       [stopButton setEnabled:YES];
  269.       [quitButton setEnabled:NO];
  270.       [execCmdMatrix setEnabled:NO];
  271.       [lineMatrix setEnabled:NO];
  272.       [selectionMatrix setEnabled:NO];
  273.       break;
  274.   }
  275. }
  276.  
  277. - (void)disableAllButtons
  278. {
  279.   [self setButtonsConformingToState:DBG_STATE_NOT_ACTIVE];
  280. }
  281.  
  282. /* Outlet methods */
  283. - (void)run:sender
  284. {
  285.   int start = YES;
  286.  
  287.   if ((debuggerState == DBG_STATE_INFERIOR_STOPPED
  288.       || debuggerState == DBG_STATE_INFERIOR_LOGICALLY_RUNNING)
  289.       && !NSRunAlertPanel (@"Warning", @"Program is running. Do you really "
  290.                             @"want to restart it?", @"Yes", @"No", NULL))
  291.         start = NO;
  292.  
  293.   if (start) {
  294.     [gdbManager executeCmd:@"set confirm off" withTty:YES withAnnotation:NO];
  295.     [gdbManager executeCmd:@"run" withTty:YES withAnnotation:NO];
  296.     [gdbManager executeCmd:@"set confirm on" withTty:YES withAnnotation:NO];
  297.   }
  298. }
  299.  
  300. - (void)interrupt:sender
  301. {
  302.   [gdbManager interrupt];
  303. }
  304.  
  305. - (void)quit:sender
  306. {
  307.   int quit = YES;
  308.  
  309.   if ((debuggerState == DBG_STATE_INFERIOR_STOPPED
  310.       || debuggerState == DBG_STATE_INFERIOR_LOGICALLY_RUNNING)
  311.       && !NSRunAlertPanel (@"Warning", @"Program is running. Do you really "
  312.                             @"want to quit?", @"Yes", @"No", NULL))
  313.     quit = NO;
  314.  
  315.   if (quit) {
  316.     [gdbManager executeCmd:@"set confirm off" withTty:YES withAnnotation:NO];
  317.     [gdbManager executeCmd:@"quit" withTty:YES withAnnotation:NO];
  318. //    [[stackBrowser window] saveFrameUsingName:stackBrowserFrameName];
  319. //    [[selectionMatrix window] saveFrameUsingName:selectionMatrixFrameName];
  320.  
  321.     [[stackBrowser window] setFrameUsingName:[[stackBrowser window] stringWithSavedFrame]];
  322.     [[selectionMatrix window] setFrameUsingName:[[selectionMatrix window] stringWithSavedFrame]];
  323.     [[NSUserDefaults standardUserDefaults] synchronize];
  324.     NSLog (@"stack frame %@", NSStringFromRect([[stackBrowser window] frame]));
  325.     NSLog (@"matrix frame %@", NSStringFromRect([[selectionMatrix window] frame]));
  326.   }
  327. }
  328.  
  329. - (void)continue:sender
  330. {
  331.   [gdbManager executeCmd:@"continue" withTty:YES withAnnotation:NO];
  332. }
  333.  
  334. - (void)step:sender
  335. {
  336.   [gdbManager executeCmd:@"step" withTty:YES withAnnotation:NO];
  337. }
  338.  
  339. - (void)finish:sender
  340. {
  341.   [gdbManager executeCmd:@"finish" withTty:YES withAnnotation:NO];
  342. }
  343.  
  344. - (void)next:sender
  345. {
  346.   [gdbManager executeCmd:@"next" withTty:YES withAnnotation:NO];
  347.   [self invalidateCurrentFrameVariables];
  348. }
  349.  
  350. - (void)breakAt:sender
  351. {
  352.   Document* document = [Document currentDocument];
  353.   int line;
  354.   NSString* command;
  355.  
  356.   [document getStartLine:&line endLine:NULL];
  357.   command = [NSString stringWithFormat:@"future-break %@:%d",
  358.     [[document documentName] lastPathComponent], line];
  359.  
  360.   [gdbManager executeCmd:command withTty:YES withAnnotation:NO];
  361. }
  362.  
  363. - (void)runUntil:sender
  364. {
  365.   Document* document = [Document currentDocument];
  366.   int line;
  367.   NSString* command;
  368.  
  369.   [document getStartLine:&line endLine:NULL];
  370.   command = [NSString stringWithFormat:@"until %@:%d",
  371.     [[document documentName] lastPathComponent], line];
  372.  
  373.   [gdbManager executeCmd:command withTty:YES withAnnotation:NO];
  374. }
  375.  
  376. - (void)print:sender
  377. {
  378.   Document* document = [Document currentDocument];
  379.   NSString* selection = [document selection];
  380.   NSString* command = [NSString stringWithFormat:@"print %@", selection];
  381.  
  382.   [gdbManager executeCmd:command withTty:YES withAnnotation:NO];
  383. }
  384.  
  385. - (void)printIndirect:sender
  386. {
  387.   Document* document = [Document currentDocument];
  388.   NSString* selection = [document selection];
  389.   NSString* command = [NSString stringWithFormat:@"print *(%@)", selection];
  390.  
  391.   [gdbManager executeCmd:command withTty:YES withAnnotation:NO];
  392. }
  393.  
  394. - (void)showStackFrameWindow:sender
  395. {
  396.   [stackBrowser loadColumnZero];
  397.   [[stackBrowser window] makeKeyAndOrderFront:nil];
  398. }
  399.  
  400. /* Browser delegate methods */
  401. - (void)browser:(NSBrowser*)sender
  402.   createRowsForColumn:(int)column
  403.   inMatrix:(NSMatrix*)matrix
  404. {
  405.   int i, count = 0;
  406.  
  407.   if (column == 0) {
  408.     NSArray* frames = [stack frames];
  409.     Frame* frame;
  410.     FrameBrowserCell* cell;
  411.  
  412.     [matrix setPrototype:[[FrameBrowserCell new] autorelease]];
  413.  
  414.     for (i = 0, count = [[stack frames] count]; i < count; i++) {
  415.       [matrix addRow];
  416.       cell = [matrix cellAtRow:i column:0];
  417.       frame = [frames objectAtIndex:[self frameNumberForBrowserCell:i]];
  418.       [cell setStringValue:[frame functionName]];
  419.       [cell setLeaf:([frame fileName] == nil)];
  420.       [cell setFrame:frame];
  421.       [cell setTarget:cell];
  422.       [cell setAction:@selector(_selectLineInFile:)];
  423.       [cell setTag:i];
  424.     }
  425.   }
  426.   else if (column == 1) {
  427.     int frameNumber = [self frameNumberForBrowserCell:[sender selectedRowInColumn:0]];
  428.     Frame* frame = [[stack frames] objectAtIndex:frameNumber];
  429.     id cell;
  430.  
  431.     [matrix setPrototype:[[GdbBrowserCell new] autorelease]];
  432.     [stack setSelectedFrame:frameNumber];
  433.  
  434.     if ([frame variablesAreValid]) {
  435.       count = [frame numberOfVariables];
  436.       for (i = 0; i < count; i++) {
  437.         [matrix addRow];
  438.         cell = [matrix cellAtRow:i column:0];
  439.         [cell setObjectToDisplay:[frame variableAtIndex:i]];
  440.       }
  441.     }
  442.     else
  443.       [frame getVariablesFromGDB];
  444.   }
  445.   else if (column > 1) {
  446.     int frameNumber = [self frameNumberForBrowserCell:[sender selectedRowInColumn:0]];
  447.     Frame* frame = [[stack frames] objectAtIndex:frameNumber];
  448.     id displayableObject;
  449.     NSArray* components;
  450.     int i, count, index;
  451.  
  452.     [matrix setPrototype:[[GdbBrowserCell new] autorelease]];
  453.     [stack setSelectedFrame:frameNumber];
  454.  
  455.     index = [[sender matrixInColumn:1] selectedRow];
  456.     displayableObject = [frame variableAtIndex:index];
  457.  
  458.     /* Determine the indirected variable we must show */
  459.     for (i = 2; i < column; i++) {
  460.       index = [[sender matrixInColumn:i] selectedRow];
  461.       displayableObject = [[displayableObject indirectedComponents] objectAtIndex:index];
  462.     }
  463.  
  464.     /* Now we have the variable we have to display. If its indirected value is
  465.       known already display them, otherwise issue a query to gdb to get them.
  466.     */
  467.     if ([displayableObject indirectedComponentsAreKnown]) {
  468.       BOOL displayableObjectIsArray
  469.           = [[displayableObject value] isKindOfClass:[ArrayValue class]];
  470.       id cell;
  471.  
  472.       components = [displayableObject indirectedComponents];
  473.       count = [components count];
  474.       for (i = 0; i < count; i++) {
  475.         [matrix addRow];
  476.         cell = [matrix cellAtRow:i column:0];
  477.         [cell setObjectToDisplay:[components objectAtIndex:i]];
  478.         [cell setObjectIsArrayComponent:displayableObjectIsArray];
  479.       }
  480.     }
  481.     else
  482.       [displayableObject getIndirectedComponentsFromGDB];
  483.   }
  484. }
  485.  
  486. - (int)frameNumberForBrowserCell:(int)row
  487. {
  488.   return [[stack frames] count] - row - 1;
  489. }
  490.  
  491. - (int)browserCellForFrame:(int)frameNumber
  492. {
  493.   return [[stack frames] count] - frameNumber - 1;
  494. }
  495.  
  496.  
  497. /* Changing the appearence of stack browser */
  498. - (void)stackChanged
  499. {
  500.   [stackBrowser loadColumnZero];
  501. }
  502.  
  503. - (void)updateCurrentFrame
  504. {
  505.   [stackBrowser reloadColumn:[stackBrowser lastColumn]];
  506. }
  507.  
  508. /* Other methods */
  509. - (id)gdbManager        { return gdbManager; }
  510. - (id)stackBrowser        { return stackBrowser; }
  511.  
  512. - (void)selectInFile:(NSString*)file startLine:(int)sl endLine:(int)el
  513. {
  514.   Document* document;
  515.  
  516.   if ([Document openDocumentWithPath:file encoding:UnknownStringEncoding]) {
  517.     document = [Document documentForPath:file];
  518.     [document selectFromLine:sl toEndLine:el];
  519.     [document jumpToSelection:nil];
  520.   }
  521. }
  522.  
  523. - (void)invalidateCurrentFrameVariables
  524. {
  525.   int selectedRow, frameNumber;
  526.  
  527.   if ((selectedRow = [stackBrowser selectedRowInColumn:0]) >= 0) {
  528.     frameNumber = [self frameNumberForBrowserCell:selectedRow];
  529.     [[[stack frames] objectAtIndex:frameNumber]
  530.       invalidateCurrentVariables];
  531.     [self updateCurrentFrame];
  532.   }
  533. }
  534.  
  535. @end
  536.