📄 tclcmdah.c
字号:
/* * tclCmdAH.c -- * * This file contains the top-level command routines for most of * the Tcl built-in commands whose names begin with the letters * A to H. * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * SCCS: @(#) tclCmdAH.c 1.159 97/10/31 13:06:07 */#include "tclInt.h"#include "tclPort.h"/* * Prototypes for local procedures defined in this file: */static char * GetTypeFromMode _ANSI_ARGS_((int mode));static int StoreStatData _ANSI_ARGS_((Tcl_Interp *interp, char *varName, struct stat *statPtr));/* *---------------------------------------------------------------------- * * Tcl_BreakCmd -- * * This procedure is invoked to process the "break" Tcl command. * See the user documentation for details on what it does. * * With the bytecode compiler, this procedure is only called when * a command name is computed at runtime, and is "break" or the name * to which "break" was renamed: e.g., "set z break; $z" * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_BreakCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ if (argc != 1) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], "\"", (char *) NULL); return TCL_ERROR; } return TCL_BREAK;}/* *---------------------------------------------------------------------- * * Tcl_CaseObjCmd -- * * This procedure is invoked to process the "case" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_CaseObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */{ register int i; int body, result; char *string, *arg; int argLen, caseObjc; Tcl_Obj *CONST *caseObjv; Tcl_Obj *armPtr; if (objc < 3) { Tcl_WrongNumArgs(interp, 1, objv, "string ?in? patList body ... ?default body?"); return TCL_ERROR; } /* * THIS FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE. */ string = Tcl_GetStringFromObj(objv[1], &argLen); body = -1; arg = Tcl_GetStringFromObj(objv[2], &argLen); if (strcmp(arg, "in") == 0) { i = 3; } else { i = 2; } caseObjc = objc - i; caseObjv = objv + i; /* * If all of the pattern/command pairs are lumped into a single * argument, split them out again. * THIS FAILS IF THE ARG'S STRING REP CONTAINS A NULL */ if (caseObjc == 1) { Tcl_Obj **newObjv; Tcl_ListObjGetElements(interp, caseObjv[0], &caseObjc, &newObjv); caseObjv = newObjv; } for (i = 0; i < caseObjc; i += 2) { int patObjc, j; char **patObjv; char *pat; register char *p; if (i == (caseObjc-1)) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "extra case pattern with no body", -1); return TCL_ERROR; } /* * Check for special case of single pattern (no list) with * no backslash sequences. */ pat = Tcl_GetStringFromObj(caseObjv[i], &argLen); for (p = pat; *p != 0; p++) { /* FAILS IF NULL BYTE */ if (isspace(UCHAR(*p)) || (*p == '\\')) { break; } } if (*p == 0) { if ((*pat == 'd') && (strcmp(pat, "default") == 0)) { body = i+1; } if (Tcl_StringMatch(string, pat)) { body = i+1; goto match; } continue; } /* * Break up pattern lists, then check each of the patterns * in the list. */ result = Tcl_SplitList(interp, pat, &patObjc, &patObjv); if (result != TCL_OK) { return result; } for (j = 0; j < patObjc; j++) { if (Tcl_StringMatch(string, patObjv[j])) { body = i+1; break; } } ckfree((char *) patObjv); if (j < patObjc) { break; } } match: if (body != -1) { armPtr = caseObjv[body-1]; result = Tcl_EvalObj(interp, caseObjv[body]); if (result == TCL_ERROR) { char msg[100]; arg = Tcl_GetStringFromObj(armPtr, &argLen); sprintf(msg, "\n (\"%.*s\" arm line %d)", argLen, arg, interp->errorLine); Tcl_AddObjErrorInfo(interp, msg, -1); } return result; } /* * Nothing matched: return nothing. */ return TCL_OK;}/* *---------------------------------------------------------------------- * * Tcl_CatchObjCmd -- * * This object-based procedure is invoked to process the "catch" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_CatchObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */{ Tcl_Obj *varNamePtr = NULL; int result; if ((objc != 2) && (objc != 3)) { Tcl_WrongNumArgs(interp, 1, objv, "command ?varName?"); return TCL_ERROR; } /* * Save a pointer to the variable name object, if any, in case the * Tcl_EvalObj reallocates the bytecode interpreter's evaluation * stack rendering objv invalid. */ if (objc == 3) { varNamePtr = objv[2]; } result = Tcl_EvalObj(interp, objv[1]); if (objc == 3) { if (Tcl_ObjSetVar2(interp, varNamePtr, NULL, Tcl_GetObjResult(interp), TCL_PARSE_PART1) == NULL) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "couldn't save command result in variable", -1); return TCL_ERROR; } } /* * Set the interpreter's object result to an integer object holding the * integer Tcl_EvalObj result. Note that we don't bother generating a * string representation. We reset the interpreter's object result * to an unshared empty object and then set it to be an integer object. */ Tcl_ResetResult(interp); Tcl_SetIntObj(Tcl_GetObjResult(interp), result); return TCL_OK;}/* *---------------------------------------------------------------------- * * Tcl_CdObjCmd -- * * This procedure is invoked to process the "cd" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_CdObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */{ char *dirName; int dirLength; Tcl_DString buffer; int result; if (objc > 2) { Tcl_WrongNumArgs(interp, 1, objv, "dirName"); return TCL_ERROR; } if (objc == 2) { dirName = Tcl_GetStringFromObj(objv[1], &dirLength); } else { dirName = "~"; } dirName = Tcl_TranslateFileName(interp, dirName, &buffer); if (dirName == NULL) { return TCL_ERROR; } result = TclChdir(interp, dirName); Tcl_DStringFree(&buffer); return result;}/* *---------------------------------------------------------------------- * * Tcl_ConcatObjCmd -- * * This object-based procedure is invoked to process the "concat" Tcl * command. See the user documentation for details on what it does/ * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_ConcatObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */{ if (objc >= 2) { Tcl_SetObjResult(interp, Tcl_ConcatObj(objc-1, objv+1)); } return TCL_OK;}/* *---------------------------------------------------------------------- * * Tcl_ContinueCmd - * * This procedure is invoked to process the "continue" Tcl command. * See the user documentation for details on what it does. * * With the bytecode compiler, this procedure is only called when * a command name is computed at runtime, and is "continue" or the name * to which "continue" was renamed: e.g., "set z continue; $z" * * Results: * A standard Tcl result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_ContinueCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{ if (argc != 1) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], "\"", (char *) NULL); return TCL_ERROR; } return TCL_CONTINUE;}/* *---------------------------------------------------------------------- * * Tcl_ErrorObjCmd -- * * This procedure is invoked to process the "error" Tcl command. * See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_ErrorObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */{ Interp *iPtr = (Interp *) interp; register Tcl_Obj *namePtr; char *info; int infoLen; if ((objc < 2) || (objc > 4)) { Tcl_WrongNumArgs(interp, 1, objv, "message ?errorInfo? ?errorCode?"); return TCL_ERROR; } if (objc >= 3) { /* process the optional info argument */ info = Tcl_GetStringFromObj(objv[2], &infoLen); if (*info != 0) { Tcl_AddObjErrorInfo(interp, info, infoLen); iPtr->flags |= ERR_ALREADY_LOGGED; } } if (objc == 4) { namePtr = Tcl_NewStringObj("errorCode", -1); Tcl_ObjSetVar2(interp, namePtr, (Tcl_Obj *) NULL, objv[3], TCL_GLOBAL_ONLY); iPtr->flags |= ERROR_CODE_SET; Tcl_DecrRefCount(namePtr); /* we're done with name object */ } Tcl_SetObjResult(interp, objv[1]); return TCL_ERROR;}/* *---------------------------------------------------------------------- * * Tcl_EvalObjCmd -- * * This object-based procedure is invoked to process the "eval" Tcl * command. See the user documentation for details on what it does. * * Results: * A standard Tcl object result. * * Side effects: * See the user documentation. * *---------------------------------------------------------------------- */ /* ARGSUSED */intTcl_EvalObjCmd(dummy, interp, objc, objv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int objc; /* Number of arguments. */ Tcl_Obj *CONST objv[]; /* Argument objects. */{ int result; register Tcl_Obj *objPtr; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "arg ?arg ...?"); return TCL_ERROR; } if (objc == 2) { result = Tcl_EvalObj(interp, objv[1]); } else { /* * More than one argument: concatenate them together with spaces * between, then evaluate the result. */ objPtr = Tcl_ConcatObj(objc-1, objv+1); result = Tcl_EvalObj(interp, objPtr); Tcl_DecrRefCount(objPtr); /* we're done with the object */ } if (result == TCL_ERROR) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -