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

📄 itcl_linkage.c

📁 linux 下的源代码分析阅读器 red hat公司新版
💻 C
字号:
/* * ------------------------------------------------------------------------ *      PACKAGE:  [incr Tcl] *  DESCRIPTION:  Object-Oriented Extensions to Tcl * *  [incr Tcl] provides object-oriented extensions to Tcl, much as *  C++ provides object-oriented extensions to C.  It provides a means *  of encapsulating related procedures together with their shared data *  in a local namespace that is hidden from the outside world.  It *  promotes code re-use through inheritance.  More than anything else, *  it encourages better organization of Tcl applications through the *  object-oriented paradigm, leading to code that is easier to *  understand and maintain. * *  This part adds a mechanism for integrating C procedures into *  [incr Tcl] classes as methods and procs.  Each C procedure must *  either be declared via Itcl_RegisterC() or dynamically loaded. * * ======================================================================== *  AUTHOR:  Michael J. McLennan *           Bell Labs Innovations for Lucent Technologies *           mmclennan@lucent.com *           http://www.tcltk.com/itcl * *     RCS:  $Id: itcl_linkage.c 144 2003-02-05 10:56:26Z mdejong $ * ======================================================================== *           Copyright (c) 1993-1998  Lucent Technologies, Inc. * ------------------------------------------------------------------------ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. */#include "itclInt.h"/* *  These records store the pointers for all "RegisterC" functions. */typedef struct ItclCfunc {    Tcl_CmdProc *argCmdProc;        /* old-style (argc,argv) command handler */    Tcl_ObjCmdProc *objCmdProc;     /* new (objc,objv) command handler */    ClientData clientData;          /* client data passed into this function */    Tcl_CmdDeleteProc *deleteProc;  /* proc called to free clientData */} ItclCfunc;static Tcl_HashTable* ItclGetRegisteredProcs _ANSI_ARGS_((Tcl_Interp *interp));static void ItclFreeC _ANSI_ARGS_((ClientData clientData, Tcl_Interp *interp));/* * ------------------------------------------------------------------------ *  Itcl_RegisterC() * *  Used to associate a symbolic name with an (argc,argv) C procedure *  that handles a Tcl command.  Procedures that are registered in this *  manner can be referenced in the body of an [incr Tcl] class *  definition to specify C procedures to acting as methods/procs. *  Usually invoked in an initialization routine for an extension, *  called out in Tcl_AppInit() at the start of an application. * *  Each symbolic procedure can have an arbitrary client data value *  associated with it.  This value is passed into the command *  handler whenever it is invoked. * *  A symbolic procedure name can be used only once for a given style *  (arg/obj) handler.  If the name is defined with an arg-style *  handler, it can be redefined with an obj-style handler; or if *  the name is defined with an obj-style handler, it can be redefined *  with an arg-style handler.  In either case, any previous client *  data is discarded and the new client data is remembered.  However, *  if a name is redefined to a different handler of the same style, *  this procedure returns an error. * *  Returns TCL_OK on success, or TCL_ERROR (along with an error message *  in interp->result) if anything goes wrong. * ------------------------------------------------------------------------ */intItcl_RegisterC(interp, name, proc, clientData, deleteProc)    Tcl_Interp *interp;             /* interpreter handling this registration */    char *name;                     /* symbolic name for procedure */    Tcl_CmdProc *proc;              /* procedure handling Tcl command */    ClientData clientData;          /* client data associated with proc */    Tcl_CmdDeleteProc *deleteProc;  /* proc called to free up client data */{    int newEntry;    Tcl_HashEntry *entry;    Tcl_HashTable *procTable;    ItclCfunc *cfunc;    /*     *  Make sure that a proc was specified.     */    if (!proc) {        Tcl_AppendResult(interp, "initialization error: null pointer for ",            "C procedure \"", name, "\"",            (char*)NULL);        return TCL_ERROR;    }    /*     *  Add a new entry for the given procedure.  If an entry with     *  this name already exists, then make sure that it was defined     *  with the same proc.     */    procTable = ItclGetRegisteredProcs(interp);    entry = Tcl_CreateHashEntry(procTable, name, &newEntry);    if (!newEntry) {        cfunc = (ItclCfunc*)Tcl_GetHashValue(entry);        if (cfunc->argCmdProc != NULL && cfunc->argCmdProc != proc) {            Tcl_AppendResult(interp, "initialization error: C procedure ",                "with name \"", name, "\" already defined",                (char*)NULL);            return TCL_ERROR;        }        if (cfunc->deleteProc != NULL) {            (*cfunc->deleteProc)(cfunc->clientData);        }    }    else {        cfunc = (ItclCfunc*)ckalloc(sizeof(ItclCfunc));        cfunc->objCmdProc = NULL;    }    cfunc->argCmdProc = proc;    cfunc->clientData = clientData;    cfunc->deleteProc = deleteProc;    Tcl_SetHashValue(entry, (ClientData)cfunc);    return TCL_OK;}/* * ------------------------------------------------------------------------ *  Itcl_RegisterObjC() * *  Used to associate a symbolic name with an (objc,objv) C procedure *  that handles a Tcl command.  Procedures that are registered in this *  manner can be referenced in the body of an [incr Tcl] class *  definition to specify C procedures to acting as methods/procs. *  Usually invoked in an initialization routine for an extension, *  called out in Tcl_AppInit() at the start of an application. * *  Each symbolic procedure can have an arbitrary client data value *  associated with it.  This value is passed into the command *  handler whenever it is invoked. * *  A symbolic procedure name can be used only once for a given style *  (arg/obj) handler.  If the name is defined with an arg-style *  handler, it can be redefined with an obj-style handler; or if *  the name is defined with an obj-style handler, it can be redefined *  with an arg-style handler.  In either case, any previous client *  data is discarded and the new client data is remembered.  However, *  if a name is redefined to a different handler of the same style, *  this procedure returns an error. * *  Returns TCL_OK on success, or TCL_ERROR (along with an error message *  in interp->result) if anything goes wrong. * ------------------------------------------------------------------------ */intItcl_RegisterObjC(interp, name, proc, clientData, deleteProc)    Tcl_Interp *interp;     /* interpreter handling this registration */    char *name;             /* symbolic name for procedure */    Tcl_ObjCmdProc *proc;   /* procedure handling Tcl command */    ClientData clientData;          /* client data associated with proc */    Tcl_CmdDeleteProc *deleteProc;  /* proc called to free up client data */{    int newEntry;    Tcl_HashEntry *entry;    Tcl_HashTable *procTable;    ItclCfunc *cfunc;    /*     *  Make sure that a proc was specified.     */    if (!proc) {        Tcl_AppendResult(interp, "initialization error: null pointer for ",            "C procedure \"", name, "\"",            (char*)NULL);        return TCL_ERROR;    }    /*     *  Add a new entry for the given procedure.  If an entry with     *  this name already exists, then make sure that it was defined     *  with the same proc.     */    procTable = ItclGetRegisteredProcs(interp);    entry = Tcl_CreateHashEntry(procTable, name, &newEntry);    if (!newEntry) {        cfunc = (ItclCfunc*)Tcl_GetHashValue(entry);        if (cfunc->objCmdProc != NULL && cfunc->objCmdProc != proc) {            Tcl_AppendResult(interp, "initialization error: C procedure ",                "with name \"", name, "\" already defined",                (char*)NULL);            return TCL_ERROR;        }        if (cfunc->deleteProc != NULL) {            (*cfunc->deleteProc)(cfunc->clientData);        }    }    else {        cfunc = (ItclCfunc*)ckalloc(sizeof(ItclCfunc));        cfunc->argCmdProc = NULL;    }    cfunc->objCmdProc = proc;    cfunc->clientData = clientData;    cfunc->deleteProc = deleteProc;    Tcl_SetHashValue(entry, (ClientData)cfunc);    return TCL_OK;}/* * ------------------------------------------------------------------------ *  Itcl_FindC() * *  Used to query a C procedure via its symbolic name.  Looks at the *  list of procedures registered previously by either Itcl_RegisterC *  or Itcl_RegisterObjC and returns pointers to the appropriate *  (argc,argv) or (objc,objv) handlers.  Returns non-zero if the *  name is recognized and pointers are returned; returns zero *  otherwise. * ------------------------------------------------------------------------ */intItcl_FindC(interp, name, argProcPtr, objProcPtr, cDataPtr)    Tcl_Interp *interp;           /* interpreter handling this registration */    char *name;                   /* symbolic name for procedure */    Tcl_CmdProc **argProcPtr;     /* returns (argc,argv) command handler */    Tcl_ObjCmdProc **objProcPtr;  /* returns (objc,objv) command handler */    ClientData *cDataPtr;         /* returns client data */{    Tcl_HashEntry *entry;    Tcl_HashTable *procTable;    ItclCfunc *cfunc;    *argProcPtr = NULL;  /* assume info won't be found */    *objProcPtr = NULL;    *cDataPtr   = NULL;    if (interp) {        procTable = (Tcl_HashTable*)Tcl_GetAssocData(interp,            "itcl_RegC", (Tcl_InterpDeleteProc**)NULL);        if (procTable) {            entry = Tcl_FindHashEntry(procTable, name);            if (entry) {                cfunc = (ItclCfunc*)Tcl_GetHashValue(entry);                *argProcPtr = cfunc->argCmdProc;                *objProcPtr = cfunc->objCmdProc;                *cDataPtr   = cfunc->clientData;            }        }    }    return (*argProcPtr != NULL || *objProcPtr != NULL);}/* * ------------------------------------------------------------------------ *  ItclGetRegisteredProcs() * *  Returns a pointer to a hash table containing the list of registered *  procs in the specified interpreter.  If the hash table does not *  already exist, it is created. * ------------------------------------------------------------------------ */static Tcl_HashTable*ItclGetRegisteredProcs(interp)    Tcl_Interp *interp;  /* interpreter handling this registration */{    Tcl_HashTable* procTable;    /*     *  If the registration table does not yet exist, then create it.     */    procTable = (Tcl_HashTable*)Tcl_GetAssocData(interp, "itcl_RegC",        (Tcl_InterpDeleteProc**)NULL);    if (!procTable) {        procTable = (Tcl_HashTable*)ckalloc(sizeof(Tcl_HashTable));        Tcl_InitHashTable(procTable, TCL_STRING_KEYS);        Tcl_SetAssocData(interp, "itcl_RegC", ItclFreeC,            (ClientData)procTable);    }    return procTable;}/* * ------------------------------------------------------------------------ *  ItclFreeC() * *  When an interpreter is deleted, this procedure is called to *  free up the associated data created by Itcl_RegisterC and *  Itcl_RegisterObjC. * ------------------------------------------------------------------------ */static voidItclFreeC(clientData, interp)    ClientData clientData;       /* associated data */    Tcl_Interp *interp;          /* intepreter being deleted */{    Tcl_HashTable *tablePtr = (Tcl_HashTable*)clientData;    Tcl_HashSearch place;    Tcl_HashEntry *entry;    ItclCfunc *cfunc;    entry = Tcl_FirstHashEntry(tablePtr, &place);    while (entry) {        cfunc = (ItclCfunc*)Tcl_GetHashValue(entry);        if (cfunc->deleteProc != NULL) {            (*cfunc->deleteProc)(cfunc->clientData);        }        ckfree ( (char*)cfunc );        entry = Tcl_NextHashEntry(&place);    }    Tcl_DeleteHashTable(tablePtr);    ckfree((char*)tablePtr);}

⌨️ 快捷键说明

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