summaryrefslogtreecommitdiffstats
path: root/generic/tclScan.c
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2018-09-04 19:47:55 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2018-09-04 19:47:55 (GMT)
commitfbef9aa84089336e767f0dafe410df51b4f1d3b3 (patch)
treead9c157389b8b2213ce0693d89ccfcf48a1509c6 /generic/tclScan.c
parent24197ad684cf243d80448a14b0aead5099299150 (diff)
parent2f2b7f6ac7122f3b6be07e793e1658cdb5791aa2 (diff)
downloadtcl-fbef9aa84089336e767f0dafe410df51b4f1d3b3.zip
tcl-fbef9aa84089336e767f0dafe410df51b4f1d3b3.tar.gz
tcl-fbef9aa84089336e767f0dafe410df51b4f1d3b3.tar.bz2
merge core-8-branch
Diffstat (limited to 'generic/tclScan.c')
-rw-r--r--generic/tclScan.c134
1 files changed, 83 insertions, 51 deletions
diff --git a/generic/tclScan.c b/generic/tclScan.c
index ef7eedf..0e3da17 100644
--- a/generic/tclScan.c
+++ b/generic/tclScan.c
@@ -10,6 +10,7 @@
*/
#include "tclInt.h"
+#include "tommath.h"
/*
* Flag values used by Tcl_ScanObjCmd.
@@ -72,17 +73,17 @@ BuildCharSet(
CharSet *cset,
const char *format) /* Points to first char of set. */
{
- Tcl_UniChar ch, start;
+ Tcl_UniChar ch = 0, start;
int offset, nranges;
const char *end;
memset(cset, 0, sizeof(CharSet));
- offset = Tcl_UtfToUniChar(format, &ch);
+ offset = TclUtfToUniChar(format, &ch);
if (ch == '^') {
cset->exclude = 1;
format += offset;
- offset = Tcl_UtfToUniChar(format, &ch);
+ offset = TclUtfToUniChar(format, &ch);
}
end = format + offset;
@@ -91,14 +92,14 @@ BuildCharSet(
*/
if (ch == ']') {
- end += Tcl_UtfToUniChar(end, &ch);
+ end += TclUtfToUniChar(end, &ch);
}
nranges = 0;
while (ch != ']') {
if (ch == '-') {
nranges++;
}
- end += Tcl_UtfToUniChar(end, &ch);
+ end += TclUtfToUniChar(end, &ch);
}
cset->chars = ckalloc(sizeof(Tcl_UniChar) * (end - format - 1));
@@ -113,11 +114,11 @@ BuildCharSet(
*/
cset->nchars = cset->nranges = 0;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
start = ch;
if (ch == ']' || ch == '-') {
cset->chars[cset->nchars++] = ch;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
}
while (ch != ']') {
if (*format == '-') {
@@ -138,7 +139,7 @@ BuildCharSet(
cset->chars[cset->nchars++] = start;
cset->chars[cset->nchars++] = ch;
} else {
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
/*
* Check to see if the range is in reverse order.
@@ -156,7 +157,7 @@ BuildCharSet(
} else {
cset->chars[cset->nchars++] = ch;
}
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
}
return format;
}
@@ -257,7 +258,7 @@ ValidateFormat(
{
int gotXpg, gotSequential, value, i, flags;
char *end;
- Tcl_UniChar ch;
+ Tcl_UniChar ch = 0;
int objIndex, xpgSize, nspace = numVars;
int *nassign = TclStackAlloc(interp, nspace * sizeof(int));
char buf[TCL_UTF_MAX+1];
@@ -279,20 +280,20 @@ ValidateFormat(
xpgSize = objIndex = gotXpg = gotSequential = 0;
while (*format != '\0') {
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
flags = 0;
if (ch != '%') {
continue;
}
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
if (ch == '%') {
continue;
}
if (ch == '*') {
flags |= SCAN_SUPPRESS;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
goto xpgCheckDone;
}
@@ -308,7 +309,7 @@ ValidateFormat(
goto notXpg;
}
format = end+1;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
gotXpg = 1;
if (gotSequential) {
goto mixedXPG;
@@ -347,7 +348,7 @@ ValidateFormat(
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
value = strtoul(format-1, (char **) &format, 10); /* INTL: "C" locale. */
flags |= SCAN_WIDTH;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
}
/*
@@ -359,13 +360,13 @@ ValidateFormat(
if (*format == 'l') {
flags |= SCAN_BIG;
format += 1;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
break;
}
case 'L':
flags |= SCAN_LONGER;
case 'h':
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
}
if (!(flags & SCAN_SUPPRESS) && numVars && (objIndex >= numVars)) {
@@ -406,20 +407,16 @@ ValidateFormat(
*/
case 'd':
case 'e':
+ case 'E':
case 'f':
case 'g':
+ case 'G':
case 'i':
case 'o':
case 'x':
+ case 'X':
case 'b':
- break;
case 'u':
- if (flags & SCAN_BIG) {
- Tcl_SetObjResult(interp, Tcl_NewStringObj(
- "unsigned bignum scans are invalid", -1));
- Tcl_SetErrorCode(interp, "TCL", "FORMAT", "BADUNSIGNED",NULL);
- goto error;
- }
break;
/*
* Bracket terms need special checking
@@ -431,24 +428,24 @@ ValidateFormat(
if (*format == '\0') {
goto badSet;
}
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
if (ch == '^') {
if (*format == '\0') {
goto badSet;
}
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
}
if (ch == ']') {
if (*format == '\0') {
goto badSet;
}
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
}
while (ch != ']') {
if (*format == '\0') {
goto badSet;
}
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
}
break;
badSet:
@@ -579,7 +576,7 @@ Tcl_ScanObjCmd(
char op = 0;
int width, underflow = 0;
Tcl_WideInt wideValue;
- Tcl_UniChar ch, sch;
+ Tcl_UniChar ch = 0, sch = 0;
Tcl_Obj **objs = NULL, *objPtr = NULL;
int flags;
char buf[513]; /* Temporary buffer to hold scanned number
@@ -592,7 +589,7 @@ Tcl_ScanObjCmd(
return TCL_ERROR;
}
- format = Tcl_GetStringFromObj(objv[2], NULL);
+ format = Tcl_GetString(objv[2]);
numVars = objc-3;
/*
@@ -614,7 +611,7 @@ Tcl_ScanObjCmd(
}
}
- string = Tcl_GetStringFromObj(objv[1], NULL);
+ string = Tcl_GetString(objv[1]);
baseString = string;
/*
@@ -627,7 +624,7 @@ Tcl_ScanObjCmd(
nconversions = 0;
while (*format != '\0') {
int parseFlag = TCL_PARSE_NO_WHITESPACE;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
flags = 0;
@@ -636,13 +633,13 @@ Tcl_ScanObjCmd(
*/
if (Tcl_UniCharIsSpace(ch)) {
- offset = Tcl_UtfToUniChar(string, &sch);
+ offset = TclUtfToUniChar(string, &sch);
while (Tcl_UniCharIsSpace(sch)) {
if (*string == '\0') {
goto done;
}
string += offset;
- offset = Tcl_UtfToUniChar(string, &sch);
+ offset = TclUtfToUniChar(string, &sch);
}
continue;
}
@@ -653,14 +650,14 @@ Tcl_ScanObjCmd(
underflow = 1;
goto done;
}
- string += Tcl_UtfToUniChar(string, &sch);
+ string += TclUtfToUniChar(string, &sch);
if (ch != sch) {
goto done;
}
continue;
}
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
if (ch == '%') {
goto literal;
}
@@ -672,13 +669,13 @@ Tcl_ScanObjCmd(
if (ch == '*') {
flags |= SCAN_SUPPRESS;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
} else if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
char *formatEnd;
value = strtoul(format-1, &formatEnd, 10);/* INTL: "C" locale. */
if (*formatEnd == '$') {
format = formatEnd+1;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
objIndex = (int) value - 1;
}
}
@@ -689,7 +686,7 @@ Tcl_ScanObjCmd(
if ((ch < 0x80) && isdigit(UCHAR(ch))) { /* INTL: "C" locale. */
width = (int) strtoul(format-1, (char **) &format, 10);/* INTL: "C" locale. */
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
} else {
width = 0;
}
@@ -703,7 +700,7 @@ Tcl_ScanObjCmd(
if (*format == 'l') {
flags |= SCAN_BIG;
format += 1;
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
break;
}
case 'L':
@@ -712,7 +709,7 @@ Tcl_ScanObjCmd(
* Fall through so we skip to the next character.
*/
case 'h':
- format += Tcl_UtfToUniChar(format, &ch);
+ format += TclUtfToUniChar(format, &ch);
}
/*
@@ -743,6 +740,7 @@ Tcl_ScanObjCmd(
parseFlag |= TCL_PARSE_OCTAL_ONLY | TCL_PARSE_SCAN_PREFIXES;
break;
case 'x':
+ case 'X':
op = 'i';
parseFlag |= TCL_PARSE_HEXADECIMAL_ONLY;
break;
@@ -758,7 +756,9 @@ Tcl_ScanObjCmd(
case 'f':
case 'e':
+ case 'E':
case 'g':
+ case 'G':
op = 'f';
break;
@@ -793,7 +793,7 @@ Tcl_ScanObjCmd(
if (!(flags & SCAN_NOSKIP)) {
while (*string != '\0') {
- offset = Tcl_UtfToUniChar(string, &sch);
+ offset = TclUtfToUniChar(string, &sch);
if (!Tcl_UniCharIsSpace(sch)) {
break;
}
@@ -820,7 +820,7 @@ Tcl_ScanObjCmd(
}
end = string;
while (*end != '\0') {
- offset = Tcl_UtfToUniChar(end, &sch);
+ offset = TclUtfToUniChar(end, &sch);
if (Tcl_UniCharIsSpace(sch)) {
break;
}
@@ -848,7 +848,7 @@ Tcl_ScanObjCmd(
format = BuildCharSet(&cset, format);
while (*end != '\0') {
- offset = Tcl_UtfToUniChar(end, &sch);
+ offset = TclUtfToUniChar(end, &sch);
if (!CharInSet(&cset, (int)sch)) {
break;
}
@@ -879,9 +879,17 @@ Tcl_ScanObjCmd(
* Scan a single Unicode character.
*/
- string += Tcl_UtfToUniChar(string, &sch);
+ offset = TclUtfToUniChar(string, &sch);
+ i = (int)sch;
+#if TCL_UTF_MAX == 4
+ if (!offset) {
+ offset = TclUtfToUniChar(string, &sch);
+ i = (((i<<10) & 0x0FFC00) + 0x10000) + (sch & 0x3FF);
+ }
+#endif
+ string += offset;
if (!(flags & SCAN_SUPPRESS)) {
- objPtr = Tcl_NewIntObj((int)sch);
+ objPtr = Tcl_NewIntObj(i);
Tcl_IncrRefCount(objPtr);
CLANG_ASSERT(objs);
objs[objIndex++] = objPtr;
@@ -918,9 +926,9 @@ Tcl_ScanObjCmd(
}
if (flags & SCAN_LONGER) {
if (Tcl_GetWideIntFromObj(NULL, objPtr, &wideValue) != TCL_OK) {
- wideValue = ~(Tcl_WideUInt)0 >> 1; /* WIDE_MAX */
+ wideValue = LLONG_MAX;
if (TclGetString(objPtr)[0] == '-') {
- wideValue++; /* WIDE_MAX + 1 = WIDE_MIN */
+ wideValue = LLONG_MIN;
}
}
if ((flags & SCAN_UNSIGNED) && (wideValue < 0)) {
@@ -928,9 +936,33 @@ Tcl_ScanObjCmd(
(Tcl_WideUInt)wideValue);
Tcl_SetStringObj(objPtr, buf, -1);
} else {
- Tcl_SetWideIntObj(objPtr, wideValue);
+ TclSetIntObj(objPtr, wideValue);
}
- } else if (!(flags & SCAN_BIG)) {
+ } else if (flags & SCAN_BIG) {
+ if (flags & SCAN_UNSIGNED) {
+ mp_int big;
+ int code = Tcl_GetBignumFromObj(interp, objPtr, &big);
+
+ if (code == TCL_OK) {
+ if (mp_isneg(&big)) {
+ code = TCL_ERROR;
+ }
+ mp_clear(&big);
+ }
+
+ if (code == TCL_ERROR) {
+ if (objs != NULL) {
+ ckfree(objs);
+ }
+ Tcl_DecrRefCount(objPtr);
+ Tcl_SetObjResult(interp, Tcl_NewStringObj(
+ "unsigned bignum scans are invalid", -1));
+ Tcl_SetErrorCode(interp, "TCL", "FORMAT",
+ "BADUNSIGNED",NULL);
+ return TCL_ERROR;
+ }
+ }
+ } else {
if (TclGetLongFromObj(NULL, objPtr, &value) != TCL_OK) {
if (TclGetString(objPtr)[0] == '-') {
value = LONG_MIN;
@@ -942,7 +974,7 @@ Tcl_ScanObjCmd(
sprintf(buf, "%lu", value); /* INTL: ISO digit */
Tcl_SetStringObj(objPtr, buf, -1);
} else {
- Tcl_SetLongObj(objPtr, value);
+ TclSetIntObj(objPtr, value);
}
}
objs[objIndex++] = objPtr;