⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tclwindde.c

📁 这是leon3处理器的交叉编译链
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  * tclWinDde.c -- * *	This file provides procedures that implement the "send" *	command, allowing commands to be passed from interpreter *	to interpreter. * * Copyright (c) 1997 by Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclWinDde.c,v 1.8 2002/01/18 14:07:40 dgp Exp $ */#include "tclPort.h"#include <ddeml.h>/* * TCL_STORAGE_CLASS is set unconditionally to DLLEXPORT because the * Registry_Init declaration is in the source file itself, which is only * accessed when we are building a library. */#undef TCL_STORAGE_CLASS#define TCL_STORAGE_CLASS DLLEXPORT/*  * The following structure is used to keep track of the interpreters * registered by this process. */typedef struct RegisteredInterp {    struct RegisteredInterp *nextPtr;				/* The next interp this application knows				 * about. */    char *name;			/* Interpreter's name (malloc-ed). */    Tcl_Interp *interp;		/* The interpreter attached to this name. */} RegisteredInterp;/* * Used to keep track of conversations. */typedef struct Conversation {    struct Conversation *nextPtr;				/* The next conversation in the list. */    RegisteredInterp *riPtr;	/* The info we know about the conversation. */    HCONV hConv;		/* The DDE handle for this conversation. */    Tcl_Obj *returnPackagePtr;	/* The result package for this conversation. */} Conversation;typedef struct ThreadSpecificData {    Conversation *currentConversations;                                /* A list of conversations currently				 * being processed. */    RegisteredInterp *interpListPtr;                                /* List of all interpreters registered				 * in the current process. */} ThreadSpecificData;static Tcl_ThreadDataKey dataKey;/* * The following variables cannot be placed in thread-local storage. * The Mutex ddeMutex guards access to the ddeInstance. */static HSZ ddeServiceGlobal = 0;static DWORD ddeInstance;       /* The application instance handle given				 * to us by DdeInitialize. */static int ddeIsServer = 0;#define TCL_DDE_VERSION "1.2"#define TCL_DDE_PACKAGE_NAME "dde"#define TCL_DDE_SERVICE_NAME "TclEval"TCL_DECLARE_MUTEX(ddeMutex)/* * Forward declarations for procedures defined later in this file. */static void		    DdeExitProc _ANSI_ARGS_((ClientData clientData));static void		    DeleteProc _ANSI_ARGS_((ClientData clientData));static Tcl_Obj *	    ExecuteRemoteObject _ANSI_ARGS_((				RegisteredInterp *riPtr, 				Tcl_Obj *ddeObjectPtr));static int		    MakeDdeConnection _ANSI_ARGS_((Tcl_Interp *interp,				char *name, HCONV *ddeConvPtr));static HDDEDATA CALLBACK    DdeServerProc _ANSI_ARGS_((UINT uType,				UINT uFmt, HCONV hConv, HSZ ddeTopic,				HSZ ddeItem, HDDEDATA hData, DWORD dwData1, 				DWORD dwData2));static void		    SetDdeError _ANSI_ARGS_((Tcl_Interp *interp));int Tcl_DdeObjCmd(ClientData clientData,	/* Used only for deletion */	Tcl_Interp *interp,		/* The interp we are sending from */	int objc,			/* Number of arguments */	Tcl_Obj *CONST objv[]);	/* The arguments */EXTERN int Dde_Init(Tcl_Interp *interp);/* *---------------------------------------------------------------------- * * Dde_Init -- * *	This procedure initializes the dde command. * * Results: *	A standard Tcl result. * * Side effects: *	None. * *---------------------------------------------------------------------- */intDde_Init(    Tcl_Interp *interp){    ThreadSpecificData *tsdPtr;        if (!Tcl_InitStubs(interp, "8.0", 0)) {	return TCL_ERROR;    }    Tcl_CreateObjCommand(interp, "dde", Tcl_DdeObjCmd, NULL, NULL);    tsdPtr = (ThreadSpecificData *)	Tcl_GetThreadData((Tcl_ThreadDataKey *) &dataKey, sizeof(ThreadSpecificData));        if (tsdPtr == NULL) {	tsdPtr = TCL_TSD_INIT(&dataKey);	tsdPtr->currentConversations = NULL;	tsdPtr->interpListPtr = NULL;    }    Tcl_CreateExitHandler(DdeExitProc, NULL);    return Tcl_PkgProvide(interp, TCL_DDE_PACKAGE_NAME, TCL_DDE_VERSION);}/* *---------------------------------------------------------------------- * * Initialize -- * *	Initialize the global DDE instance. * * Results: *	None. * * Side effects: *	Registers the DDE server proc. * *---------------------------------------------------------------------- */static voidInitialize(void){    int nameFound = 0;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);        /*     * See if the application is already registered; if so, remove its     * current name from the registry. The deletion of the command     * will take care of disposing of this entry.     */    if (tsdPtr->interpListPtr != NULL) {	nameFound = 1;    }    /*     * Make sure that the DDE server is there. This is done only once,     * add an exit handler tear it down.     */    if (ddeInstance == 0) {	Tcl_MutexLock(&ddeMutex);	if (ddeInstance == 0) {	    if (DdeInitialize(&ddeInstance, DdeServerProc,		    CBF_SKIP_REGISTRATIONS		    | CBF_SKIP_UNREGISTRATIONS		    | CBF_FAIL_POKES, 0) 		    != DMLERR_NO_ERROR) {		ddeInstance = 0;	    }	}	Tcl_MutexUnlock(&ddeMutex);    }    if ((ddeServiceGlobal == 0) && (nameFound != 0)) {	Tcl_MutexLock(&ddeMutex);	if ((ddeServiceGlobal == 0) && (nameFound != 0)) {	    ddeIsServer = 1;	    Tcl_CreateExitHandler(DdeExitProc, NULL);	    ddeServiceGlobal = DdeCreateStringHandle(ddeInstance, \		    TCL_DDE_SERVICE_NAME, 0);	    DdeNameService(ddeInstance, ddeServiceGlobal, 0L, DNS_REGISTER);	} else {	    ddeIsServer = 0;	}	Tcl_MutexUnlock(&ddeMutex);    }}    /* *-------------------------------------------------------------- * * DdeSetServerName -- * *	This procedure is called to associate an ASCII name with a Dde *	server.  If the interpreter has already been named, the *	name replaces the old one. * * Results: *	The return value is the name actually given to the interp. *	This will normally be the same as name, but if name was already *	in use for a Dde Server then a name of the form "name #2" will *	be chosen,  with a high enough number to make the name unique. * * Side effects: *	Registration info is saved, thereby allowing the "send" command *	to be used later to invoke commands in the application.  In *	addition, the "send" command is created in the application's *	interpreter.  The registration will be removed automatically *	if the interpreter is deleted or the "send" command is removed. * *-------------------------------------------------------------- */static char *DdeSetServerName(    Tcl_Interp *interp,    char *name			/* The name that will be used to				 * refer to the interpreter in later				 * "send" commands.  Must be globally				 * unique. */    ){    int suffix, offset;    RegisteredInterp *riPtr, *prevPtr;    Tcl_DString dString;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    /*     * See if the application is already registered; if so, remove its     * current name from the registry. The deletion of the command     * will take care of disposing of this entry.     */    for (riPtr = tsdPtr->interpListPtr, prevPtr = NULL; riPtr != NULL; 	    prevPtr = riPtr, riPtr = riPtr->nextPtr) {	if (riPtr->interp == interp) {	    if (name != NULL) {		if (prevPtr == NULL) {		    tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr;		} else {		    prevPtr->nextPtr = riPtr->nextPtr;		}		break;	    } else {		/*		 * the name was NULL, so the caller is asking for		 * the name of the current interp.		 */		return riPtr->name;	    }	}    }    if (name == NULL) {	/*	 * the name was NULL, so the caller is asking for	 * the name of the current interp, but it doesn't	 * have a name.	 */	return "";    }        /*     * Pick a name to use for the application.  Use "name" if it's not     * already in use.  Otherwise add a suffix such as " #2", trying     * larger and larger numbers until we eventually find one that is     * unique.     */    suffix = 1;    offset = 0;    Tcl_DStringInit(&dString);    /*     * We have found a unique name. Now add it to the registry.     */    riPtr = (RegisteredInterp *) ckalloc(sizeof(RegisteredInterp));    riPtr->interp = interp;    riPtr->name = ckalloc(strlen(name) + 1);    riPtr->nextPtr = tsdPtr->interpListPtr;    tsdPtr->interpListPtr = riPtr;    strcpy(riPtr->name, name);    Tcl_CreateObjCommand(interp, "dde", Tcl_DdeObjCmd,	    (ClientData) riPtr, DeleteProc);    if (Tcl_IsSafe(interp)) {	Tcl_HideCommand(interp, "dde", "dde");    }    Tcl_DStringFree(&dString);    /*     * re-initialize with the new name     */    Initialize();        return riPtr->name;}/* *-------------------------------------------------------------- * * DeleteProc * *	This procedure is called when the command "dde" is destroyed. * * Results: *	none * * Side effects: *	The interpreter given by riPtr is unregistered. * *-------------------------------------------------------------- */static voidDeleteProc(clientData)    ClientData clientData;	/* The interp we are deleting passed				 * as ClientData. */{    RegisteredInterp *riPtr = (RegisteredInterp *) clientData;    RegisteredInterp *searchPtr, *prevPtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);    for (searchPtr = tsdPtr->interpListPtr, prevPtr = NULL;	    (searchPtr != NULL) && (searchPtr != riPtr);	    prevPtr = searchPtr, searchPtr = searchPtr->nextPtr) {	/*	 * Empty loop body.	 */    }    if (searchPtr != NULL) {	if (prevPtr == NULL) {	    tsdPtr->interpListPtr = tsdPtr->interpListPtr->nextPtr;	} else {	    prevPtr->nextPtr = searchPtr->nextPtr;	}    }    ckfree(riPtr->name);    Tcl_EventuallyFree(clientData, TCL_DYNAMIC);}/* *-------------------------------------------------------------- * * ExecuteRemoteObject -- * *	Takes the package delivered by DDE and executes it in *	the server's interpreter. * * Results: *	A list Tcl_Obj * that describes what happened. The first *	element is the numerical return code (TCL_ERROR, etc.). *	The second element is the result of the script. If the *	return result was TCL_ERROR, then the third element *	will be the value of the global "errorCode", and the *	fourth will be the value of the global "errorInfo". *	The return result will have a refCount of 0. * * Side effects: *	A Tcl script is run, which can cause all kinds of other *	things to happen. * *-------------------------------------------------------------- */static Tcl_Obj *ExecuteRemoteObject(    RegisteredInterp *riPtr,	    /* Info about this server. */    Tcl_Obj *ddeObjectPtr)	    /* The object to execute. */{    Tcl_Obj *errorObjPtr;    Tcl_Obj *returnPackagePtr;    int result;    result = Tcl_EvalObjEx(riPtr->interp, ddeObjectPtr, TCL_EVAL_GLOBAL);    returnPackagePtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL);    Tcl_ListObjAppendElement(NULL, returnPackagePtr,	    Tcl_NewIntObj(result));    Tcl_ListObjAppendElement(NULL, returnPackagePtr,	    Tcl_GetObjResult(riPtr->interp));    if (result == TCL_ERROR) {	errorObjPtr = Tcl_GetVar2Ex(riPtr->interp, "errorCode", NULL,		TCL_GLOBAL_ONLY);	Tcl_ListObjAppendElement(NULL, returnPackagePtr, errorObjPtr);	errorObjPtr = Tcl_GetVar2Ex(riPtr->interp, "errorInfo", NULL,		TCL_GLOBAL_ONLY);        Tcl_ListObjAppendElement(NULL, returnPackagePtr, errorObjPtr);    }    return returnPackagePtr;}/* *-------------------------------------------------------------- * * DdeServerProc -- * *	Handles all transactions for this server. Can handle *	execute, request, and connect protocols. Dde will *	call this routine when a client attempts to run a dde *	command using this server. * * Results: *	A DDE Handle with the result of the dde command. * * Side effects: *	Depending on which command is executed, arbitrary *	Tcl scripts can be run. * *-------------------------------------------------------------- */static HDDEDATA CALLBACKDdeServerProc (    UINT uType,			/* The type of DDE transaction we				 * are performing. */    UINT uFmt,			/* The format that data is sent or				 * received. */    HCONV hConv,		/* The conversation associated with the 				 * current transaction. */    HSZ ddeTopic,		/* A string handle. Transaction-type 				 * dependent. */    HSZ ddeItem,		/* A string handle. Transaction-type 				 * dependent. */    HDDEDATA hData,		/* DDE data. Transaction-type dependent. */    DWORD dwData1,		/* Transaction-dependent data. */    DWORD dwData2)		/* Transaction-dependent data. */{    Tcl_DString dString;    int len;    char *utilString;    Tcl_Obj *ddeObjectPtr;    HDDEDATA ddeReturn = NULL;    RegisteredInterp *riPtr;    Conversation *convPtr, *prevConvPtr;    ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -