📄 itcl_cmds.c
字号:
/* * Push any child namespaces onto the stack and continue * the search in those namespaces. */ entry = Tcl_FirstHashEntry(&nsPtr->childTable, &place); while (entry != NULL) { Itcl_PushStack(Tcl_GetHashValue(entry), &search); entry = Tcl_NextHashEntry(&place); } } Tcl_DeleteHashTable(&unique); Itcl_DeleteStack(&search); Tcl_SetObjResult(interp, listPtr); return TCL_OK;}/* * ------------------------------------------------------------------------ * Itcl_ProtectionCmd() * * Invoked by Tcl whenever the user issues a protection setting * command like "public" or "private". Creates commands and * variables, and assigns a protection level to them. Protection * levels are defined as follows: * * public => accessible from any namespace * protected => accessible from selected namespaces * private => accessible only in the namespace where it was defined * * Handles the following syntax: * * public <command> ?<arg> <arg>...? * * Returns TCL_OK/TCL_ERROR to indicate success/failure. * ------------------------------------------------------------------------ */intItcl_ProtectionCmd(clientData, interp, objc, objv) ClientData clientData; /* protection level (public/protected/private) */ Tcl_Interp *interp; /* current interpreter */ int objc; /* number of arguments */ Tcl_Obj *CONST objv[]; /* argument objects */{ int pLevel = (int)clientData; int result; int oldLevel; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "command ?arg arg...?"); return TCL_ERROR; } oldLevel = Itcl_Protection(interp, pLevel); if (objc == 2) { /* CYGNUS LOCAL - Fix for 8.1 */#if TCL_MAJOR_VERSION == 8 && TCL_MINOR_VERSION == 1 result = Tcl_EvalObj(interp, objv[1], 0);#else result = Tcl_EvalObj(interp, objv[1]);#endif /* END CYGNUS LOCAL */ } else { result = Itcl_EvalArgs(interp, objc-1, objv+1); } if (result == TCL_BREAK) { Tcl_SetResult(interp, "invoked \"break\" outside of a loop", TCL_STATIC); result = TCL_ERROR; } else if (result == TCL_CONTINUE) { Tcl_SetResult(interp, "invoked \"continue\" outside of a loop", TCL_STATIC); result = TCL_ERROR; } else if (result != TCL_OK) { char mesg[256], *name; name = Tcl_GetStringFromObj(objv[0], (int*)NULL); sprintf(mesg, "\n (%.100s body line %d)", name, interp->errorLine); Tcl_AddErrorInfo(interp, mesg); } Itcl_Protection(interp, oldLevel); return result;}/* * ------------------------------------------------------------------------ * Itcl_DelClassCmd() * * Part of the "delete" ensemble. Invoked by Tcl whenever the * user issues a "delete class" command to delete classes. * Handles the following syntax: * * delete class <name> ?<name>...? * * Returns TCL_OK/TCL_ERROR to indicate success/failure. * ------------------------------------------------------------------------ *//* ARGSUSED */intItcl_DelClassCmd(clientData, interp, objc, objv) ClientData clientData; /* unused */ Tcl_Interp *interp; /* current interpreter */ int objc; /* number of arguments */ Tcl_Obj *CONST objv[]; /* argument objects */{ int i; char *name; ItclClass *cdefn; /* * Since destroying a base class will destroy all derived * classes, calls like "destroy class Base Derived" could * fail. Break this into two passes: first check to make * sure that all classes on the command line are valid, * then delete them. */ for (i=1; i < objc; i++) { name = Tcl_GetStringFromObj(objv[i], (int*)NULL); cdefn = Itcl_FindClass(interp, name, /* autoload */ 1); if (cdefn == NULL) { return TCL_ERROR; } } for (i=1; i < objc; i++) { name = Tcl_GetStringFromObj(objv[i], (int*)NULL); cdefn = Itcl_FindClass(interp, name, /* autoload */ 0); if (cdefn) { Tcl_ResetResult(interp); if (Itcl_DeleteClass(interp, cdefn) != TCL_OK) { return TCL_ERROR; } } } Tcl_ResetResult(interp); return TCL_OK;}/* * ------------------------------------------------------------------------ * Itcl_DelObjectCmd() * * Part of the "delete" ensemble. Invoked by Tcl whenever the user * issues a "delete object" command to delete [incr Tcl] objects. * Handles the following syntax: * * delete object <name> ?<name>...? * * Returns TCL_OK/TCL_ERROR to indicate success/failure. * ------------------------------------------------------------------------ */intItcl_DelObjectCmd(clientData, interp, objc, objv) ClientData clientData; /* object management info */ Tcl_Interp *interp; /* current interpreter */ int objc; /* number of arguments */ Tcl_Obj *CONST objv[]; /* argument objects */{ int i; char *name; ItclObject *contextObj; /* * Scan through the list of objects and attempt to delete them. * If anything goes wrong (i.e., destructors fail), then * abort with an error. */ for (i=1; i < objc; i++) { name = Tcl_GetStringFromObj(objv[i], (int*)NULL); if (Itcl_FindObject(interp, name, &contextObj) != TCL_OK) { return TCL_ERROR; } if (contextObj == NULL) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "object \"", name, "\" not found", (char*)NULL); return TCL_ERROR; } if (Itcl_DeleteObject(interp, contextObj) != TCL_OK) { return TCL_ERROR; } } return TCL_OK;}/* * ------------------------------------------------------------------------ * Itcl_ScopeCmd() * * Invoked by Tcl whenever the user issues a "scope" command to * create a fully qualified variable name. Handles the following * syntax: * * scope <variable> * * If the input string is already fully qualified (starts with "::"), * then this procedure does nothing. Otherwise, it looks for a * data member called <variable> and returns its fully qualified * name. If the <variable> is a common data member, this procedure * returns a name of the form: * * ::namesp::namesp::class::variable * * If the <variable> is an instance variable, this procedure returns * a name of the form: * * @itcl ::namesp::namesp::object variable * * This kind of scoped value is recognized by the Itcl_ScopedVarResolver * proc, which handles variable resolution for the entire interpreter. * * Returns TCL_OK/TCL_ERROR to indicate success/failure. * ------------------------------------------------------------------------ *//* ARGSUSED */intItcl_ScopeCmd(dummy, interp, objc, objv) ClientData dummy; /* unused */ Tcl_Interp *interp; /* current interpreter */ int objc; /* number of arguments */ Tcl_Obj *CONST objv[]; /* argument objects */{ int result = TCL_OK; Tcl_Namespace *contextNs = Tcl_GetCurrentNamespace(interp); char *openParen = NULL; register char *p; char *token; ItclClass *contextClass; ItclObject *contextObj; ItclObjectInfo *info; Tcl_CallFrame *framePtr; Tcl_HashEntry *entry; ItclVarLookup *vlookup; Tcl_Obj *objPtr; Tcl_Var var; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "varname"); return TCL_ERROR; } /* * If this looks like a fully qualified name already, * then return it as is. */ token = Tcl_GetStringFromObj(objv[1], (int*)NULL); if (*token == ':' && *(token+1) == ':') { Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } /* * If the variable name is an array reference, pick out * the array name and use that for the lookup operations * below. */ for (p=token; *p != '\0'; p++) { if (*p == '(') { openParen = p; } else if (*p == ')' && openParen) { *openParen = '\0'; break; } } /* * Figure out what context we're in. If this is a class, * then look up the variable in the class definition. * If this is a namespace, then look up the variable in its * varTable. Note that the normal Itcl_GetContext function * returns an error if we're not in a class context, so we * perform a similar function here, the hard way. * * TRICKY NOTE: If this is an array reference, we'll get * the array variable as the variable name. We must be * careful to add the index (everything from openParen * onward) as well. */ if (Itcl_IsClassNamespace(contextNs)) { contextClass = (ItclClass*)contextNs->clientData; entry = Tcl_FindHashEntry(&contextClass->resolveVars, token); if (!entry) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "variable \"", token, "\" not found in class \"", contextClass->fullname, "\"", (char*)NULL); result = TCL_ERROR; goto scopeCmdDone; } vlookup = (ItclVarLookup*)Tcl_GetHashValue(entry); if (vlookup->vdefn->member->flags & ITCL_COMMON) { Tcl_Obj *resultPtr = Tcl_GetObjResult(interp); Tcl_AppendToObj(resultPtr, vlookup->vdefn->member->fullname, -1); if (openParen) { *openParen = '('; Tcl_AppendToObj(resultPtr, openParen, -1); openParen = NULL; } result = TCL_OK; goto scopeCmdDone; } /* * If this is not a common variable, then we better have * an object context. Return the name "@itcl object variable". */ framePtr = _Tcl_GetCallFrame(interp, 0); info = contextClass->info; entry = Tcl_FindHashEntry(&info->contextFrames, (char*)framePtr); if (!entry) { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "can't scope variable \"", token, "\": missing object context\"", (char*)NULL); result = TCL_ERROR; goto scopeCmdDone; } contextObj = (ItclObject*)Tcl_GetHashValue(entry); Tcl_AppendElement(interp, "@itcl"); objPtr = Tcl_NewStringObj((char*)NULL, 0); Tcl_IncrRefCount(objPtr); Tcl_GetCommandFullName(interp, contextObj->accessCmd, objPtr); Tcl_AppendElement(interp, Tcl_GetStringFromObj(objPtr, (int*)NULL)); Tcl_DecrRefCount(objPtr); objPtr = Tcl_NewStringObj((char*)NULL, 0); Tcl_IncrRefCount(objPtr); Tcl_AppendToObj(objPtr, vlookup->vdefn->member->fullname, -1); if (openParen) { *openParen = '('; Tcl_AppendToObj(objPtr, openParen, -1); openParen = NULL; } Tcl_AppendElement(interp, Tcl_GetStringFromObj(objPtr, (int*)NULL)); Tcl_DecrRefCount(objPtr); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -