gecko-dev/lib/libmocha/lm_jsd.c

337 строки
8.4 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
/*
* JSDebug StreamConverter hooks for source text in Navigator
*/
/* Please leave outside of ifdef for windows precompiled headers */
#include "lm.h"
#include "net.h"
#include "prlink.h"
#ifdef JSDEBUGGER
#include "jsdebug.h"
/***************************************/
/* a static global, oh well... */
static JSDContext* g_jsdc = NULL;
typedef struct
{
NET_StreamClass* next_stream;
JSDSourceText* jsdsrc;
} LocalData;
/***************************************/
/* support for dynamic library load and calling */
/* these must match declarations in jsdebug.h */
typedef void
(*SetUserCallbacksProc)(JSRuntime* jsruntime, JSD_UserCallbacks* callbacks, void* user);
typedef JSDSourceText*
(*NewSourceTextProc)(JSDContext* jsdc, const char* url);
typedef JSDSourceText*
(*AppendSourceTextProc)(JSDContext* jsdc,
JSDSourceText* jsdsrc,
const char* text, /* *not* zero terminated */
size_t length,
JSDSourceStatus status);
static SetUserCallbacksProc g_SetUserCallbacks = NULL;
static NewSourceTextProc g_NewSourceText = NULL;
static AppendSourceTextProc g_AppendSourceText = NULL;
static PRLibrary* g_JSDModule = NULL;
#ifdef XP_PC
#if defined(_WIN32) || defined(XP_OS2)
static char moduleName[] = "jsd3240.dll";
#else
static char moduleName[] = "jsd1640.dll";
#endif /* _WIN32 */
#endif /* XP_PC */
#ifdef XP_MAC
static char moduleName[] = "JavaScript Debug Support";
#endif
#ifdef XP_UNIX
static char moduleName[] = "libjsd";
#endif /*XP_UNIX */
#ifdef XP_UNIX
static PRLibrary*
LoadUnixLibrary(const char *name)
{
PRLibrary* lib = NULL;
char* libPath;
char* fullname;
const char* rawLibPath;
char* cur;
char* next;
rawLibPath = PR_GetLibraryPath();
if( ! rawLibPath )
return NULL;
cur = libPath = strdup(rawLibPath);
if( ! libPath )
return NULL;
do
{
next = strchr(cur, ':');
if(next)
*next++ = 0;
if( cur[strlen(cur)-1] == '/' )
fullname = PR_smprintf("%s%s.%s", cur, name, DLL_SUFFIX);
else
fullname = PR_smprintf("%s/%s.%s", cur, name, DLL_SUFFIX);
lib = PR_LoadLibrary(fullname);
free(fullname);
if( lib )
break;
cur = next;
} while( cur && *cur );
free(libPath);
return lib;
}
#endif /*XP_UNIX */
static void
UnLoadJSDModule(void)
{
if( g_JSDModule )
PR_UnloadLibrary(g_JSDModule);
g_JSDModule = NULL;
g_SetUserCallbacks = NULL;
g_NewSourceText = NULL;
g_AppendSourceText = NULL;
}
static int
LoadJSDModuleAndCallbacks(void)
{
#ifdef XP_MAC
const char *libPath = PR_GetLibraryPath();
PR_SetLibraryPath( "/usr/local/netscape/" );
g_JSDModule = PR_LoadLibrary(moduleName);
/* set path back to original path (don't have ourselves in list) */
PR_SetLibraryPath( libPath );
#elif defined(XP_UNIX)
g_JSDModule = LoadUnixLibrary(moduleName);
#else
g_JSDModule = PR_LoadLibrary(moduleName);
#endif
if( ! g_JSDModule )
return 0;
g_SetUserCallbacks = (SetUserCallbacksProc) PR_FindSymbol( g_JSDModule, "JSD_SetUserCallbacks");
g_NewSourceText = (NewSourceTextProc ) PR_FindSymbol( g_JSDModule, "JSD_NewSourceText");
g_AppendSourceText = (AppendSourceTextProc) PR_FindSymbol( g_JSDModule, "JSD_AppendSourceText");
if( ! g_SetUserCallbacks ||
! g_NewSourceText ||
! g_AppendSourceText )
{
UnLoadJSDModule();
return 0;
}
return 1;
}
/***************************************/
/* helpers */
PR_STATIC_CALLBACK(void)
lmjsd_SetContext(JSDContext* jsdc, void* user)
{
g_jsdc = jsdc;
}
static void cleanup_ld( LocalData* ld )
{
if( ld )
{
XP_FREEIF(ld->next_stream);
XP_FREE(ld);
}
}
/***************************************/
/* converter callbacks */
PR_STATIC_CALLBACK(int)
lmjsd_CvtPutBlock (NET_StreamClass *stream, const char *str, int32 len)
{
LocalData* ld = (LocalData*) stream->data_object;
if( g_jsdc && ld->jsdsrc )
ld->jsdsrc = g_AppendSourceText(g_jsdc, ld->jsdsrc,
str, len, JSD_SOURCE_PARTIAL );
return ((*ld->next_stream->put_block)(ld->next_stream,str,len));
}
PR_STATIC_CALLBACK(void)
lmjsd_CvtComplete (NET_StreamClass *stream)
{
LocalData* ld = (LocalData*) stream->data_object;
if( g_jsdc && ld->jsdsrc )
g_AppendSourceText(g_jsdc, ld->jsdsrc,
NULL, 0, JSD_SOURCE_COMPLETED );
(*ld->next_stream->complete)(ld->next_stream);
cleanup_ld(ld);
}
PR_STATIC_CALLBACK(void)
lmjsd_CvtAbort (NET_StreamClass *stream, int status)
{
LocalData* ld = (LocalData*) stream->data_object;
if( g_jsdc && ld->jsdsrc )
g_AppendSourceText(g_jsdc, ld->jsdsrc,
NULL, 0, JSD_SOURCE_ABORTED );
(*ld->next_stream->abort)(ld->next_stream, status);
cleanup_ld(ld);
}
PR_STATIC_CALLBACK(unsigned int)
lmjsd_CvtWriteReady (NET_StreamClass *stream)
{
LocalData* ld = (LocalData*) stream->data_object;
return (*ld->next_stream->is_write_ready)(ld->next_stream);
}
/***************************************/
/* exported functions */
void
lm_InitJSDebug(JSRuntime *jsruntime)
{
JSD_UserCallbacks cbs;
if( LoadJSDModuleAndCallbacks() )
{
memset(&cbs, 0, sizeof(JSD_UserCallbacks) );
cbs.size = sizeof(JSD_UserCallbacks);
cbs.setContext = lmjsd_SetContext;
g_SetUserCallbacks( jsruntime, &cbs, &g_jsdc ); /* &g_jsdc is just a unique address */
}
}
void
lm_ExitJSDebug(JSRuntime *jsruntime)
{
if( g_SetUserCallbacks )
g_SetUserCallbacks( jsruntime, NULL, &g_jsdc ); /* &g_jsdc is just a unique address */
g_jsdc = NULL;
UnLoadJSDModule();
}
JSBool
LM_GetJSDebugActive(void)
{
return (JSBool)(NULL != g_jsdc);
}
void
LM_JamSourceIntoJSDebug( const char *filename,
const char *str,
int32 len,
MWContext *mwcontext )
{
JSDSourceText* jsdsrc;
if( ! g_jsdc )
return;
jsdsrc = g_NewSourceText(g_jsdc, filename);
if( jsdsrc )
jsdsrc = g_AppendSourceText(g_jsdc, jsdsrc,
str, len, JSD_SOURCE_PARTIAL );
if( jsdsrc )
g_AppendSourceText(g_jsdc, jsdsrc,
NULL, 0, JSD_SOURCE_COMPLETED );
}
extern NET_StreamClass*
LM_StreamBuilder( int format_out,
void *data_obj,
URL_Struct *URL_s,
MWContext *mwcontext )
{
LocalData* ld;
NET_StreamClass* stream;
/* If JSDebug is not active, then don't link into chain */
if( ! g_jsdc )
return NET_StreamBuilder(format_out, URL_s, mwcontext);
if( ! (ld = XP_NEW_ZAP(LocalData)) ||
! (ld->jsdsrc = g_NewSourceText(g_jsdc, URL_s->address)) )
{
cleanup_ld(ld);
return NET_StreamBuilder(format_out, URL_s, mwcontext);
}
if( ! (stream = NET_NewStream("JSDebuggerConverter", lmjsd_CvtPutBlock,
lmjsd_CvtComplete, lmjsd_CvtAbort,
lmjsd_CvtWriteReady, ld, mwcontext)) )
{
g_AppendSourceText(g_jsdc, ld->jsdsrc, NULL, 0, JSD_SOURCE_FAILED);
cleanup_ld(ld);
return NET_StreamBuilder(format_out, URL_s, mwcontext);
}
if( ! (ld->next_stream = NET_StreamBuilder(format_out, URL_s, mwcontext)) )
{
g_AppendSourceText(g_jsdc, ld->jsdsrc, NULL, 0, JSD_SOURCE_FAILED);
cleanup_ld(ld);
XP_FREE(stream);
return NULL;
}
return stream;
}
#endif /* JSDEBUGGER */