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

📄 itcl_ensemble.c

📁 linux 下的源代码分析阅读器 red hat公司新版
💻 C
📖 第 1 页 / 共 5 页
字号:
 * Side effects: *      If an error is encountered, an error is left as the result *      in the interpreter. * *---------------------------------------------------------------------- */static intAddEnsemblePart(interp, ensData, partName, usageInfo,    objProc, clientData, deleteProc, rVal)    Tcl_Interp *interp;            /* interpreter to be updated */    Ensemble* ensData;             /* ensemble that will contain this part */    char* partName;                /* name of the new part */    char* usageInfo;               /* usage info for argument list */    Tcl_ObjCmdProc *objProc;       /* handling procedure for part */    ClientData clientData;         /* client data associated with part */    Tcl_CmdDeleteProc *deleteProc; /* procedure used to destroy client data */    EnsemblePart **rVal;           /* returns: new ensemble part */{    EnsemblePart *ensPart;    Command *cmdPtr;    /*     *  Install the new part into the part list.     */    if (CreateEnsemblePart(interp, ensData, partName, &ensPart) != TCL_OK) {        return TCL_ERROR;    }    if (usageInfo) {        ensPart->usage = ckalloc((unsigned)(strlen(usageInfo)+1));        strcpy(ensPart->usage, usageInfo);    }    cmdPtr = (Command*)ckalloc(sizeof(Command));    cmdPtr->hPtr = NULL;    cmdPtr->nsPtr = ((Command*)ensData->cmd)->nsPtr;    cmdPtr->refCount = 0;    cmdPtr->cmdEpoch = 0;    cmdPtr->compileProc = NULL;    cmdPtr->objProc = objProc;    cmdPtr->objClientData = (ClientData)clientData;    cmdPtr->proc = NULL;    cmdPtr->clientData = NULL;    cmdPtr->deleteProc = deleteProc;    cmdPtr->deleteData = (ClientData)clientData;    cmdPtr->deleted = 0;    cmdPtr->importRefPtr = NULL;    ensPart->cmdPtr = cmdPtr;    *rVal = ensPart;    return TCL_OK;}/* *---------------------------------------------------------------------- * * DeleteEnsemble -- * *      Invoked when the command associated with an ensemble is *      destroyed, to delete the ensemble.  Destroys all parts *      included in the ensemble, and frees all memory associated *      with it. * * Results: *      None. * * Side effects: *      None. * *---------------------------------------------------------------------- */static voidDeleteEnsemble(clientData)    ClientData clientData;    /* ensemble data */{    Ensemble* ensData = (Ensemble*)clientData;    /*     *  BE CAREFUL:  Each ensemble part removes itself from the list.     *    So keep deleting the first part until all parts are gone.     */    while (ensData->numParts > 0) {        DeleteEnsemblePart(ensData->parts[0]);    }    ckfree((char*)ensData->parts);    ckfree((char*)ensData);}/* *---------------------------------------------------------------------- * * FindEnsemble -- * *      Searches for an ensemble command and follows a path to *      sub-ensembles. * * Results: *      Returns TCL_OK if the ensemble was found, along with a *      pointer to the ensemble data in "ensDataPtr".  Returns *      TCL_ERROR if anything goes wrong. * * Side effects: *      If anything goes wrong, this procedure returns an error *      message as the result in the interpreter. * *---------------------------------------------------------------------- */static intFindEnsemble(interp, nameArgv, nameArgc, ensDataPtr)    Tcl_Interp *interp;            /* interpreter containing the ensemble */    char **nameArgv;               /* path of names leading to ensemble */    int nameArgc;                  /* number of strings in nameArgv */    Ensemble** ensDataPtr;         /* returns: ensemble data */{    int i;    Command* cmdPtr;    Ensemble *ensData;    EnsemblePart *ensPart;    *ensDataPtr = NULL;  /* assume that no data will be found */    /*     *  If there are no names in the path, then return an error.     */    if (nameArgc < 1) {        Tcl_AppendToObj(Tcl_GetObjResult(interp),            "invalid ensemble name \"\"", -1);        return TCL_ERROR;    }    /*     *  Use the first name to find the command for the top-level     *  ensemble.     */    cmdPtr = (Command*) Tcl_FindCommand(interp, nameArgv[0],        (Tcl_Namespace*)NULL, TCL_LEAVE_ERR_MSG);    if (cmdPtr == NULL || cmdPtr->deleteProc != DeleteEnsemble) {        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),            "command \"", nameArgv[0], "\" is not an ensemble",            (char*)NULL);        return TCL_ERROR;    }    ensData = (Ensemble*)cmdPtr->objClientData;    /*     *  Follow the trail of sub-ensemble names.     */    for (i=1; i < nameArgc; i++) {        if (FindEnsemblePart(interp, ensData, nameArgv[i], &ensPart)            != TCL_OK) {            return TCL_ERROR;        }        if (ensPart == NULL) {            char *pname = Tcl_Merge(i, nameArgv);            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),                "invalid ensemble name \"", pname, "\"",                (char*)NULL);            ckfree(pname);            return TCL_ERROR;        }        cmdPtr = ensPart->cmdPtr;        if (cmdPtr == NULL || cmdPtr->deleteProc != DeleteEnsemble) {            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),                "part \"", nameArgv[i], "\" is not an ensemble",                (char*)NULL);            return TCL_ERROR;        }        ensData = (Ensemble*)cmdPtr->objClientData;    }    *ensDataPtr = ensData;    return TCL_OK;}/* *---------------------------------------------------------------------- * * CreateEnsemblePart -- * *      Creates a new part within an ensemble. * * Results: *      If successful, this procedure returns TCL_OK, along with a *      pointer to the new part in "ensPartPtr".  If a part with the *      same name already exists, this procedure returns TCL_ERROR. * * Side effects: *      If anything goes wrong, this procedure returns an error *      message as the result in the interpreter. * *---------------------------------------------------------------------- */static intCreateEnsemblePart(interp, ensData, partName, ensPartPtr)    Tcl_Interp *interp;          /* interpreter containing the ensemble */    Ensemble *ensData;           /* ensemble being modified */    char* partName;              /* name of the new part */    EnsemblePart **ensPartPtr;   /* returns: new ensemble part */{    int i, pos, size;    EnsemblePart** partList;    EnsemblePart* part;    /*     *  If a matching entry was found, then return an error.     */    if (FindEnsemblePartIndex(ensData, partName, &pos)) {        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),            "part \"", partName, "\" already exists in ensemble",            (char*)NULL);        return TCL_ERROR;    }    /*     *  Otherwise, make room for a new entry.  Keep the parts in     *  lexicographical order, so we can search them quickly     *  later.     */    if (ensData->numParts >= ensData->maxParts) {        size = ensData->maxParts*sizeof(EnsemblePart*);        partList = (EnsemblePart**)ckalloc((unsigned)2*size);        memcpy((VOID*)partList, (VOID*)ensData->parts, (size_t)size);        ckfree((char*)ensData->parts);        ensData->parts = partList;        ensData->maxParts *= 2;    }    for (i=ensData->numParts; i > pos; i--) {        ensData->parts[i] = ensData->parts[i-1];    }    ensData->numParts++;    part = (EnsemblePart*)ckalloc(sizeof(EnsemblePart));    part->name = (char*)ckalloc((unsigned)(strlen(partName)+1));    strcpy(part->name, partName);    part->cmdPtr   = NULL;    part->usage    = NULL;    part->ensemble = ensData;    ensData->parts[pos] = part;    /*     *  Compare the new part against the one on either side of     *  it.  Determine how many letters are needed in each part     *  to guarantee that an abbreviated form is unique.  Update     *  the parts on either side as well, since they are influenced     *  by the new part.     */    ComputeMinChars(ensData, pos);    ComputeMinChars(ensData, pos-1);    ComputeMinChars(ensData, pos+1);    *ensPartPtr = part;    return TCL_OK;}/* *---------------------------------------------------------------------- * * DeleteEnsemblePart -- * *      Deletes a single part from an ensemble.  The part must have  *      been created previously by CreateEnsemblePart. * *      If the part has a delete proc, then it is called to free the *      associated client data. * * Results: *      None. * * Side effects: *      Delete proc is called. * *---------------------------------------------------------------------- */static voidDeleteEnsemblePart(ensPart)    EnsemblePart *ensPart;     /* part being destroyed */{    int i, pos;    Command *cmdPtr;    Ensemble *ensData;    cmdPtr = ensPart->cmdPtr;    /*     *  If this part has a delete proc, then call it to free     *  up the client data.     */    if (cmdPtr->deleteData && cmdPtr->deleteProc) {        (*cmdPtr->deleteProc)(cmdPtr->deleteData);    }    ckfree((char*)cmdPtr);    /*     *  Find this part within its ensemble, and remove it from     *  the list of parts.     */    if (FindEnsemblePartIndex(ensPart->ensemble, ensPart->name, &pos)) {        ensData = ensPart->ensemble;        for (i=pos; i < ensData->numParts-1; i++) {            ensData->parts[i] = ensData->parts[i+1];        }        ensData->numParts--;    }    /*     *  Free the memory associated with the part.     */    if (ensPart->usage) {        ckfree(ensPart->usage);    }    ckfree(ensPart->name);    ckfree((char*)ensPart);}/* *---------------------------------------------------------------------- * * FindEnsemblePart -- * *      Searches for a part name within an ensemble.  Recognizes *      unique abbreviations for part names. * * Results: *      If the part name is not a unique abbreviation, this procedure *      returns TCL_ERROR.  Otherwise, it returns TCL_OK.  If the *      part can be found, "rensPart" returns a pointer to the part. *      Otherwise, it returns NULL. * * Side effects: *      If anything goes wrong, this procedure returns an error *      message as the result in the interpreter. * *---------------------------------------------------------------------- */static intFindEnsemblePart(interp, ensData, partName, rensPart)    Tcl_Interp *interp;       /* interpreter containing the ensemble */    Ensemble *ensData;        /* ensemble being searched */    char* partName;           /* name of the desired part */    EnsemblePart **rensPart;  /* returns:  pointer to the desired part */{    int pos = 0;    int first, last, nlen;    int i, cmp;    *rensPart = NULL;    /*     *  Search for the desired part name.     *  All parts are in lexicographical order, so use a     *  binary search to find the part quickly.  Match only     *  as many characters as are included in the specified     *  part name.     */    first = 0;    last  = ensData->numParts-1;    nlen  = strlen(partName);    while (last >= first) {        pos = (first+last)/2;        if (*partName == *ensData->parts[pos]->name) {            cmp = strncmp(partName, ensData->parts[pos]->name, nlen);            if (cmp == 0) {                break;    /* found it! */            }        }        else if (*partName < *ensData->parts[pos]->name) {            cmp = -1;        }        else {            cmp = 1;        }        if (cmp > 0) {            first = pos+1;        } else {            last = pos-1;        }    }    /*     *  If a matching entry could not be found, then quit.     */    if (last < first) {        return TCL_OK;    }    /*     *  If a matching entry was found, there may be some ambiguity     *  if the user did not specify enough characters.  Find the     *  top-most match in the list, and see if the part name has     *  enough characters.  If there are two parts like "foo"     *  and "food", this allows us to match "foo" exactly.     */    if (nlen < ensData->parts[pos]->minChars) {        while (pos > 0) {            pos--;            if (strncmp(partName, ensData->parts[pos]->name, nlen) != 0) {                pos++;                break;            }        }    }    if (nlen < ensData->parts[pos]->minChars) {        Tcl_Obj *resultPtr = Tcl_NewStringObj((char*)NULL, 0);        Tcl_AppendStringsToObj(resultPtr,            "ambiguous option \"", partName, "\": should be one of...",            (char*)NULL);        for (i=pos; i < ensData->numParts; i++) {            if (strncmp(partName, ensData->parts[i]->name, nlen) != 0) {                break;            }            Tcl_AppendToObj(resultPtr, "\n  ", 3); 

⌨️ 快捷键说明

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