📄 tclcmdmz.c
字号:
for (objv++, objc--; objc > 1; objv += 2, objc -= 2) { char *option = Tcl_GetStringFromObj(objv[0], &optionLen); char *arg = Tcl_GetStringFromObj(objv[1], &argLen); if (strcmp(option, "-code") == 0) { register int c = arg[0]; if ((c == 'o') && (strcmp(arg, "ok") == 0)) { code = TCL_OK; } else if ((c == 'e') && (strcmp(arg, "error") == 0)) { code = TCL_ERROR; } else if ((c == 'r') && (strcmp(arg, "return") == 0)) { code = TCL_RETURN; } else if ((c == 'b') && (strcmp(arg, "break") == 0)) { code = TCL_BREAK; } else if ((c == 'c') && (strcmp(arg, "continue") == 0)) { code = TCL_CONTINUE; } else { result = Tcl_GetIntFromObj((Tcl_Interp *) NULL, objv[1], &code); if (result != TCL_OK) { Tcl_ResetResult(interp); Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad completion code \"", Tcl_GetStringFromObj(objv[1], (int *) NULL), "\": must be ok, error, return, break, ", "continue, or an integer", (char *) NULL); return result; } } } else if (strcmp(option, "-errorinfo") == 0) { iPtr->errorInfo = (char *) ckalloc((unsigned) (strlen(arg) + 1)); strcpy(iPtr->errorInfo, arg); } else if (strcmp(option, "-errorcode") == 0) { iPtr->errorCode = (char *) ckalloc((unsigned) (strlen(arg) + 1)); strcpy(iPtr->errorCode, arg); } else { Tcl_AppendStringsToObj(Tcl_GetObjResult(interp), "bad option \"", option, "\": must be -code, -errorcode, or -errorinfo", (char *) NULL); return TCL_ERROR; } } if (objc == 1) { /* * Set the interpreter's object result. An inline version of * Tcl_SetObjResult. */ Tcl_SetObjResult(interp, objv[0]); } iPtr->returnCode = code; return TCL_RETURN;}/* *---------------------------------------------------------------------- * * Tcl_ScanCmd -- * * This procedure is invoked to process the "scan" 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_ScanCmd(dummy, interp, argc, argv) ClientData dummy; /* Not used. */ Tcl_Interp *interp; /* Current interpreter. */ int argc; /* Number of arguments. */ char **argv; /* Argument strings. */{# define MAX_FIELDS 20 typedef struct { char fmt; /* Format for field. */ int size; /* How many bytes to allow for * field. */ char *location; /* Where field will be stored. */ } Field; Field fields[MAX_FIELDS]; /* Info about all the fields in the * format string. */ register Field *curField; int numFields = 0; /* Number of fields actually * specified. */ int suppress; /* Current field is assignment- * suppressed. */ int totalSize = 0; /* Number of bytes needed to store * all results combined. */ char *results; /* Where scanned output goes. * Malloced; NULL means not allocated * yet. */ int numScanned; /* sscanf's result. */ register char *fmt; int i, widthSpecified, length, code; char buf[40]; /* * The variables below are used to hold a copy of the format * string, so that we can replace format specifiers like "%f" * and "%F" with specifiers like "%lf" */# define STATIC_SIZE 5 char copyBuf[STATIC_SIZE], *fmtCopy; register char *dst; if (argc < 3) { Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " string format ?varName varName ...?\"", (char *) NULL); return TCL_ERROR; } /* * This procedure operates in four stages: * 1. Scan the format string, collecting information about each field. * 2. Allocate an array to hold all of the scanned fields. * 3. Call sscanf to do all the dirty work, and have it store the * parsed fields in the array. * 4. Pick off the fields from the array and assign them to variables. */ code = TCL_OK; results = NULL; length = strlen(argv[2]) * 2 + 1; if (length < STATIC_SIZE) { fmtCopy = copyBuf; } else { fmtCopy = (char *) ckalloc((unsigned) length); } dst = fmtCopy; for (fmt = argv[2]; *fmt != 0; fmt++) { *dst = *fmt; dst++; if (*fmt != '%') { continue; } fmt++; if (*fmt == '%') { *dst = *fmt; dst++; continue; } if (*fmt == '*') { suppress = 1; *dst = *fmt; dst++; fmt++; } else { suppress = 0; } widthSpecified = 0; while (isdigit(UCHAR(*fmt))) { widthSpecified = 1; *dst = *fmt; dst++; fmt++; } if ((*fmt == 'l') || (*fmt == 'h') || (*fmt == 'L')) { fmt++; } *dst = *fmt; dst++; if (suppress) { continue; } if (numFields == MAX_FIELDS) { Tcl_SetResult(interp, "too many fields to scan", TCL_STATIC); code = TCL_ERROR; goto done; } curField = &fields[numFields]; numFields++; switch (*fmt) { case 'd': case 'i': case 'o': case 'x': curField->fmt = 'd'; curField->size = sizeof(int); break; case 'u': curField->fmt = 'u'; curField->size = sizeof(int); break; case 's': curField->fmt = 's'; curField->size = strlen(argv[1]) + 1; break; case 'c': if (widthSpecified) { Tcl_SetResult(interp, "field width may not be specified in %c conversion", TCL_STATIC); code = TCL_ERROR; goto done; } curField->fmt = 'c'; curField->size = sizeof(int); break; case 'e': case 'f': case 'g': dst[-1] = 'l'; dst[0] = 'f'; dst++; curField->fmt = 'f'; curField->size = sizeof(double); break; case '[': curField->fmt = 's'; curField->size = strlen(argv[1]) + 1; do { fmt++; if (*fmt == 0) { Tcl_SetResult(interp, "unmatched [ in format string", TCL_STATIC); code = TCL_ERROR; goto done; } *dst = *fmt; dst++; } while (*fmt != ']'); break; default: { char buf[50]; sprintf(buf, "bad scan conversion character \"%c\"", *fmt); Tcl_SetResult(interp, buf, TCL_VOLATILE); code = TCL_ERROR; goto done; } } curField->size = TCL_ALIGN(curField->size); totalSize += curField->size; } *dst = 0; if (numFields != (argc-3)) { Tcl_SetResult(interp, "different numbers of variable names and field specifiers", TCL_STATIC); code = TCL_ERROR; goto done; } /* * Step 2: */ results = (char *) ckalloc((unsigned) totalSize); for (i = 0, totalSize = 0, curField = fields; i < numFields; i++, curField++) { curField->location = results + totalSize; totalSize += curField->size; } /* * Fill in the remaining fields with NULL; the only purpose of * this is to keep some memory analyzers, like Purify, from * complaining. */ for ( ; i < MAX_FIELDS; i++, curField++) { curField->location = NULL; } /* * Step 3: */ numScanned = sscanf(argv[1], fmtCopy, fields[0].location, fields[1].location, fields[2].location, fields[3].location, fields[4].location, fields[5].location, fields[6].location, fields[7].location, fields[8].location, fields[9].location, fields[10].location, fields[11].location, fields[12].location, fields[13].location, fields[14].location, fields[15].location, fields[16].location, fields[17].location, fields[18].location, fields[19].location); /* * Step 4: */ if (numScanned < numFields) { numFields = numScanned; } for (i = 0, curField = fields; i < numFields; i++, curField++) { switch (curField->fmt) { char string[TCL_DOUBLE_SPACE]; case 'd': TclFormatInt(string, *((int *) curField->location)); if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) { storeError: Tcl_AppendResult(interp, "couldn't set variable \"", argv[i+3], "\"", (char *) NULL); code = TCL_ERROR; goto done; } break; case 'u': sprintf(string, "%u", *((int *) curField->location)); if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) { goto storeError; } break; case 'c': TclFormatInt(string, *((char *) curField->location) & 0xff); if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) { goto storeError; } break; case 's': if (Tcl_SetVar(interp, argv[i+3], curField->location, 0) == NULL) { goto storeError; } break; case 'f': Tcl_PrintDouble((Tcl_Interp *) NULL, *((double *) curField->location), string); if (Tcl_SetVar(interp, argv[i+3], string, 0) == NULL) { goto storeError; } break; } } TclFormatInt(buf, numScanned); Tcl_SetResult(interp, buf, TCL_VOLATILE); done: if (results != NULL) { ckfree(results); } if (fmtCopy != copyBuf) { ckfree(fmtCopy); } return code;}/* *---------------------------------------------------------------------- * * Tcl_SourceObjCmd -- * * This procedure is invoked to process the "source" 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_SourceObjCmd(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 *bytes; int result; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "fileName"); return TCL_ERROR; } /* * THIS FAILS IF THE OBJECT'S STRING REP CONTAINS A NULL. */ bytes = Tcl_GetStringFromObj(objv[1], (int *) NULL); result = Tcl_EvalFile(interp, bytes); return result;}/* *---------------------------------------------------------------------- * * Tcl_SplitObjCmd -- * * This procedure is invoked to process the "split" 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_SplitObjCmd(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 char *p, *p2; char *splitChars, *string, *elementStart; int splitCharLen, stringLen, i, j; Tcl_Obj *listPtr; if (objc == 2) { splitChars = " \n\t\r"; splitCharLen = 4; } else if (objc == 3) { splitChars = Tcl_GetStringFromObj(objv[2], &splitCharLen); } else { Tcl_WrongNumArgs(interp, 1, objv, "string ?splitChars?"); return TCL_ERROR; } string = Tcl_GetStringFromObj(objv[1], &stringLen); listPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); /* * Handle the special case of splitting on every character. */ if (splitCharLen == 0) { for (i = 0, p = string; i < stringLen; i++, p++) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(p, 1)); } } else { /* * Normal case: split on any of a given set of characters. * Discard instances of the split characters. */ for (i = 0, p = elementStart = string; i < stringLen; i++, p++) { for (j = 0, p2 = splitChars; j < splitCharLen; j++, p2++) { if (*p2 == *p) { Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(elementStart, (p-elementStart))); elementStart = p+1; break; } } } if (p != string) { int remainingChars = stringLen - (elementStart-string); Tcl_ListObjAppendElement(interp, listPtr, Tcl_NewStringObj(elementStart, remainingChars)); } } Tcl_SetObjResult(interp, listPtr); return TCL_OK;}/* *---------------------------------------------------------------------- * * Tcl_StringObjCmd -- * * This procedure is invoked to process the "string" 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_StringObjCmd(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 index, left, right; Tcl_Obj *resultPtr; char *string1, *string2; int length1, length2; static char *options[] = { "compare", "first", "index", "last", "length", "match", "range", "tolower", "toupper", "trim", "trimleft", "trimright", "wordend", "wordstart", NULL }; enum options { STR_COMPARE, STR_FIRST, STR_INDEX, STR_LAST, STR_LENGTH, STR_MATCH, STR_RANGE, STR_TOLOWER, STR_TOUPPER, STR_TRIM, STR_TRIMLEFT, STR_TRIMRIGHT, STR_WORDEND, STR_WORDSTART }; if (objc < 2) { Tcl_WrongNumArgs(interp, 1, objv, "option arg ?arg ...?"); return TCL_ERROR; } if (Tcl_GetIndexFromObj(interp, objv[1], options, "option", 0, &index) != TCL_OK) { return TCL_ERROR; } resultPtr = Tcl_GetObjResult(interp); switch ((enum options) index) { case STR_COMPARE: { int match, length; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "string1 string2"); return TCL_ERROR; } string1 = Tcl_GetStringFromObj(objv[2], &length1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -