/* Frame.m created by ovidiu on Sun 23-Mar-1997 */

#import <Foundation/Foundation.h>
#import "GdbDisplayController.h"
#import "DebuggerController_Protocol.h"
#import "NSScannerAddition.h"
#import "Stack.h"
#import "Frame.h"
#import "Variable.h"

@implementation Frame

+ (Frame*)frameWithAnnotation:(NSString*)annotation stack:(Stack*)theStack
{
  NSScanner* scanner = [NSScanner scannerWithString:annotation];

  Frame* frame = [[self new] autorelease];

  if (![scanner scanAfterString:@"\032\032frame-begin"])
    return nil;
  [scanner scanInt:&frame->frameNumber];
  [scanner scanHexInt:&frame->frameAddress];

  if (![scanner scanAfterString:@"\032\032frame-function-name\n"])
    return nil;
  if (![scanner scanUpToString:@"\n" intoString:&(frame->functionName)])
    return nil;
  [frame->functionName retain];

  [scanner scanAfterString:@"\032\032frame-source-file\n"];
  [scanner scanUpToString:@"\n" intoString:&(frame->fileName)];
  [frame->fileName retain];

  frame->stack = theStack;
  return frame;
}

- init
{
  self = [super init];
  variables = [NSMutableArray new];
  return self;
}

- (void)dealloc
{
  [functionName release];
  [super dealloc];
}

- (void)invalidateCurrentVariables
{
  validVariables = NO;
}

- (void)getVariablesFromGDB
{
#if 1
  [variables removeAllObjects];
  if (!validVariables) {
    validVariables = YES;
#else
  if (![variables count]) {
#endif
//    NSLog (@"getVariablesFromGDB: frame number = %d", frameNumber);
    [[self gdbController] executeGDBCommand:@"info typed-variables"
                                      annotate:NO
                                  notifyObject:self
                                      selector:@selector(frameArguments:type:)];
  }
}

- (void)frameArguments:(NSString*)gdbOutput type:(GdbOutputType)type
{
  int i, count;
  id gdbController;

  if (type != GDB_OUTPUT_ANNOTATION)
    return;

  gdbController = [self gdbController];
  [variables release];
  variables = [[Variable variablesFromDescription:gdbOutput] retain];

  for (i = 0, count = [variables count]; i < count; i++)
    [[variables objectAtIndex:i] setGdbDisplayController:gdbController];

  validVariables = YES;
  [gdbController updateCurrentFrame];
}

- (void)setFilename:(NSString*)_fileName
          startLine:(int)_startLine
            endLine:(int)_endLine
{
  [_fileName retain];
  [fileName release];
  fileName = _fileName;
  startLine = _startLine;
  endLine = _endLine;
}

- (Variable*)variableAtIndex:(int)index
{
  return [variables objectAtIndex:index];
}

- (void)selectLineInFile
{
//  NSLog (@"_selectLineInFile: gdbController = %x, fileName = %@, "
//         @"startLine = %d, endLine = %d",
//         [self gdbController], fileName, startLine, endLine);

  [stack setSelectedFrame:frameNumber];
  if (fileName)
    [[self gdbController] selectInFile:fileName startLine:startLine endLine:endLine];
}

- (int)frameNumber			{ return frameNumber; }
- (NSString*)functionName		{ return functionName; }
- (NSString*)fileName			{ return fileName; }
- (GdbDisplayController*)gdbController	{ return [stack gdbController]; }
- (int)numberOfVariables		{ return [variables count]; }
- (BOOL)variablesAreValid		{ return validVariables; }
- (int)startLine			{ return startLine; }
- (int)endLine				{ return endLine; }

- (NSString*)description
{
  return functionName;
}

@end
