diff options
Diffstat (limited to 'generic/tclCompExpr.c')
| -rw-r--r-- | generic/tclCompExpr.c | 100 |
1 files changed, 74 insertions, 26 deletions
diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c index 74610c7..fa15fba 100644 --- a/generic/tclCompExpr.c +++ b/generic/tclCompExpr.c @@ -164,6 +164,8 @@ enum Marks { * "=" is encountered. */ #define INVALID 5 /* A parse error. Used when any punctuation * appears that's not a supported operator. */ +#define COMMENT 6 /* Comment. Lasts to end of line or end of + * expression, whichever comes first. */ /* Leaf lexemes */ @@ -462,7 +464,7 @@ static const unsigned char Lexeme[] = { INVALID /* FS */, INVALID /* GS */, INVALID /* RS */, INVALID /* US */, INVALID /* SPACE */, 0 /* ! or != */, - QUOTED /* " */, INVALID /* # */, + QUOTED /* " */, 0 /* # */, VARIABLE /* $ */, MOD /* % */, 0 /* & or && */, INVALID /* ' */, OPEN_PAREN /* ( */, CLOSE_PAREN /* ) */, @@ -674,9 +676,10 @@ ParseExpr( OpNode *newPtr = NULL; do { - if (size <= UINT_MAX/sizeof(OpNode)) { - newPtr = (OpNode *)attemptckrealloc(nodes, size * sizeof(OpNode)); - } + if (size <= UINT_MAX/sizeof(OpNode)) { + newPtr = (OpNode *) attemptckrealloc(nodes, + size * sizeof(OpNode)); + } } while ((newPtr == NULL) && ((size -= (size - nodesUsed) / 2) > nodesUsed)); if (newPtr == NULL) { @@ -708,6 +711,10 @@ ParseExpr( int b; switch (lexeme) { + case COMMENT: + start += scanned; + numBytes -= scanned; + continue; case INVALID: msg = Tcl_ObjPrintf("invalid character \"%.*s\"", scanned, start); @@ -742,6 +749,32 @@ ParseExpr( } else if (Tcl_GetBooleanFromObj(NULL,literal,&b) == TCL_OK) { lexeme = BOOLEAN; } else { + /* + * Tricky case: see test expr-62.10 + */ + + int scanned2 = scanned; + do { + scanned2 += TclParseAllWhiteSpace( + start + scanned2, numBytes - scanned2); + scanned2 += ParseLexeme( + start + scanned2, numBytes - scanned2, &lexeme, + NULL); + } while (lexeme == COMMENT); + if (lexeme == OPEN_PAREN) { + /* + * Actually a function call, but with obscuring + * comments. Skip to the start of the parentheses. + * Note that we assume that open parentheses are one + * byte long. + */ + + lexeme = FUNCTION; + Tcl_ListObjAppendElement(NULL, funcList, literal); + scanned = scanned2 - 1; + break; + } + Tcl_DecrRefCount(literal); msg = Tcl_ObjPrintf("invalid bareword \"%.*s%s\"", (scanned < limit) ? scanned : limit - 3, start, @@ -1009,7 +1042,7 @@ ParseExpr( * later. */ - literal = Tcl_NewObj(); + TclNewObj(literal); if (TclWordKnownAtCompileTime(tokenPtr, literal)) { Tcl_ListObjAppendElement(NULL, litList, literal); complete = lastParsed = OT_LITERAL; @@ -1836,11 +1869,13 @@ Tcl_ParseExpr( { int code; OpNode *opTree = NULL; /* Will point to the tree of operators. */ - Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals. */ - Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names. */ + Tcl_Obj *litList; /* List to hold the literals. */ + Tcl_Obj *funcList; /* List to hold the functon names. */ Tcl_Parse *exprParsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse)); /* Holds the Tcl_Tokens of substitutions. */ + TclNewObj(litList); + TclNewObj(funcList); if (numBytes < 0) { numBytes = (start ? strlen(start) : 0); } @@ -1892,8 +1927,8 @@ ParseLexeme( storage, if non-NULL. */ { const char *end; - int scanned; - Tcl_UniChar ch = 0; + int scanned, size; + int ch; Tcl_Obj *literal = NULL; unsigned char byte; @@ -1907,6 +1942,16 @@ ParseLexeme( return 1; } switch (byte) { + case '#': + /* + * Scan forward over the comment contents. + */ + for (size = 0; byte != '\n' && byte != 0 && size < numBytes; size++) { + byte = UCHAR(start[size]); + } + *lexemePtr = COMMENT; + return size - (byte == '\n'); + case '*': if ((numBytes > 1) && (start[1] == '*')) { *lexemePtr = EXPON; @@ -2040,7 +2085,7 @@ ParseLexeme( break; } - literal = Tcl_NewObj(); + TclNewObj(literal); if (TclParseNumber(NULL, literal, NULL, start, numBytes, &end, TCL_PARSE_NO_WHITESPACE) == TCL_OK) { if (end < start + numBytes && !TclIsBareword(*end)) { @@ -2100,14 +2145,14 @@ ParseLexeme( */ if (!TclIsBareword(*start) || *start == '_') { - if (Tcl_UtfCharComplete(start, numBytes)) { - scanned = TclUtfToUniChar(start, &ch); + if (TclUCS4Complete(start, numBytes)) { + scanned = TclUtfToUCS4(start, &ch); } else { - char utfBytes[4]; + char utfBytes[8]; memcpy(utfBytes, start, numBytes); utfBytes[numBytes] = '\0'; - scanned = TclUtfToUniChar(utfBytes, &ch); + scanned = TclUtfToUCS4(utfBytes, &ch); } *lexemePtr = INVALID; Tcl_DecrRefCount(literal); @@ -2154,12 +2199,15 @@ TclCompileExpr( int optimize) /* 0 for one-off expressions. */ { OpNode *opTree = NULL; /* Will point to the tree of operators */ - Tcl_Obj *litList = Tcl_NewObj(); /* List to hold the literals */ - Tcl_Obj *funcList = Tcl_NewObj(); /* List to hold the functon names*/ + Tcl_Obj *litList; /* List to hold the literals */ + Tcl_Obj *funcList; /* List to hold the functon names*/ Tcl_Parse *parsePtr = (Tcl_Parse *)TclStackAlloc(interp, sizeof(Tcl_Parse)); /* Holds the Tcl_Tokens of substitutions */ + int code; - int code = ParseExpr(interp, script, numBytes, &opTree, litList, + TclNewObj(litList); + TclNewObj(funcList); + code = ParseExpr(interp, script, numBytes, &opTree, litList, funcList, parsePtr, 0 /* parseOnly */); if (code == TCL_OK) { @@ -2458,8 +2506,8 @@ CompileExprTree( if (optimize) { int length; const char *bytes = TclGetStringFromObj(literal, &length); - int index = TclRegisterLiteral(envPtr, bytes, length, 0); - Tcl_Obj *objPtr = TclFetchLiteral(envPtr, index); + int idx = TclRegisterLiteral(envPtr, bytes, length, 0); + Tcl_Obj *objPtr = TclFetchLiteral(envPtr, idx); if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) { /* @@ -2479,7 +2527,7 @@ CompileExprTree( objPtr->internalRep = literal->internalRep; literal->typePtr = NULL; } - TclEmitPush(index, envPtr); + TclEmitPush(idx, envPtr); } else { /* * When optimize==0, we know the expression is a one-off and @@ -2505,7 +2553,7 @@ CompileExprTree( if (ExecConstantExprTree(interp, nodes, next, litObjvPtr) == TCL_OK) { - int index; + int idx; Tcl_Obj *objPtr = Tcl_GetObjResult(interp); /* @@ -2519,8 +2567,8 @@ CompileExprTree( const char *bytes = Tcl_GetStringFromObj(objPtr, &numBytes); - index = TclRegisterLiteral(envPtr, bytes, numBytes, 0); - tableValue = TclFetchLiteral(envPtr, index); + idx = TclRegisterLiteral(envPtr, bytes, numBytes, 0); + tableValue = TclFetchLiteral(envPtr, idx); if ((tableValue->typePtr == NULL) && (objPtr->typePtr != NULL)) { /* @@ -2532,9 +2580,9 @@ CompileExprTree( objPtr->typePtr = NULL; } } else { - index = TclAddLiteralObj(envPtr, objPtr, NULL); + idx = TclAddLiteralObj(envPtr, objPtr, NULL); } - TclEmitPush(index, envPtr); + TclEmitPush(idx, envPtr); } else { TclCompileSyntaxError(interp, envPtr); } @@ -2711,7 +2759,7 @@ TclVariadicOpCmd( int code; if (objc < 2) { - Tcl_SetObjResult(interp, Tcl_NewIntObj(occdPtr->i.identity)); + Tcl_SetObjResult(interp, Tcl_NewWideIntObj(occdPtr->i.identity)); return TCL_OK; } |
