ftp.nice.ch/Attic/openStep/developer/bundles/GDBbundle.1.0.s.tgz#/GDBbundle-1.0.s/debug/gdb/gdb/next/DisplaySupport/TellDisplayer.m

This is TellDisplayer.m in view mode; [Download] [Up]

#import <stdio.h>
#import <Foundation/Foundation.h>
#import "GdbManager.h"
#import "DisplayMisc.h"
#import "TellDisplayer.h"
#import "ViewDisplayProvider_Protocol.h"
#import "GuiDisplayProvider_Protocol.h"
#import "debug.h"
#import "gdb.h"
#include <sys/param.h>
#include <sys/stat.h>
#include <fcntl.h>

// gdbManager is the object which manages GDB and the thread it runs in.
// This object communicates with the client (in another process)
// and the DebuggerServer object in our process but in
// another thread.

static GdbManager		*gdbManager = nil;

// The autorelease pool is needed because the DO facilities use it.
// Since the gdb thread isn't in a Run Loop, we have to manage
// the pool ourself and when it gets released.

NSAutoreleasePool	*pool;
int			pool_num_times = 0;

extern	WindowHookFunction	window_hook;

static	int		disp_is_view;


int
setup_display_system(const char *connection_name)
{

    
    pool = [[NSAutoreleasePool alloc] init];

    if (connection_name) {
        const char	*conn_host;
        const char	*c;
        char		new_conn[256];
        char		*nc;
        
        c = connection_name;
        nc = new_conn;
        conn_host = NULL;
        while (*c != '\0') {
            *nc = *c;
            if (*c == ':') {
                *nc = '\0';
                conn_host = c + 1;
                connection_name = new_conn;
                break;
            }
            nc++;
            c++;
        }
        gdbManager = make_gui_gdb_manager();
        [gdbManager setDisplayProviderConnectionName:connection_name
                                                host:conn_host];
        disp_is_view = 0;
    }
    else {
        extern char *get_view_connection();
        extern char *get_view_host();
        
	gdbManager = make_view_gdb_manager();
        [gdbManager setDisplayProviderConnectionName:get_view_connection()
                                                host:get_view_host()];
        disp_is_view = 1;
    }
   
#if 0
    { /* utility code which causes gdb to wait. We can
	 then attach with another gdb.*/
      static volatile wait = 1;

      while (wait) {
	sleep(10);
      }

    }
#endif

    if ([gdbManager establishConnection] == 0) {
	[gdbManager release];
	[pool release];
	return 0;
    }

    window_hook = [gdbManager windowHookFunction];
    return 1;
}

void
shut_down_display_system()
{
    window_hook = NULL;
    if (gdbManager) {
        [gdbManager release];
        gdbManager = nil;
    }
    if (pool) {
        [pool release];
        pool_num_times = 0;
        pool = nil;
    }
    if (disp_is_view)
        (void)turn_off_viewing();
    else {
      extern	int do_display_lines;
      do_display_lines = 0;
    }   
}    

static void
get_full_path_name(char *filename, char **fullname)
{
    extern char	*source_path;
    int		fd;

    fd = openp (source_path, 0, filename, O_RDONLY, 0, fullname);
    if (fd > 0)
	close(fd);
}

// 'localException' is defined by NS_HANDLER
#define EXCEPTION_MSG(func)	\
	NSLog(@"Exception sending remote message(%@); name: %@, reason: %@", \
	      func, [localException name], [localException reason]);


void
tell_displayer_display_lines(struct symtab	*symtab,
                             int		first_line,
                             int 		last_line)
{
    id<ViewDisplayProvider>	displayProvider;

    if (gdbManager == nil)
        return;

    if (symtab->fullname == NULL)
	get_full_path_name(symtab->filename, &symtab->fullname);
    
    NS_DURING {
        displayProvider = [gdbManager
                displayProviderForProtocol:@protocol(ViewDisplayProvider)];

        if (displayProvider) {
            /* rooted path */
            NSString *fileString = [NSString
				    stringWithCString: symtab->fullname];
/* is this NSString malloc'd? is it freed?  is it pooled? */
            [displayProvider lineChangedForThread: -1
                                           inFile: fileString
                                      atStartLine: first_line
                                        toEndLine: last_line];
        }
    }
    NS_HANDLER {
	EXCEPTION_MSG(@"display_lines");
	shut_down_display_system();
    }
    NS_ENDHANDLER;
    return;
}



