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

📄 itcl_ensemble.c

📁 linux 下的源代码分析阅读器 red hat公司新版
💻 C
📖 第 1 页 / 共 5 页
字号:
            GetEnsemblePartUsage(ensData->parts[i], resultPtr);        }        Tcl_SetObjResult(interp, resultPtr);        return TCL_ERROR;    }    /*     *  Found a match.  Return the desired part.     */    *rensPart = ensData->parts[pos];    return TCL_OK;}/* *---------------------------------------------------------------------- * * FindEnsemblePartIndex -- * *      Searches for a part name within an ensemble.  The part name *      must be an exact match for an existing part name in the *      ensemble.  This procedure is useful for managing (i.e., *      creating and deleting) parts in an ensemble. * * Results: *      If an exact match is found, this procedure returns *      non-zero, along with the index of the part in posPtr. *      Otherwise, it returns zero, along with an index in posPtr *      indicating where the part should be. * * Side effects: *      None. * *---------------------------------------------------------------------- */static intFindEnsemblePartIndex(ensData, partName, posPtr)    Ensemble *ensData;        /* ensemble being searched */    char *partName;           /* name of desired part */    int *posPtr;              /* returns: index for part */{    int pos = 0;    int first, last;    int cmp;    /*     *  Search for the desired part name.     *  All parts are in lexicographical order, so use a     *  binary search to find the part quickly.     */    first = 0;    last  = ensData->numParts-1;    while (last >= first) {        pos = (first+last)/2;        if (*partName == *ensData->parts[pos]->name) {            cmp = strcmp(partName, ensData->parts[pos]->name);            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 (last >= first) {        *posPtr = pos;        return 1;    }    *posPtr = first;    return 0;}/* *---------------------------------------------------------------------- * * ComputeMinChars -- * *      Compares part names on an ensemble's part list and *      determines the minimum number of characters needed for a *      unique abbreviation.  The parts on either side of a *      particular part index are compared.  As long as there is *      a part on one side or the other, this procedure updates *      the parts to have the proper minimum abbreviations. * * Results: *      None. * * Side effects: *      Updates three parts within the ensemble to remember *      the minimum abbreviations. * *---------------------------------------------------------------------- */static voidComputeMinChars(ensData, pos)    Ensemble *ensData;        /* ensemble being modified */    int pos;                  /* index of part being updated */{    int min, max;    char *p, *q;    /*     *  If the position is invalid, do nothing.     */    if (pos < 0 || pos >= ensData->numParts) {        return;    }    /*     *  Start by assuming that only the first letter is required     *  to uniquely identify this part.  Then compare the name     *  against each neighboring part to determine the real minimum.     */    ensData->parts[pos]->minChars = 1;    if (pos-1 >= 0) {        p = ensData->parts[pos]->name;        q = ensData->parts[pos-1]->name;        for (min=1; *p == *q && *p != '\0' && *q != '\0'; min++) {            p++;            q++;        }        if (min > ensData->parts[pos]->minChars) {            ensData->parts[pos]->minChars = min;        }    }    if (pos+1 < ensData->numParts) {        p = ensData->parts[pos]->name;        q = ensData->parts[pos+1]->name;        for (min=1; *p == *q && *p != '\0' && *q != '\0'; min++) {            p++;            q++;        }        if (min > ensData->parts[pos]->minChars) {            ensData->parts[pos]->minChars = min;        }    }    max = strlen(ensData->parts[pos]->name);    if (ensData->parts[pos]->minChars > max) {        ensData->parts[pos]->minChars = max;    }}/* *---------------------------------------------------------------------- * * HandleEnsemble -- * *      Invoked by Tcl whenever the user issues an ensemble-style *      command.  Handles commands of the form: * *        <ensembleName> <partName> ?<arg> <arg>...? * *      Looks for the <partName> within the ensemble, and if it *      exists, the procedure transfers control to it. * * Results: *      Returns TCL_OK if successful, and 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 intHandleEnsemble(clientData, interp, objc, objv)    ClientData clientData;   /* ensemble data */    Tcl_Interp *interp;      /* current interpreter */    int objc;                /* number of arguments */    Tcl_Obj *CONST objv[];   /* argument objects */{    Ensemble *ensData = (Ensemble*)clientData;    int i, result;    Command *cmdPtr;    EnsemblePart *ensPart;    char *partName;    int partNameLen;    Tcl_Obj *cmdlinePtr, *chainObj;    int cmdlinec;    Tcl_Obj **cmdlinev;    /*     *  If a part name is not specified, return an error that     *  summarizes the usage for this ensemble.     */    if (objc < 2) {        Tcl_Obj *resultPtr = Tcl_NewStringObj(            "wrong # args: should be one of...\n", -1);        GetEnsembleUsage(ensData, resultPtr);        Tcl_SetObjResult(interp, resultPtr);        return TCL_ERROR;    }    /*     *  Lookup the desired part.  If an ambiguous abbrevition is     *  found, return an error immediately.     */    partName = Tcl_GetStringFromObj(objv[1], &partNameLen);    if (FindEnsemblePart(interp, ensData, partName, &ensPart) != TCL_OK) {        return TCL_ERROR;    }    /*     *  If the part was not found, then look for an "@error" part     *  to handle the error.     */    if (ensPart == NULL) {        if (FindEnsemblePart(interp, ensData, "@error", &ensPart) != TCL_OK) {            return TCL_ERROR;        }        if (ensPart != NULL) {            cmdPtr = (Command*)ensPart->cmdPtr;            result = (*cmdPtr->objProc)(cmdPtr->objClientData,                interp, objc, objv);            return result;        }    }    if (ensPart == NULL) {        return Itcl_EnsembleErrorCmd((ClientData)ensData,            interp, objc-1, objv+1);    }    /*     *  Pass control to the part, and return the result.     */    chainObj = Tcl_NewObj();    chainObj->bytes = NULL;    chainObj->typePtr = &itclEnsInvocType;    chainObj->internalRep.twoPtrValue.ptr1 = (VOID *) ensPart;    Tcl_IncrRefCount(objv[1]);    chainObj->internalRep.twoPtrValue.ptr2 = (VOID *) objv[0];    Tcl_IncrRefCount(objv[0]);    cmdlinePtr = Tcl_NewListObj(0, (Tcl_Obj**)NULL);    Tcl_ListObjAppendElement((Tcl_Interp*)NULL, cmdlinePtr, chainObj);    for (i=2; i < objc; i++) {        Tcl_ListObjAppendElement((Tcl_Interp*)NULL, cmdlinePtr, objv[i]);    }    Tcl_IncrRefCount(cmdlinePtr);    result = Tcl_ListObjGetElements((Tcl_Interp*)NULL, cmdlinePtr,        &cmdlinec, &cmdlinev);    if (result == TCL_OK) {        cmdPtr = (Command*)ensPart->cmdPtr;        result = (*cmdPtr->objProc)(cmdPtr->objClientData, interp,            cmdlinec, cmdlinev);    }    Tcl_DecrRefCount(cmdlinePtr);    return result;}/* *---------------------------------------------------------------------- * * Itcl_EnsembleCmd -- * *      Invoked by Tcl whenever the user issues the "ensemble" *      command to manipulate an ensemble.  Handles the following *      syntax: * *        ensemble <ensName> ?<command> <arg> <arg>...? *        ensemble <ensName> { *            part <partName> <args> <body> *            ensemble <ensName> { *                ... *            } *        } * *      Finds or creates the ensemble <ensName>, and then executes *      the commands to add parts. * * Results: *      Returns TCL_OK if successful, and TCL_ERROR if anything *      goes wrong. * * Side effects: *      If anything goes wrong, this procedure returns an error *      message as the result in the interpreter. * *---------------------------------------------------------------------- */intItcl_EnsembleCmd(clientData, interp, objc, objv)    ClientData clientData;   /* ensemble data */    Tcl_Interp *interp;      /* current interpreter */    int objc;                /* number of arguments */    Tcl_Obj *CONST objv[];   /* argument objects */{    int status;    char *ensName;    EnsembleParser *ensInfo;    Ensemble *ensData, *savedEnsData;    EnsemblePart *ensPart;    Tcl_Command cmd;    Command *cmdPtr;    Tcl_Obj *objPtr;    /*     *  Make sure that an ensemble name was specified.     */    if (objc < 2) {        Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),            "wrong # args: should be \"",            Tcl_GetStringFromObj(objv[0], (int*)NULL),            " name ?command arg arg...?\"",            (char*)NULL);        return TCL_ERROR;    }    /*     *  If this is the "ensemble" command in the main interpreter,     *  then the client data will be null.  Otherwise, it is     *  the "ensemble" command in the ensemble body parser, and     *  the client data indicates which ensemble we are modifying.     */    if (clientData) {        ensInfo = (EnsembleParser*)clientData;    } else {        ensInfo = GetEnsembleParser(interp);    }    ensData = ensInfo->ensData;    /*     *  Find or create the desired ensemble.  If an ensemble is     *  being built, then this "ensemble" command is enclosed in     *  another "ensemble" command.  Use the current ensemble as     *  the parent, and find or create an ensemble part within it.     */    ensName = Tcl_GetStringFromObj(objv[1], (int*)NULL);    if (ensData) {        if (FindEnsemblePart(interp, ensData, ensName, &ensPart) != TCL_OK) {            ensPart = NULL;        }        if (ensPart == NULL) {            if (CreateEnsemble(interp, ensData, ensName) != TCL_OK) {                return TCL_ERROR;            }            if (FindEnsemblePart(interp, ensData, ensName, &ensPart)                != TCL_OK) {                panic("Itcl_EnsembleCmd: can't create ensemble");            }        }        cmdPtr = (Command*)ensPart->cmdPtr;        if (cmdPtr->deleteProc != DeleteEnsemble) {            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),                "part \"", Tcl_GetStringFromObj(objv[1], (int*)NULL),                "\" is not an ensemble",                (char*)NULL);            return TCL_ERROR;        }        ensData = (Ensemble*)cmdPtr->objClientData;    }    /*     *  Otherwise, the desired ensemble is a top-level ensemble.     *  Find or create the access command for the ensemble, and     *  then get its data.     */    else {        cmd = Tcl_FindCommand(interp, ensName, (Tcl_Namespace*)NULL, 0);        if (cmd == NULL) {            if (CreateEnsemble(interp, (Ensemble*)NULL, ensName)                != TCL_OK) {                return TCL_ERROR;            }            cmd = Tcl_FindCommand(interp, ensName, (Tcl_Namespace*)NULL, 0);        }        cmdPtr = (Command*)cmd;        if (cmdPtr == NULL || cmdPtr->deleteProc != DeleteEnsemble) {            Tcl_AppendStringsToObj(Tcl_GetObjResult(interp),                "command \"", Tcl_GetStringFromObj(objv[1], (int*)NULL),                "\" is not an ensemble",                (char*)NULL);            return TCL_ERROR;        }        ensData = (Ensemble*)cmdPtr->objClientData;    }    /*     *  At this point, we have the data for the ensemble that is     *  being manipulated.  Plug this into the parser, and then     *  interpret the rest of the arguments in the ensemble parser.      */    status = TCL_OK;    savedEnsData = ensInfo->ensData;    ensInfo->ensData = ensData;    if (objc == 3) {      /* CYGNUS LOCAL - fix for Tcl8.1 */#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 1        status = Tcl_EvalObj(ensInfo->parser, objv[2], 0);#else        status = Tcl_EvalObj(ensInfo->parser, objv[2]);#endif    }    else if (objc > 3) {        objPtr = Tcl_NewListObj(objc-2, objv+2);        Tcl_IncrRefCount(objPtr);  /* stop Eval trashing it */#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 1        status = Tcl_EvalObj(ensInfo->parser, objPtr, 0);#else

⌨️ 快捷键说明

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