tclcmdil.c

来自「tcl是工具命令语言」· C语言 代码 · 共 2,174 行 · 第 1/5 页

C
2,174
字号
/*  * tclCmdIL.c -- * *	This file contains the top-level command routines for most of *	the Tcl built-in commands whose names begin with the letters *	I through L.  It contains only commands in the generic core *	(i.e. those that don't depend much upon UNIX facilities). * * Copyright (c) 1987-1993 The Regents of the University of California. * Copyright (c) 1993-1997 Lucent Technologies. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * Copyright (c) 2001 by Kevin B. Kenny.  All rights reserved. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclCmdIL.c,v 1.47 2003/02/27 16:01:55 dkf Exp $ */#include "tclInt.h"#include "tclPort.h"#include "tclRegexp.h"/* * During execution of the "lsort" command, structures of the following * type are used to arrange the objects being sorted into a collection * of linked lists. */typedef struct SortElement {    Tcl_Obj *objPtr;			/* Object being sorted. */    int count;				/* number of same elements in list */    struct SortElement *nextPtr;        /* Next element in the list, or					 * NULL for end of list. */} SortElement;/* * The "lsort" command needs to pass certain information down to the * function that compares two list elements, and the comparison function * needs to pass success or failure information back up to the top-level * "lsort" command.  The following structure is used to pass this * information. */typedef struct SortInfo {    int isIncreasing;		/* Nonzero means sort in increasing order. */    int sortMode;		/* The sort mode.  One of SORTMODE_*				 * values defined below */    Tcl_Obj *compareCmdPtr;     /* The Tcl comparison command when sortMode				 * is SORTMODE_COMMAND.  Pre-initialized to				 * hold base of command.*/    int index;			/* If the -index option was specified, this				 * holds the index of the list element				 * to extract for comparison.  If -index				 * wasn't specified, this is -1. */    Tcl_Interp *interp;		/* The interpreter in which the sortis				 * being done. */    int resultCode;		/* Completion code for the lsort command.				 * If an error occurs during the sort this				 * is changed from TCL_OK to  TCL_ERROR. */} SortInfo;/* * The "sortMode" field of the SortInfo structure can take on any of the * following values. */#define SORTMODE_ASCII      0#define SORTMODE_INTEGER    1#define SORTMODE_REAL       2#define SORTMODE_COMMAND    3#define SORTMODE_DICTIONARY 4/* * Magic values for the index field of the SortInfo structure. * Note that the index "end-1" will be translated to SORTIDX_END-1, etc. */#define SORTIDX_NONE	-1		/* Not indexed; use whole value. */#define SORTIDX_END	-2		/* Indexed from end. *//* * Forward declarations for procedures defined in this file: */static void		AppendLocals _ANSI_ARGS_((Tcl_Interp *interp,			    Tcl_Obj *listPtr, CONST char *pattern,			    int includeLinks));static int		DictionaryCompare _ANSI_ARGS_((char *left,			    char *right));static int		InfoArgsCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoBodyCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoCmdCountCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoCommandsCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoCompleteCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoDefaultCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoExistsCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoFunctionsCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoGlobalsCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoHostnameCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoLevelCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoLibraryCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoLoadedCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoLocalsCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoNameOfExecutableCmd _ANSI_ARGS_((			    ClientData dummy, Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoPatchLevelCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoProcsCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoScriptCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoSharedlibCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoTclVersionCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static int		InfoVarsCmd _ANSI_ARGS_((ClientData dummy,			    Tcl_Interp *interp, int objc,			    Tcl_Obj *CONST objv[]));static SortElement *    MergeSort _ANSI_ARGS_((SortElement *headPt,			    SortInfo *infoPtr));static SortElement *    MergeLists _ANSI_ARGS_((SortElement *leftPtr,			    SortElement *rightPtr, SortInfo *infoPtr));static int		SortCompare _ANSI_ARGS_((Tcl_Obj *firstPtr,			    Tcl_Obj *second, SortInfo *infoPtr));/* *---------------------------------------------------------------------- * * Tcl_IfObjCmd -- * *	This procedure is invoked to process the "if" 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 "if" or the name *	to which "if" was renamed: e.g., "set z if; $z 1 {puts foo}" * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *---------------------------------------------------------------------- */	/* ARGSUSED */intTcl_IfObjCmd(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 thenScriptIndex = 0;	/* then script to be evaled after syntax check */    int i, result, value;    char *clause;    i = 1;    while (1) {	/*	 * At this point in the loop, objv and objc refer to an expression	 * to test, either for the main expression or an expression	 * following an "elseif".  The arguments after the expression must	 * be "then" (optional) and a script to execute if the expression is	 * true.	 */	if (i >= objc) {	    clause = Tcl_GetString(objv[i-1]);	    Tcl_AppendResult(interp, "wrong # args: no expression after \"",		    clause, "\" argument", (char *) NULL);	    return TCL_ERROR;	}	if (!thenScriptIndex) {	    result = Tcl_ExprBooleanObj(interp, objv[i], &value);	    if (result != TCL_OK) {		return result;	    }	}	i++;	if (i >= objc) {	    missingScript:	    clause = Tcl_GetString(objv[i-1]);	    Tcl_AppendResult(interp, "wrong # args: no script following \"",		    clause, "\" argument", (char *) NULL);	    return TCL_ERROR;	}	clause = Tcl_GetString(objv[i]);	if ((i < objc) && (strcmp(clause, "then") == 0)) {	    i++;	}	if (i >= objc) {	    goto missingScript;	}	if (value) {	    thenScriptIndex = i;	    value = 0;	}		/*	 * The expression evaluated to false.  Skip the command, then	 * see if there is an "else" or "elseif" clause.	 */	i++;	if (i >= objc) {	    if (thenScriptIndex) {		return Tcl_EvalObjEx(interp, objv[thenScriptIndex], 0);	    }	    return TCL_OK;	}	clause = Tcl_GetString(objv[i]);	if ((clause[0] == 'e') && (strcmp(clause, "elseif") == 0)) {	    i++;	    continue;	}	break;    }    /*     * Couldn't find a "then" or "elseif" clause to execute.  Check now     * for an "else" clause.  We know that there's at least one more     * argument when we get here.     */    if (strcmp(clause, "else") == 0) {	i++;	if (i >= objc) {	    Tcl_AppendResult(interp,		    "wrong # args: no script following \"else\" argument",		    (char *) NULL);	    return TCL_ERROR;	}    }    if (i < objc - 1) {	Tcl_AppendResult(interp,		"wrong # args: extra words after \"else\" clause in \"if\" command",		(char *) NULL);	return TCL_ERROR;    }    if (thenScriptIndex) {	return Tcl_EvalObjEx(interp, objv[thenScriptIndex], 0);    }    return Tcl_EvalObjEx(interp, objv[i], 0);}/* *---------------------------------------------------------------------- * * Tcl_IncrObjCmd -- * *	This procedure is invoked to process the "incr" 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 "incr" or the name *	to which "incr" was renamed: e.g., "set z incr; $z i -1" * * Results: *	A standard Tcl result. * * Side effects: *	See the user documentation. * *---------------------------------------------------------------------- */    /* ARGSUSED */intTcl_IncrObjCmd(dummy, interp, objc, objv)    ClientData dummy;			/* Not used. */    Tcl_Interp *interp;			/* Current interpreter. */    int objc;				/* Number of arguments. */    Tcl_Obj *CONST objv[];		/* Argument objects. */{    long incrAmount;    Tcl_Obj *newValuePtr;        if ((objc != 2) && (objc != 3)) {        Tcl_WrongNumArgs(interp, 1, objv, "varName ?increment?");	return TCL_ERROR;    }    /*     * Calculate the amount to increment by.     */        if (objc == 2) {	incrAmount = 1;    } else {#ifdef TCL_WIDE_INT_IS_LONG	if (Tcl_GetLongFromObj(interp, objv[2], &incrAmount) != TCL_OK) {	    Tcl_AddErrorInfo(interp, "\n    (reading increment)");	    return TCL_ERROR;	}#else	/*	 * Need to be a bit cautious to ensure that [expr]-like rules	 * are enforced for interpretation of wide integers, despite	 * the fact that the underlying API itself is a 'long' only one.	 */	if (objv[2]->typePtr == &tclIntType) {	    incrAmount = objv[2]->internalRep.longValue;	} else if (objv[2]->typePtr == &tclWideIntType) {	    incrAmount = Tcl_WideAsLong(objv[2]->internalRep.wideValue);	} else {	    Tcl_WideInt wide;	    if (Tcl_GetWideIntFromObj(interp, objv[2], &wide) != TCL_OK) {		Tcl_AddErrorInfo(interp, "\n    (reading increment)");		return TCL_ERROR;	    }	    incrAmount = Tcl_WideAsLong(wide);	    if ((wide <= Tcl_LongAsWide(LONG_MAX))		    && (wide >= Tcl_LongAsWide(LONG_MIN))) {		objv[2]->typePtr = &tclIntType;		objv[2]->internalRep.longValue = incrAmount;	    }	}#endif    }        /*     * Increment the variable's value.     */    newValuePtr = TclIncrVar2(interp, objv[1], (Tcl_Obj *) NULL, incrAmount,	    TCL_LEAVE_ERR_MSG);    if (newValuePtr == NULL) {	return TCL_ERROR;    }    /*     * Set the interpreter's object result to refer to the variable's new     * value object.     */    Tcl_SetObjResult(interp, newValuePtr);    return TCL_OK; }/* *---------------------------------------------------------------------- * * Tcl_InfoObjCmd -- * *	This procedure is invoked to process the "info" 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_InfoObjCmd(clientData, interp, objc, objv)    ClientData clientData;	/* Arbitrary value passed to the command. */    Tcl_Interp *interp;		/* Current interpreter. */    int objc;			/* Number of arguments. */    Tcl_Obj *CONST objv[];	/* Argument objects. */{    static CONST char *subCmds[] = {            "args", "body", "cmdcount", "commands",	     "complete", "default", "exists", "functions", "globals",	     "hostname", "level", "library", "loaded",	     "locals", "nameofexecutable", "patchlevel", "procs",	     "script", "sharedlibextension", "tclversion", "vars",	     (char *) NULL};    enum ISubCmdIdx {	    IArgsIdx, IBodyIdx, ICmdCountIdx, ICommandsIdx,	    ICompleteIdx, IDefaultIdx, IExistsIdx, IFunctionsIdx, IGlobalsIdx,	    IHostnameIdx, ILevelIdx, ILibraryIdx, ILoadedIdx,	    ILocalsIdx, INameOfExecutableIdx, IPatchLevelIdx, IProcsIdx,	    IScriptIdx, ISharedLibExtensionIdx, ITclVersionIdx, IVarsIdx    };    int index, result;    if (objc < 2) {        Tcl_WrongNumArgs(interp, 1, objv, "option ?arg arg ...?");        return TCL_ERROR;    }        result = Tcl_GetIndexFromObj(interp, objv[1], subCmds, "option", 0,	    (int *) &index);    if (result != TCL_OK) {	return result;    }    switch (index) {        case IArgsIdx:	    result = InfoArgsCmd(clientData, interp, objc, objv);            break;	case IBodyIdx:	    result = InfoBodyCmd(clientData, interp, objc, objv);	    break;

⌨️ 快捷键说明

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