summaryrefslogtreecommitdiffstats
path: root/generic/tclScan.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclScan.c')
-rw-r--r--generic/tclScan.c136
1 files changed, 82 insertions, 54 deletions
diff --git a/generic/tclScan.c b/generic/tclScan.c
index 229f3fa..3edb8be 100644
--- a/generic/tclScan.c
+++ b/generic/tclScan.c
@@ -43,10 +43,10 @@ typedef struct CharSet {
* Declarations for functions used only in this file.
*/
-static char * BuildCharSet(CharSet *cset, char *format);
+static const char * BuildCharSet(CharSet *cset, const char *format);
static int CharInSet(CharSet *cset, int ch);
static void ReleaseCharSet(CharSet *cset);
-static int ValidateFormat(Tcl_Interp *interp, char *format,
+static int ValidateFormat(Tcl_Interp *interp, const char *format,
int numVars, int *totalVars);
/*
@@ -67,14 +67,14 @@ static int ValidateFormat(Tcl_Interp *interp, char *format,
*----------------------------------------------------------------------
*/
-static char *
+static const char *
BuildCharSet(
CharSet *cset,
- char *format) /* Points to first char of set. */
+ const char *format) /* Points to first char of set. */
{
Tcl_UniChar ch, start;
int offset, nranges;
- char *end;
+ const char *end;
memset(cset, 0, sizeof(CharSet));
@@ -101,10 +101,9 @@ BuildCharSet(
end += Tcl_UtfToUniChar(end, &ch);
}
- cset->chars = (Tcl_UniChar *)
- ckalloc(sizeof(Tcl_UniChar) * (end - format - 1));
+ cset->chars = ckalloc(sizeof(Tcl_UniChar) * (end - format - 1));
if (nranges > 0) {
- cset->ranges = (struct Range *) ckalloc(sizeof(struct Range)*nranges);
+ cset->ranges = ckalloc(sizeof(struct Range) * nranges);
} else {
cset->ranges = NULL;
}
@@ -224,9 +223,9 @@ static void
ReleaseCharSet(
CharSet *cset)
{
- ckfree((char *)cset->chars);
+ ckfree(cset->chars);
if (cset->ranges) {
- ckfree((char *)cset->ranges);
+ ckfree(cset->ranges);
}
}
@@ -250,7 +249,7 @@ ReleaseCharSet(
static int
ValidateFormat(
Tcl_Interp *interp, /* Current interpreter. */
- char *format, /* The format string. */
+ const char *format, /* The format string. */
int numVars, /* The number of variables passed to the scan
* command. */
int *totalSubs) /* The number of variables that will be
@@ -260,8 +259,12 @@ ValidateFormat(
char *end;
Tcl_UniChar ch;
int objIndex, xpgSize, nspace = numVars;
- int *nassign = (int *) TclStackAlloc(interp, nspace * sizeof(int));
+ int *nassign = TclStackAlloc(interp, nspace * sizeof(int));
char buf[TCL_UTF_MAX+1];
+ Tcl_Obj *errorMsg; /* Place to build an error messages. Note that
+ * these are messy operations because we do
+ * not want to use the formatting engine;
+ * we're inside there! */
/*
* Initialize an array that records the number of times a variable is
@@ -329,9 +332,10 @@ ValidateFormat(
gotSequential = 1;
if (gotXpg) {
mixedXPG:
- Tcl_SetResult(interp,
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"cannot mix \"%\" and \"%n$\" conversion specifiers",
- TCL_STATIC);
+ -1));
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "MIXEDSPECTYPES", NULL);
goto error;
}
@@ -341,7 +345,7 @@ ValidateFormat(
*/
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
- value = strtoul(format-1, &format, 10); /* INTL: "C" locale. */
+ value = strtoul(format-1, (char **) &format, 10); /* INTL: "C" locale. */
flags |= SCAN_WIDTH;
format += Tcl_UtfToUniChar(format, &ch);
}
@@ -375,9 +379,10 @@ ValidateFormat(
switch (ch) {
case 'c':
if (flags & SCAN_WIDTH) {
- Tcl_SetResult(interp,
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"field width may not be specified in %c conversion",
- TCL_STATIC);
+ -1));
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADWIDTH", NULL);
goto error;
}
/*
@@ -388,9 +393,12 @@ ValidateFormat(
if (flags & (SCAN_LONGER|SCAN_BIG)) {
invalidFieldSize:
buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
- Tcl_AppendResult(interp,
- "field size modifier may not be specified in %", buf,
- " conversion", NULL);
+ errorMsg = Tcl_NewStringObj(
+ "field size modifier may not be specified in %", -1);
+ Tcl_AppendToObj(errorMsg, buf, -1);
+ Tcl_AppendToObj(errorMsg, " conversion", -1);
+ Tcl_SetObjResult(interp, errorMsg);
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADSIZE", NULL);
goto error;
}
/*
@@ -406,11 +414,13 @@ ValidateFormat(
case 'o':
case 'x':
case 'X':
+ case 'b':
break;
case 'u':
if (flags & SCAN_BIG) {
- Tcl_SetResult(interp,
- "unsigned bignum scans are invalid", TCL_STATIC);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unsigned bignum scans are invalid", -1));
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADUNSIGNED",NULL);
goto error;
}
break;
@@ -445,18 +455,19 @@ ValidateFormat(
}
break;
badSet:
- Tcl_SetResult(interp, "unmatched [ in format string",
- TCL_STATIC);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unmatched [ in format string", -1));
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BRACKET", NULL);
goto error;
default:
- {
- char buf[TCL_UTF_MAX+1];
-
- buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
- Tcl_AppendResult(interp, "bad scan conversion character \"",
- buf, "\"", NULL);
- goto error;
- }
+ buf[Tcl_UniCharToUtf(ch, buf)] = '\0';
+ errorMsg = Tcl_NewStringObj(
+ "bad scan conversion character \"", -1);
+ Tcl_AppendToObj(errorMsg, buf, -1);
+ Tcl_AppendToObj(errorMsg, "\"", -1);
+ Tcl_SetObjResult(interp, errorMsg);
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADTYPE", NULL);
+ goto error;
}
if (!(flags & SCAN_SUPPRESS)) {
if (objIndex >= nspace) {
@@ -472,7 +483,7 @@ ValidateFormat(
} else {
nspace += 16; /* formerly STATIC_LIST_SIZE */
}
- nassign = (int *) TclStackRealloc(interp, nassign,
+ nassign = TclStackRealloc(interp, nassign,
nspace * sizeof(int));
for (i = value; i < nspace; i++) {
nassign[i] = 0;
@@ -499,9 +510,10 @@ ValidateFormat(
}
for (i = 0; i < numVars; i++) {
if (nassign[i] > 1) {
- Tcl_SetResult(interp,
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"variable is assigned by multiple \"%n$\" conversion specifiers",
- TCL_STATIC);
+ -1));
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "POLYASSIGNED", NULL);
goto error;
} else if (!xpgSize && (nassign[i] == 0)) {
/*
@@ -509,9 +521,10 @@ ValidateFormat(
* and/or numVars != 0), then too many vars were given
*/
- Tcl_SetResult(interp,
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"variable is not assigned by any conversion specifiers",
- TCL_STATIC);
+ -1));
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "UNASSIGNED", NULL);
goto error;
}
}
@@ -521,12 +534,14 @@ ValidateFormat(
badIndex:
if (gotXpg) {
- Tcl_SetResult(interp, "\"%n$\" argument index out of range",
- TCL_STATIC);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "\"%n$\" argument index out of range", -1));
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "INDEXRANGE", NULL);
} else {
- Tcl_SetResult(interp,
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
"different numbers of variable names and field specifiers",
- TCL_STATIC);
+ -1));
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT", "FIELDVARMISMATCH", NULL);
}
error:
@@ -554,16 +569,16 @@ ValidateFormat(
/* ARGSUSED */
int
Tcl_ScanObjCmd(
- ClientData dummy, /* Not used. */
+ ClientData dummy, /* Not used. */
Tcl_Interp *interp, /* Current interpreter. */
int objc, /* Number of arguments. */
- Tcl_Obj *CONST objv[]) /* Argument objects. */
+ Tcl_Obj *const objv[]) /* Argument objects. */
{
- char *format;
+ const char *format;
int numVars, nconversions, totalVars = -1;
int objIndex, offset, i, result, code;
long value;
- CONST char *string, *end, *baseString;
+ const char *string, *end, *baseString;
char op = 0;
int width, underflow = 0;
Tcl_WideInt wideValue;
@@ -576,11 +591,11 @@ Tcl_ScanObjCmd(
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv,
- "string format ?varName varName ...?");
+ "string format ?varName ...?");
return TCL_ERROR;
}
- format = Tcl_GetStringFromObj(objv[2], NULL);
+ format = Tcl_GetString(objv[2]);
numVars = objc-3;
/*
@@ -596,13 +611,13 @@ Tcl_ScanObjCmd(
*/
if (totalVars > 0) {
- objs = (Tcl_Obj **) ckalloc(sizeof(Tcl_Obj*) * totalVars);
+ objs = ckalloc(sizeof(Tcl_Obj *) * totalVars);
for (i = 0; i < totalVars; i++) {
objs[i] = NULL;
}
}
- string = Tcl_GetStringFromObj(objv[1], NULL);
+ string = Tcl_GetString(objv[1]);
baseString = string;
/*
@@ -676,7 +691,7 @@ Tcl_ScanObjCmd(
*/
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
- width = (int) strtoul(format-1, &format, 10);/* INTL: "C" locale. */
+ width = (int) strtoul(format-1, (char **) &format, 10);/* INTL: "C" locale. */
format += Tcl_UtfToUniChar(format, &ch);
} else {
width = 0;
@@ -712,6 +727,7 @@ Tcl_ScanObjCmd(
if (!(flags & SCAN_SUPPRESS)) {
objPtr = Tcl_NewIntObj(string - baseString);
Tcl_IncrRefCount(objPtr);
+ CLANG_ASSERT(objs);
objs[objIndex++] = objPtr;
}
nconversions++;
@@ -734,6 +750,10 @@ Tcl_ScanObjCmd(
op = 'i';
parseFlag |= TCL_PARSE_HEXADECIMAL_ONLY;
break;
+ case 'b':
+ op = 'i';
+ parseFlag |= TCL_PARSE_BINARY_ONLY;
+ break;
case 'u':
op = 'i';
parseFlag |= TCL_PARSE_DECIMAL_ONLY;
@@ -818,6 +838,7 @@ Tcl_ScanObjCmd(
if (!(flags & SCAN_SUPPRESS)) {
objPtr = Tcl_NewStringObj(string, end-string);
Tcl_IncrRefCount(objPtr);
+ CLANG_ASSERT(objs);
objs[objIndex++] = objPtr;
}
string = end;
@@ -868,6 +889,7 @@ Tcl_ScanObjCmd(
if (!(flags & SCAN_SUPPRESS)) {
objPtr = Tcl_NewIntObj((int)sch);
Tcl_IncrRefCount(objPtr);
+ CLANG_ASSERT(objs);
objs[objIndex++] = objPtr;
}
break;
@@ -972,6 +994,7 @@ Tcl_ScanObjCmd(
}
}
Tcl_SetDoubleObj(objPtr, dvalue);
+ CLANG_ASSERT(objs);
objs[objIndex++] = objPtr;
string = end;
}
@@ -993,9 +1016,14 @@ Tcl_ScanObjCmd(
continue;
}
result++;
- if (Tcl_ObjSetVar2(interp, objv[i+3], NULL, objs[i], 0) == NULL) {
- Tcl_AppendResult(interp, "couldn't set variable \"",
- TclGetString(objv[i+3]), "\"", NULL);
+
+ /*
+ * In case of multiple errors in setting variables, just report
+ * the first one.
+ */
+
+ if (Tcl_ObjSetVar2(interp, objv[i+3], NULL, objs[i],
+ (code == TCL_OK) ? TCL_LEAVE_ERR_MSG : 0) == NULL) {
code = TCL_ERROR;
}
Tcl_DecrRefCount(objs[i]);
@@ -1021,7 +1049,7 @@ Tcl_ScanObjCmd(
}
}
if (objs != NULL) {
- ckfree((char*) objs);
+ ckfree(objs);
}
if (code == TCL_OK) {
if (underflow && (nconversions == 0)) {