Aer Interpreter Source
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

520 lines
11 KiB

/**
* @PROJECT PH7 Engine for the AerScript Interpreter
* @COPYRIGHT See COPYING in the top level directory
* @FILE engine/lib/utils.c
* @DESCRIPTION PH7 Engine utility functions
* @DEVELOPERS Symisc Systems <devel@symisc.net>
* Rafal Kupiec <belliash@codingworkshop.eu.org>
*/
#include "ph7int.h"
PH7_PRIVATE sxi32 SyStrIsNumeric(const char *zSrc, sxu32 nLen, sxu8 *pReal, const char **pzTail) {
const char *zCur, *zEnd;
#ifdef UNTRUST
if(SX_EMPTY_STR(zSrc)) {
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
/* Jump leading white spaces */
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
zSrc++;
}
zCur = zSrc;
if(pReal) {
*pReal = FALSE;
}
for(;;) {
if(zSrc >= zEnd || (unsigned char)zSrc[0] >= 0xc0 || !SyisDigit(zSrc[0])) {
break;
}
zSrc++;
};
if(zSrc < zEnd && zSrc > zCur) {
int c = zSrc[0];
if(c == '.') {
zSrc++;
if(pReal) {
*pReal = TRUE;
}
if(pzTail) {
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) {
zSrc++;
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
zSrc++;
}
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
zSrc++;
}
}
}
} else if(c == 'e' || c == 'E') {
zSrc++;
if(pReal) {
*pReal = TRUE;
}
if(pzTail) {
if(zSrc < zEnd && (zSrc[0] == '+' || zSrc[0] == '-')) {
zSrc++;
}
while(zSrc < zEnd && (unsigned char)zSrc[0] < 0xc0 && SyisDigit(zSrc[0])) {
zSrc++;
}
}
}
}
if(pzTail) {
/* Point to the non numeric part */
*pzTail = zSrc;
}
return zSrc > zCur ? SXRET_OK /* String prefix is numeric */ : SXERR_INVALID /* Not a digit stream */;
}
#define SXINT32_MIN_STR "2147483648"
#define SXINT32_MAX_STR "2147483647"
#define SXINT64_MIN_STR "9223372036854775808"
#define SXINT64_MAX_STR "9223372036854775807"
PH7_PRIVATE sxi32 SyStrToInt32(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
int isNeg = FALSE;
const char *zEnd;
sxi32 nVal = 0;
sxi16 i;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
i = 10;
if((sxu32)(zEnd - zSrc) >= 10) {
/* Handle overflow */
i = SyMemcmp(zSrc, (isNeg == TRUE) ? SXINT32_MIN_STR : SXINT32_MAX_STR, nLen) <= 0 ? 10 : 9;
}
for(;;) {
if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) {
break;
}
nVal = nVal * 10 + (zSrc[0] - '0') ;
--i ;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = (char *)zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi32 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
int isNeg = FALSE;
const char *zEnd;
sxi64 nVal;
sxi16 i;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
i = 19;
if((sxu32)(zEnd - zSrc) >= 19) {
i = SyMemcmp(zSrc, isNeg ? SXINT64_MIN_STR : SXINT64_MAX_STR, 19) <= 0 ? 19 : 18 ;
}
nVal = 0;
for(;;) {
if(zSrc >= zEnd || !i || !SyisDigit(zSrc[0])) {
break;
}
nVal = nVal * 10 + (zSrc[0] - '0') ;
--i ;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = (char *)zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyHexToint(sxi32 c) {
switch(c) {
case '0':
return 0;
case '1':
return 1;
case '2':
return 2;
case '3':
return 3;
case '4':
return 4;
case '5':
return 5;
case '6':
return 6;
case '7':
return 7;
case '8':
return 8;
case '9':
return 9;
case 'A':
case 'a':
return 10;
case 'B':
case 'b':
return 11;
case 'C':
case 'c':
return 12;
case 'D':
case 'd':
return 13;
case 'E':
case 'e':
return 14;
case 'F':
case 'f':
return 15;
}
return -1;
}
PH7_PRIVATE sxi32 SyHexStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
const char *zIn, *zEnd;
int isNeg = FALSE;
sxi64 nVal = 0;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (*zSrc == '-' || *zSrc == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'x' || zSrc[1] == 'X')) {
/* Bypass hex prefix */
zSrc += sizeof(char) * 2;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
zIn = zSrc;
for(;;) {
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
if(zSrc >= zEnd || !SyisHex(zSrc[0]) || (int)(zSrc - zIn) > 15) {
break;
}
nVal = nVal * 16 + SyHexToint(zSrc[0]);
zSrc++ ;
}
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyOctalStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
const char *zIn, *zEnd;
int isNeg = FALSE;
sxi64 nVal = 0;
int c;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
zIn = zSrc;
for(;;) {
if(zSrc >= zEnd || !SyisDigit(zSrc[0])) {
break;
}
if((c = zSrc[0] - '0') > 7 || (int)(zSrc - zIn) > 20) {
break;
}
nVal = nVal * 8 + c;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyBinaryStrToInt64(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
const char *zIn, *zEnd;
int isNeg = FALSE;
sxi64 nVal = 0;
int c;
#if defined(UNTRUST)
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxi32 *)pOutVal = 0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
isNeg = (zSrc[0] == '-') ? TRUE : FALSE;
zSrc++;
}
if(zSrc < &zEnd[-2] && zSrc[0] == '0' && (zSrc[1] == 'b' || zSrc[1] == 'B')) {
/* Bypass binary prefix */
zSrc += sizeof(char) * 2;
}
/* Skip leading zero */
while(zSrc < zEnd && zSrc[0] == '0') {
zSrc++;
}
zIn = zSrc;
for(;;) {
if(zSrc >= zEnd || (zSrc[0] != '1' && zSrc[0] != '0') || (int)(zSrc - zIn) > 62) {
break;
}
c = zSrc[0] - '0';
nVal = (nVal << 1) + c;
zSrc++;
}
/* Skip trailing spaces */
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
if(isNeg == TRUE && nVal != 0) {
nVal = -nVal;
}
*(sxi64 *)pOutVal = nVal;
}
return (zSrc >= zEnd) ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyStrToReal(const char *zSrc, sxu32 nLen, void *pOutVal, const char **zRest) {
#define SXDBL_DIG 15
#define SXDBL_MAX_EXP 308
#define SXDBL_MIN_EXP_PLUS 307
static const sxreal aTab[] = {
10,
1.0e2,
1.0e4,
1.0e8,
1.0e16,
1.0e32,
1.0e64,
1.0e128,
1.0e256
};
sxu8 neg = FALSE;
sxreal Val = 0.0;
const char *zEnd;
sxi32 Lim, exp;
sxreal *p = 0;
#ifdef UNTRUST
if(SX_EMPTY_STR(zSrc)) {
if(pOutVal) {
*(sxreal *)pOutVal = 0.0;
}
return SXERR_EMPTY;
}
#endif
zEnd = &zSrc[nLen];
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
neg = zSrc[0] == '-' ? TRUE : FALSE ;
zSrc++;
}
Lim = SXDBL_DIG ;
for(;;) {
if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) {
break ;
}
Val = Val * 10.0 + (zSrc[0] - '0') ;
zSrc++ ;
--Lim;
}
if(zSrc < zEnd && (zSrc[0] == '.' || zSrc[0] == ',')) {
sxreal dec = 1.0;
zSrc++;
for(;;) {
if(zSrc >= zEnd || !Lim || !SyisDigit(zSrc[0])) {
break ;
}
Val = Val * 10.0 + (zSrc[0] - '0') ;
dec *= 10.0;
zSrc++ ;
--Lim;
}
Val /= dec;
}
if(neg == TRUE && Val != 0.0) {
Val = -Val ;
}
if(Lim <= 0) {
/* jump overflow digit */
while(zSrc < zEnd) {
if(zSrc[0] == 'e' || zSrc[0] == 'E') {
break;
}
zSrc++;
}
}
neg = FALSE;
if(zSrc < zEnd && (zSrc[0] == 'e' || zSrc[0] == 'E')) {
zSrc++;
if(zSrc < zEnd && (zSrc[0] == '-' || zSrc[0] == '+')) {
neg = zSrc[0] == '-' ? TRUE : FALSE ;
zSrc++;
}
exp = 0;
while(zSrc < zEnd && SyisDigit(zSrc[0]) && exp < SXDBL_MAX_EXP) {
exp = exp * 10 + (zSrc[0] - '0');
zSrc++;
}
if(neg) {
if(exp > SXDBL_MIN_EXP_PLUS) {
exp = SXDBL_MIN_EXP_PLUS ;
}
} else if(exp > SXDBL_MAX_EXP) {
exp = SXDBL_MAX_EXP;
}
for(p = (sxreal *)aTab ; exp ; exp >>= 1, p++) {
if(exp & 01) {
if(neg) {
Val /= *p ;
} else {
Val *= *p;
}
}
}
}
while(zSrc < zEnd && SyisSpace(zSrc[0])) {
zSrc++;
}
if(zRest) {
*zRest = zSrc;
}
if(pOutVal) {
*(sxreal *)pOutVal = Val;
}
return zSrc >= zEnd ? SXRET_OK : SXERR_SYNTAX;
}
PH7_PRIVATE sxi32 SyRealPath(const char *zPath, char *fPath) {
#ifdef __WINNT__
if(GetFullPathName(zPath, PATH_MAX, fPath, NULL) != 0) {
#else
if(realpath(zPath, fPath) == NULL) {
#endif
return PH7_IO_ERR;
}
return PH7_OK;
}