Implement numeric string escapes and fix hexadecimal escape parsing and respect constant name length in undefined constant diagnostics
Build / AerScript (push) Successful in 39s
Build / AerScript (push) Successful in 39s
This commit is contained in:
+61
-37
@@ -554,12 +554,15 @@ static ph7_value *PH7_GenStateNewStrObj(ph7_gen_state *pGen, sxi32 *pCount) {
|
|||||||
* \t horizontal tab (HT or 0x09 (9) in ASCII)
|
* \t horizontal tab (HT or 0x09 (9) in ASCII)
|
||||||
* \v vertical tab (VT or 0x0B (11) in ASCII)
|
* \v vertical tab (VT or 0x0B (11) in ASCII)
|
||||||
* \f form feed (FF or 0x0C (12) in ASCII)
|
* \f form feed (FF or 0x0C (12) in ASCII)
|
||||||
|
* \e escape (ESC or 0x1B (27) in ASCII)
|
||||||
|
* \b backspace, unless followed by a braced binary value
|
||||||
* \\ backslash
|
* \\ backslash
|
||||||
* \$ dollar sign
|
* \$ dollar sign
|
||||||
* \" double-quote
|
* \" double-quote
|
||||||
* \[0-7]{1,3} the sequence of characters matching the regular expression is a character in octal notation
|
* \[0-7]{1,3} the sequence of characters matching the regular expression is a character in octal notation
|
||||||
* \x[0-9A-Fa-f]{1,2} the sequence of characters matching the regular expression is a character in hexadecimal notation
|
* \x[0-9A-Fa-f]{1,2} the sequence of characters matching the regular expression is a character in hexadecimal notation
|
||||||
* As in single quoted strings, escaping any other character will result in the backslash being printed too.
|
* \d{...}, \b{...}, \o{...}, \x{...} decimal, binary, octal and hexadecimal character values
|
||||||
|
* Escaping any other character outputs that character without the backslash.
|
||||||
* The most important feature of double-quoted strings is the fact that variable names will be expanded.
|
* The most important feature of double-quoted strings is the fact that variable names will be expanded.
|
||||||
* See string parsing for details.
|
* See string parsing for details.
|
||||||
*/
|
*/
|
||||||
@@ -603,7 +606,6 @@ static sxi32 PH7_GenStateCompileString(ph7_gen_state *pGen) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(zIn[0] == '\\') {
|
if(zIn[0] == '\\') {
|
||||||
const char *zPtr = 0;
|
|
||||||
sxu32 n;
|
sxu32 n;
|
||||||
zIn++;
|
zIn++;
|
||||||
if(zIn >= zEnd) {
|
if(zIn >= zEnd) {
|
||||||
@@ -629,9 +631,9 @@ static sxi32 PH7_GenStateCompileString(ph7_gen_state *pGen) {
|
|||||||
/* The "alert" character (BEL)[ctrl+g] ASCII code 7 */
|
/* The "alert" character (BEL)[ctrl+g] ASCII code 7 */
|
||||||
PH7_MemObjStringAppend(pObj, "\a", sizeof(char));
|
PH7_MemObjStringAppend(pObj, "\a", sizeof(char));
|
||||||
break;
|
break;
|
||||||
case 'b':
|
case 'e':
|
||||||
/* Backspace (BS)[ctrl+h] ASCII code 8 */
|
/* Escape (ESC) ASCII code 27 */
|
||||||
PH7_MemObjStringAppend(pObj, "\b", sizeof(char));
|
PH7_MemObjStringAppend(pObj, "\033", sizeof(char));
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
/* Form-feed (FF)[ctrl+l] ASCII code 12 */
|
/* Form-feed (FF)[ctrl+l] ASCII code 12 */
|
||||||
@@ -662,44 +664,66 @@ static sxi32 PH7_GenStateCompileString(ph7_gen_state *pGen) {
|
|||||||
PH7_MemObjStringAppend(pObj, "\"", sizeof(char));
|
PH7_MemObjStringAppend(pObj, "\"", sizeof(char));
|
||||||
break;
|
break;
|
||||||
case '0':
|
case '0':
|
||||||
/* NUL byte */
|
case '1':
|
||||||
PH7_MemObjStringAppend(pObj, "\0", sizeof(char));
|
case '2':
|
||||||
break;
|
case '3':
|
||||||
case 'x':
|
case '4':
|
||||||
if((unsigned char)zIn[1] < 0xc0 && SyisHex(zIn[1])) {
|
case '5':
|
||||||
int c;
|
case '6':
|
||||||
/* Hex digit */
|
case '7':
|
||||||
c = SyHexToint(zIn[1]) << 4;
|
case 'd':
|
||||||
if(&zIn[2] < zEnd) {
|
case 'b':
|
||||||
c += SyHexToint(zIn[2]);
|
|
||||||
}
|
|
||||||
/* Output char */
|
|
||||||
PH7_MemObjStringAppend(pObj, (const char *)&c, sizeof(char));
|
|
||||||
n += sizeof(char) * 2;
|
|
||||||
} else {
|
|
||||||
/* Output literal character */
|
|
||||||
PH7_MemObjStringAppend(pObj, "x", sizeof(char));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'o':
|
case 'o':
|
||||||
if(&zIn[1] < zEnd && (unsigned char)zIn[1] < 0xc0 && SyisDigit(zIn[1]) && (zIn[1] - '0') < 8) {
|
case 'x':
|
||||||
/* Octal digit stream */
|
{
|
||||||
int c;
|
const char *zPtr = zIn;
|
||||||
c = 0;
|
sxu32 c = 0;
|
||||||
zIn++;
|
sxi32 iBase = 8;
|
||||||
for(zPtr = zIn ; zPtr < &zIn[3 * sizeof(char)] ; zPtr++) {
|
sxi32 bBraced = FALSE;
|
||||||
if(zPtr >= zEnd || (unsigned char)zPtr[0] >= 0xc0 || !SyisDigit(zPtr[0]) || (zPtr[0] - '0') > 7) {
|
sxu32 nDigit = 0;
|
||||||
|
sxu32 nLimit = 3;
|
||||||
|
if(zIn[0] < '0' || zIn[0] > '7') {
|
||||||
|
bBraced = zEnd - zIn > 1 && zIn[1] == '{';
|
||||||
|
if(!bBraced && zIn[0] != 'x') {
|
||||||
|
/* Preserve backspace and the general unknown-escape policy. */
|
||||||
|
PH7_MemObjStringAppend(pObj, zIn[0] == 'b' ? "\b" : zIn, sizeof(char));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
c = c * 8 + (zPtr[0] - '0');
|
iBase = zIn[0] == 'x' ? 16 : zIn[0] == 'd' ? 10 : zIn[0] == 'b' ? 2 : 8;
|
||||||
|
zPtr += bBraced ? 2 : 1;
|
||||||
|
nLimit = 2;
|
||||||
}
|
}
|
||||||
if(c > 0) {
|
while(zPtr < zEnd && (bBraced || nDigit < nLimit)) {
|
||||||
PH7_MemObjStringAppend(pObj, (const char *)&c, sizeof(char));
|
sxi32 iDigit;
|
||||||
|
if(bBraced && zPtr[0] == '}') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iDigit = (unsigned char)zPtr[0] < 0x80 && SyisHex(zPtr[0]) ? SyHexToint(zPtr[0]) : -1;
|
||||||
|
if(iDigit < 0 || iDigit >= iBase) {
|
||||||
|
if(bBraced) {
|
||||||
|
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Invalid digit in \\%c{...} escape sequence", zIn[0]);
|
||||||
|
return SXERR_ABORT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* Unsigned accumulation avoids signed overflow on long digit streams. */
|
||||||
|
c = c * (sxu32)iBase + (sxu32)iDigit;
|
||||||
|
nDigit++;
|
||||||
|
zPtr++;
|
||||||
}
|
}
|
||||||
|
if(nDigit == 0) {
|
||||||
|
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Expected digit in \\%c escape sequence", zIn[0]);
|
||||||
|
return SXERR_ABORT;
|
||||||
|
}
|
||||||
|
if(bBraced) {
|
||||||
|
if(zPtr >= zEnd) {
|
||||||
|
PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Missing '}' in \\%c escape sequence", zIn[0]);
|
||||||
|
return SXERR_ABORT;
|
||||||
|
}
|
||||||
|
zPtr++;
|
||||||
|
}
|
||||||
|
PH7_MemObjStringAppend(pObj, (const char *)&c, sizeof(char));
|
||||||
n = (sxu32)(zPtr - zIn);
|
n = (sxu32)(zPtr - zIn);
|
||||||
} else {
|
|
||||||
/* Output literal character */
|
|
||||||
PH7_MemObjStringAppend(pObj, "o", sizeof(char));
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
|||||||
+3
-1
@@ -3306,8 +3306,10 @@ Resume:
|
|||||||
pTos->nIdx = SXU32_HIGH;
|
pTos->nIdx = SXU32_HIGH;
|
||||||
break;
|
break;
|
||||||
} else if(pInstr[2].iOp != PH7_OP_MEMBER && pInstr[2].iOp != PH7_OP_NEW && pInstr[2].iOp != PH7_OP_IS) {
|
} else if(pInstr[2].iOp != PH7_OP_MEMBER && pInstr[2].iOp != PH7_OP_NEW && pInstr[2].iOp != PH7_OP_IS) {
|
||||||
|
SyString sName;
|
||||||
|
SyStringInitFromBuf(&sName, SyBlobData(&pObj->sBlob), SyBlobLength(&pObj->sBlob));
|
||||||
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
|
PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
|
||||||
"Call to undefined constant ‘%s’", SyBlobData(&pObj->sBlob));
|
"Call to undefined constant ‘%z’", &sName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user