void
tell_displayer_state_changed(DebuggerState newState)
{
    id<ViewDisplayProvider>	displayProvider;
    static DebuggerState	prevState = DBG_STATE_NOT_ACTIVE;
    
    if (gdbManager == nil)
        return;

    /* This is a workaround. For some reason, the NeXT code calls us
       many (e.g. 8) times with newState == DBG_STATE_INFERIOR_RUNNING.
       This results in unnecessary DO communication and makes single stepping
       slow. So, don't send multiple messages with the same state.
     */
    if ((newState == DBG_STATE_INFERIOR_RUNNING) && (newState == prevState))
	return;
    prevState = newState;
    
    NS_DURING {
        displayProvider = [gdbManager
                displayProviderForProtocol:@protocol(ViewDisplayProvider)];

        if (displayProvider) {
            [displayProvider inferiorStateChanged: newState];
        }
    }
    NS_HANDLER {
	EXCEPTION_MSG(@"state_changed");
	shut_down_display_system();
    }
    NS_ENDHANDLER;
    return;
}

void
tell_displayer_breakpoint_changed(struct breakpoint 	*bp,
                                  BreakpointState	newState)
{
    char fullname[2048], *fp;
    id<GuiDisplayProvider>	displayProvider;

    if (gdbManager == nil)
        return;

    /* for now, only care about real breakpoints */
    /* will need to deal with other types too */
    if ((bp->number == 0) || (bp->type != bp_breakpoint))
	return;			

#if 0
    /*
     * the breakpoint structure no longer contains a symtab member.
     * Instead, it just has a char pointer that holds a file name
     * (which is evidently the main thing that the symtab member 
     * was used for).
     */
 
    if (bp->symtab->fullname == NULL)
	get_full_path_name(bp->symtab);
#else /* 1 */
    /*
     * I do not know whether the filename pointer of the breakpoint struct
     * is normally a full path or not.  If it is not a full path, I do not
     * know what effect it might have, if we replaced it with a full path.
     * Since I don't know, for the time being I'm not going to do it.
     *
     * This means that we may be recomputing the full path over and over.
     * That needs to be addressed (FIXME).  Moreover, I don't think that
     * the way get_full_path_name works (ie. by calling open) is very
     * efficient.  MVS
     */
    fp = bp->source_file;
    if (fp == NULL)
        return;
    else if (fp[0] != '/') { /* rooted path? */
        get_full_path_name(fp, &fp);
        /* could copy back into bp if considered safe */
        /* AND... the sonofabitch is malloc'd.  We're leaking it. */
        if ((fp == NULL) || (fp[0] != '/'))
            return;
    }
#endif

    NS_DURING {
        displayProvider = [gdbManager
                displayProviderForProtocol:@protocol(GuiDisplayProvider)];

        if (displayProvider) {
            /* rooted path */
            NSString *fileString = [NSString
				    stringWithCString: fp]; /* full path */

            [displayProvider breakpointChanged:bp->number
                                      newState:newState
                                        inFile:fileString
	                                atLine:bp->line_number];
        }
    }
    NS_HANDLER {
	EXCEPTION_MSG(@"breakpoint_changed");
	shut_down_display_system();
    }
    NS_ENDHANDLER;
    return;
}


void
tell_displayer_frame_changed(int newFrame)
{
    id<GuiDisplayProvider>	displayProvider;

    if (gdbManager == nil)
        return;

    NS_DURING {
        displayProvider = [gdbManager
                displayProviderForProtocol:@protocol(GuiDisplayProvider)];

        if (displayProvider) {
            [displayProvider frameChanged: newFrame];
        }
    }
    NS_HANDLER {
        EXCEPTION_MSG(@"frame_changed");
        shut_down_display_system();
    }
    NS_ENDHANDLER;
    return;
}


#define		STACK_LIMIT (99)

void
tell_displayer_stack_changed()
{
    id<GuiDisplayProvider>	displayProvider;
    struct frame_info		*frame0;
    int 			numFrames;
    struct frame_info		*f;
    BOOL			maxedOut;
    
    if (gdbManager == nil)
        return;

    frame0 = get_current_frame();

    if (frame0 == NULL) {
        /* no stack... */
        return;
    }


    /* count how many frames there are;
       include frame 0, so start at 1*/
    numFrames = 1;
    maxedOut = NO;
    for (f = get_prev_frame(frame0);
         f && (f != frame0);
         f = get_prev_frame(f))  {
        numFrames++;
        if (numFrames >= STACK_LIMIT) {
            maxedOut = YES;
            break;
        }
    }
    
    NS_DURING {
        displayProvider = [gdbManager
                displayProviderForProtocol:@protocol(GuiDisplayProvider)];

        if (displayProvider) {
            [displayProvider stackChanged:numFrames
                             limitReached:maxedOut];
        }
    }
    NS_HANDLER {
        EXCEPTION_MSG(@"stack_changed");
        shut_down_display_system();
    }
    NS_ENDHANDLER;
    return;
}



void gui_inferior_stopped(int newFrame /* true current frame is different
					  from previous one
					*/
			  )
{
  }

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.