*** generic/tclCmdMZ.c.orig Wed May 26 00:34:40 1999 --- generic/tclCmdMZ.c Thu Jul 15 14:48:52 1999 *************** *** 2047,2052 **** --- 2047,2053 ---- enum options { OPT_EXACT, OPT_GLOB, OPT_REGEXP, OPT_LAST }; + int splitObjs, seenComment; mode = OPT_EXACT; for (i = 1; i < objc; i++) { *************** *** 2080,2085 **** --- 2081,2087 ---- * argument, split them out again. */ + splitObjs = 0; if (objc == 1) { Tcl_Obj **listv; *************** *** 2087,2099 **** --- 2089,2114 ---- return TCL_ERROR; } objv = listv; + splitObjs = 1; } + seenComment = 0; for (i = 0; i < objc; i += 2) { if (i == objc - 1) { Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), "extra switch pattern with no body", -1); + + /* + * Check if this can be due to a badly placed comment + * in the switch block + */ + + if (splitObjs && seenComment) { + Tcl_AppendToObj(Tcl_GetObjResult(interp), + "; this can be due to a comment incorrectly placed outside a switch body - see the Tcl and switch man pages", -1); + } + return TCL_ERROR; } *************** *** 2102,2107 **** --- 2117,2133 ---- */ pattern = Tcl_GetString(objv[i]); + + /* + * The following is an heuristic to detect the infamous + * "comment in switch" error: just check if a pattern + * begins with '#'. + */ + + if (splitObjs && *pattern == '#') { + seenComment = 1; + } + matched = 0; if ((i == objc - 2) && (*pattern == 'd') *** generic/tclGet.c.orig Fri Apr 16 23:01:20 1999 --- generic/tclGet.c Thu Jul 15 14:05:32 1999 *************** *** 71,76 **** --- 71,77 ---- if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "expected integer but got \"", string, "\"", (char *) NULL); + TclCheckBadOctal(interp, p); } return TCL_ERROR; } *************** *** 157,162 **** --- 158,164 ---- if (interp != (Tcl_Interp *) NULL) { Tcl_AppendResult(interp, "expected integer but got \"", string, "\"", (char *) NULL); + TclCheckBadOctal(interp, p); } return TCL_ERROR; } *** generic/tclObj.c.orig Thu May 13 00:47:16 1999 --- generic/tclObj.c Thu Jul 15 14:08:24 1999 *************** *** 1685,1690 **** --- 1685,1691 ---- sprintf(buf, "expected integer but got \"%.50s\"", string); Tcl_ResetResult(interp); Tcl_AppendToObj(Tcl_GetObjResult(interp), buf, -1); + TclCheckBadOctal(interp, p); } return TCL_ERROR; } *** generic/tclExecute.c.orig Fri Apr 16 23:01:20 1999 --- generic/tclExecute.c Thu Jul 15 15:14:00 1999 *************** *** 3080,3085 **** --- 3080,3088 ---- (isDouble? "floating-point value" : "non-numeric string"), " as operand of \"", operatorStrings[opCode - INST_LOR], "\"", (char *) NULL); + if (opndPtr->typePtr != &tclDoubleType) { + TclCheckBadOctal(interp, Tcl_GetString(opndPtr)); + } } } *** generic/tclUtil.c.orig Wed May 26 00:34:40 1999 --- generic/tclUtil.c Thu Jul 15 14:56:24 1999 *************** *** 2249,2258 **** --- 2249,2311 ---- "bad index \"", bytes, "\": must be integer or end?-integer?", (char *) NULL); + TclCheckBadOctal(interp, bytes); } return TCL_ERROR; } return TCL_OK; + } + + /* + *---------------------------------------------------------------------- + * + * TclCheckBadOctal -- + * + * This procedure checks for a bad octal value and appends a + * meaningful error to the interp's result. + * + * Results: + * 1 if the argument was a bad octal, else 0. + * + * Side effects: + * The interpreter's result is modified. + * + *---------------------------------------------------------------------- + */ + + int + TclCheckBadOctal(interp, value) + Tcl_Interp *interp; /* Interpreter to use for error reporting. + * If NULL, then no error message is left + * after errors. */ + char *value; /* String to check. */ + { + char *p; + + /* + * A frequent mistake is invalid octal values due to an unwanted + * leading zero. Try to generate a meaningful error message. + */ + + p = value; + if (*p == '+' || *p == '-') { + p++; + } + if (*p == '0') { + while (isdigit(UCHAR(*p))) { + p++; + } + if (*p == '\0') { + /* Reached end of string */ + if (interp) { + Tcl_AppendResult(interp, + "; \"", value, "\" uses an incorrect octal representation - see the expr man page", + (char *) NULL); + } + return 1; + } + } + return 0; } /* *** generic/tclInt.h.orig Wed May 26 00:34:40 1999 --- generic/tclInt.h Thu Jul 15 14:20:26 1999 *************** *** 1544,1549 **** --- 1544,1551 ---- EXTERN void TclAllocateFreeObjects _ANSI_ARGS_((void)); EXTERN int TclArraySet _ANSI_ARGS_((Tcl_Interp *interp, Tcl_Obj *arrayNameObj, Tcl_Obj *arrayElemObj)); + EXTERN int TclCheckBadOctal _ANSI_ARGS_((Tcl_Interp *interp, + char *value)); EXTERN int TclCleanupChildren _ANSI_ARGS_((Tcl_Interp *interp, int numPids, Tcl_Pid *pidPtr, Tcl_Channel errorChan));