diff --git a/engine/api.c b/engine/api.c index 346c202..d41674b 100644 --- a/engine/api.c +++ b/engine/api.c @@ -456,13 +456,6 @@ const char *ph7_lib_version(void) { const char *ph7_lib_signature(void) { return PH7_SIG; } -/* - * [CAPIREF: ph7_lib_ident()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -const char *ph7_lib_ident(void) { - return PH7_IDENT; -} /* * [CAPIREF: ph7_lib_copyright()] * Please refer to the official documentation for function purpose and expected parameters. @@ -652,21 +645,16 @@ int ph7_vm_init( * This API does not actually evaluate the PHP code. It merely compile and prepares the PHP script * for evaluation. */ -static sxi32 ProcessScript( +static sxi32 ProcessSourceFile( ph7 *pEngine, /* Running PH7 engine */ ph7_vm **ppVm, /* OUT: A pointer to the virtual machine */ SyString *pScript, /* Raw PHP script to compile */ - sxi32 iFlags, /* Compile-time flags */ const char *zFilePath /* File path if script come from a file. NULL otherwise */ ) { ph7_vm *pVm = *ppVm; int iFileDir, rc; char *pFileDir, *fFilePath[PATH_MAX + 1]; char *pFilePath[PATH_MAX + 1]; - if(iFlags < 0) { - /* Default compile-time flags */ - iFlags = 0; - } /* Install local import path which is the current directory */ ph7_vm_config(pVm, PH7_VM_CONFIG_IMPORT_PATH, "./"); if(zFilePath && SyRealPath(zFilePath, fFilePath) == PH7_OK) { @@ -680,7 +668,7 @@ static sxi32 ProcessScript( PH7_VmPushFilePath(pVm, pFilePath, -1, TRUE, 0); } /* Compile the script */ - PH7_CompileScript(pVm, &(*pScript), iFlags); + PH7_CompileAerScript(pVm, &(*pScript), PH7_AERSCRIPT_CODE); if(pVm->sCodeGen.nErr > 0 || pVm == 0) { sxu32 nErr = pVm->sCodeGen.nErr; /* Compilation error or null ppVm pointer,release this VM */ @@ -720,7 +708,7 @@ Release: * [CAPIREF: ph7_compile()] * Please refer to the official documentation for function purpose and expected parameters. */ -int ph7_compile(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm) { +int ph7_compile_code(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm) { SyString sScript; int rc; if(PH7_ENGINE_MISUSE(pEngine) || zSource == 0) { @@ -740,39 +728,7 @@ int ph7_compile(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm) { } #endif /* Compile the script */ - rc = ProcessScript(&(*pEngine), ppOutVm, &sScript, 0, 0); -#if defined(PH7_ENABLE_THREADS) - /* Leave engine mutex */ - SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ -#endif - /* Compilation result */ - return rc; -} -/* - * [CAPIREF: ph7_compile_v2()] - * Please refer to the official documentation for function purpose and expected parameters. - */ -int ph7_compile_v2(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm, int iFlags) { - SyString sScript; - int rc; - if(PH7_ENGINE_MISUSE(pEngine) || zSource == 0) { - return PH7_CORRUPT; - } - if(nLen < 0) { - /* Compute input length automatically */ - nLen = (int)SyStrlen(zSource); - } - SyStringInitFromBuf(&sScript, zSource, nLen); -#if defined(PH7_ENABLE_THREADS) - /* Acquire engine mutex */ - SyMutexEnter(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ - if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE && - PH7_THRD_ENGINE_RELEASE(pEngine)) { - return PH7_ABORT; /* Another thread have released this instance */ - } -#endif - /* Compile the script */ - rc = ProcessScript(&(*pEngine), ppOutVm, &sScript, iFlags, 0); + rc = ProcessSourceFile(&(*pEngine), ppOutVm, &sScript, 0); #if defined(PH7_ENABLE_THREADS) /* Leave engine mutex */ SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ @@ -784,7 +740,7 @@ int ph7_compile_v2(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm * [CAPIREF: ph7_compile_file()] * Please refer to the official documentation for function purpose and expected parameters. */ -int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm, int iFlags) { +int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm) { const ph7_vfs *pVfs; int rc; rc = PH7_OK; /* cc warning */ @@ -819,7 +775,7 @@ int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm, int } else { /* Compile the file */ SyStringInitFromBuf(&sScript, pMapView, nSize); - rc = ProcessScript(&(*pEngine), ppOutVm, &sScript, iFlags, zFilePath); + rc = ProcessSourceFile(&(*pEngine), ppOutVm, &sScript, zFilePath); /* Release the memory view of the whole file */ if(pVfs->xUnmap) { pVfs->xUnmap(pMapView, nSize); diff --git a/engine/compiler.c b/engine/compiler.c index cf63200..acddca0 100644 --- a/engine/compiler.c +++ b/engine/compiler.c @@ -11,78 +11,14 @@ * http://ph7.symisc.net/ */ /* $SymiscID: compile.c v6.0 Win7 2012-08-18 05:11 stable $ */ -#include "ph7int.h" -/* - * This file implement a thread-safe and full-reentrant compiler for the PH7 engine. - * That is, routines defined in this file takes a stream of tokens and output - * PH7 bytecode instructions. - */ -/* Forward declaration */ -typedef struct LangConstruct LangConstruct; -typedef struct JumpFixup JumpFixup; -/* Block [i.e: set of statements] control flags */ -#define GEN_BLOCK_LOOP 0x001 /* Loop block [i.e: for,while,...] */ -#define GEN_BLOCK_PROTECTED 0x002 /* Protected block */ -#define GEN_BLOCK_COND 0x004 /* Conditional block [i.e: if(condition){} ]*/ -#define GEN_BLOCK_FUNC 0x008 /* Function body */ -#define GEN_BLOCK_GLOBAL 0x010 /* Global block (always set)*/ -#define GEN_BLOC_NESTED_FUNC 0x020 /* Nested function body */ -#define GEN_BLOCK_EXPR 0x040 /* Expression */ -#define GEN_BLOCK_STD 0x080 /* Standard block */ -#define GEN_BLOCK_EXCEPTION 0x100 /* Exception block [i.e: try{ } }*/ -#define GEN_BLOCK_SWITCH 0x200 /* Switch statement */ -/* - * Compilation of some PHP constructs such as if, for, while, the logical or - * (||) and logical and (&&) operators in expressions requires the - * generation of forward jumps. - * Since the destination PC target of these jumps isn't known when the jumps - * are emitted, we record each forward jump in an instance of the following - * structure. Those jumps are fixed later when the jump destination is resolved. - */ -struct JumpFixup { - sxi32 nJumpType; /* Jump type. Either TRUE jump, FALSE jump or Unconditional jump */ - sxu32 nInstrIdx; /* Instruction index to fix later when the jump destination is resolved. */ -}; -/* - * Each language construct is represented by an instance - * of the following structure. - */ -struct LangConstruct { - sxu32 nID; /* Language construct ID [i.e: PH7_TKWRD_WHILE,PH7_TKWRD_FOR,PH7_TKWRD_IF...] */ - ProcLangConstruct xConstruct; /* C function implementing the language construct */ -}; -/* Compilation flags */ -#define PH7_COMPILE_SINGLE_STMT 0x001 /* Compile a single statement */ -/* Token stream synchronization macros */ -#define SWAP_TOKEN_STREAM(GEN,START,END)\ - pTmp = GEN->pEnd;\ - pGen->pIn = START;\ - pGen->pEnd = END -#define UPDATE_TOKEN_STREAM(GEN)\ - if( GEN->pIn < pTmp ){\ - GEN->pIn++;\ - }\ - GEN->pEnd = pTmp -#define SWAP_DELIMITER(GEN,START,END)\ - pTmpIn = GEN->pIn;\ - pTmpEnd = GEN->pEnd;\ - GEN->pIn = START;\ - GEN->pEnd = END -#define RE_SWAP_DELIMITER(GEN)\ - GEN->pIn = pTmpIn;\ - GEN->pEnd = pTmpEnd -/* Flags related to expression compilation */ -#define EXPR_FLAG_LOAD_IDX_STORE 0x001 /* Set the iP2 flag when dealing with the LOAD_IDX instruction */ -#define EXPR_FLAG_RDONLY_LOAD 0x002 /* Read-only load, refer to the 'PH7_OP_LOAD' VM instruction for more information */ -#define EXPR_FLAG_COMMA_STATEMENT 0x004 /* Treat comma expression as a single statement (used by class attributes) */ -/* Forward declaration */ -static sxi32 PH7_CompileExpr(ph7_gen_state *pGen, sxi32 iFlags, sxi32(*xTreeValidator)(ph7_gen_state *, ph7_expr_node *)); +#include "compiler.h" + /* * Fetch a block that correspond to the given criteria from the stack of * compiled blocks. * Return a pointer to that block on success. NULL otherwise. */ -static GenBlock *GenStateFetchBlock(GenBlock *pCurrent, sxi32 iBlockType, sxi32 iCount) { +static GenBlock *PH7_GenStateFetchBlock(GenBlock *pCurrent, sxi32 iBlockType, sxi32 iCount) { GenBlock *pBlock = pCurrent; for(;;) { if(pBlock->iFlags & iBlockType) { @@ -105,7 +41,7 @@ static GenBlock *GenStateFetchBlock(GenBlock *pCurrent, sxi32 iBlockType, sxi32 /* * Initialize a freshly allocated block instance. */ -static void GenStateInitBlock( +static void PH7_GenStateInitBlock( ph7_gen_state *pGen, /* Code generator state */ GenBlock *pBlock, /* Target block */ sxi32 iType, /* Block type [i.e: loop, conditional, function body, etc.]*/ @@ -127,7 +63,7 @@ static void GenStateInitBlock( * on success.Otherwise generate a compile-time error and abort * processing on failure. */ -static sxi32 GenStateEnterBlock( +static sxi32 PH7_GenStateEnterBlock( ph7_gen_state *pGen, /* Code generator state */ sxi32 iType, /* Block type [i.e: loop, conditional, function body, etc.]*/ sxu32 nFirstInstr, /* First instruction to compile */ @@ -147,7 +83,7 @@ static sxi32 GenStateEnterBlock( } /* Zero the structure */ SyZero(pBlock, sizeof(GenBlock)); - GenStateInitBlock(&(*pGen), pBlock, iType, nFirstInstr, pUserData); + PH7_GenStateInitBlock(&(*pGen), pBlock, iType, nFirstInstr, pUserData); /* Link to the parent block */ pBlock->pParent = pGen->pCurrent; /* Mark as the current block */ @@ -161,23 +97,23 @@ static sxi32 GenStateEnterBlock( /* * Release block fields without freeing the whole instance. */ -static void GenStateReleaseBlock(GenBlock *pBlock) { +static void PH7_GenStateReleaseBlock(GenBlock *pBlock) { SySetRelease(&pBlock->aPostContFix); SySetRelease(&pBlock->aJumpFix); } /* * Release a block. */ -static void GenStateFreeBlock(GenBlock *pBlock) { +static void PH7_GenStateFreeBlock(GenBlock *pBlock) { ph7_gen_state *pGen = pBlock->pGen; - GenStateReleaseBlock(&(*pBlock)); + PH7_GenStateReleaseBlock(&(*pBlock)); /* Free the instance */ SyMemBackendPoolFree(&pGen->pVm->sAllocator, pBlock); } /* * POP and release a block from the stack of compiled blocks. */ -static sxi32 GenStateLeaveBlock(ph7_gen_state *pGen, GenBlock **ppBlock) { +static sxi32 PH7_GenStateLeaveBlock(ph7_gen_state *pGen, GenBlock **ppBlock) { GenBlock *pBlock = pGen->pCurrent; if(pBlock == 0) { /* No more block to pop */ @@ -190,21 +126,21 @@ static sxi32 GenStateLeaveBlock(ph7_gen_state *pGen, GenBlock **ppBlock) { *ppBlock = pBlock; } else { /* Safely release the block */ - GenStateFreeBlock(&(*pBlock)); + PH7_GenStateFreeBlock(&(*pBlock)); } return SXRET_OK; } /* * Emit a forward jump. * Notes on forward jumps - * Compilation of some PHP constructs such as if,for,while and the logical or + * Compilation of some Aer constructs such as if,for,while and the logical or * (||) and logical and (&&) operators in expressions requires the * generation of forward jumps. * Since the destination PC target of these jumps isn't known when the jumps * are emitted, we record each forward jump in an instance of the following * structure. Those jumps are fixed later when the jump destination is resolved. */ -static sxi32 GenStateNewJumpFixup(GenBlock *pBlock, sxi32 nJumpType, sxu32 nInstrIdx) { +static sxi32 PH7_GenStateNewJumpFixup(GenBlock *pBlock, sxi32 nJumpType, sxu32 nInstrIdx) { JumpFixup sJumpFix; sxi32 rc; /* Init the JumpFixup structure */ @@ -218,14 +154,14 @@ static sxi32 GenStateNewJumpFixup(GenBlock *pBlock, sxi32 nJumpType, sxu32 nInst * Fix a forward jump now the jump destination is resolved. * Return the total number of fixed jumps. * Notes on forward jumps: - * Compilation of some PHP constructs such as if,for,while and the logical or + * Compilation of some Aer constructs such as if,for,while and the logical or * (||) and logical and (&&) operators in expressions requires the * generation of forward jumps. * Since the destination PC target of these jumps isn't known when the jumps * are emitted, we record each forward jump in an instance of the following * structure.Those jumps are fixed later when the jump destination is resolved. */ -static sxu32 GenStateFixJumps(GenBlock *pBlock, sxi32 nJumpType, sxu32 nJumpDest) { +static sxu32 PH7_GenStateFixJumps(GenBlock *pBlock, sxi32 nJumpType, sxu32 nJumpDest) { JumpFixup *aFix; VmInstr *pInstr; sxu32 nFixed; @@ -257,7 +193,7 @@ static sxu32 GenStateFixJumps(GenBlock *pBlock, sxi32 nJumpType, sxu32 nJumpDest /* * Check if a given token value is installed in the literal table. */ -static sxi32 GenStateFindLiteral(ph7_gen_state *pGen, const SyString *pValue, sxu32 *pIdx) { +static sxi32 PH7_GenStateFindLiteral(ph7_gen_state *pGen, const SyString *pValue, sxu32 *pIdx) { SyHashEntry *pEntry; pEntry = SyHashGet(&pGen->hLiteral, (const void *)pValue->zString, pValue->nByte); if(pEntry == 0) { @@ -270,7 +206,7 @@ static sxi32 GenStateFindLiteral(ph7_gen_state *pGen, const SyString *pValue, sx * Install a given constant index in the literal table. * In order to be installed, the ph7_value must be of type string. */ -static sxi32 GenStateInstallLiteral(ph7_gen_state *pGen, ph7_value *pObj, sxu32 nIdx) { +static sxi32 PH7_GenStateInstallLiteral(ph7_gen_state *pGen, ph7_value *pObj, sxu32 nIdx) { if(SyBlobLength(&pObj->sBlob) > 0) { SyHashInsert(&pGen->hLiteral, SyBlobData(&pObj->sBlob), SyBlobLength(&pObj->sBlob), SX_INT_TO_PTR(nIdx)); } @@ -280,7 +216,7 @@ static sxi32 GenStateInstallLiteral(ph7_gen_state *pGen, ph7_value *pObj, sxu32 * Reserve a room for a numeric constant [i.e: 64-bit integer or real number] * in the constant table. */ -static ph7_value *GenStateInstallNumLiteral(ph7_gen_state *pGen, sxu32 *pIdx) { +static ph7_value *PH7_GenStateInstallNumLiteral(ph7_gen_state *pGen, sxu32 *pIdx) { ph7_value *pObj; sxu32 nIdx = 0; /* cc warning */ /* Reserve a new constant */ @@ -290,20 +226,11 @@ static ph7_value *GenStateInstallNumLiteral(ph7_gen_state *pGen, sxu32 *pIdx) { return 0; } *pIdx = nIdx; - /* TODO(chems): Create a numeric table (64bit int keys) same as - * the constant string iterals table [optimization purposes]. - */ return pObj; } -/* - * Implementation of the PHP language constructs. - */ -/* Forward declaration */ -static sxi32 GenStateCompileChunk(ph7_gen_state *pGen, sxi32 iFlags); /* * Compile a numeric [i.e: integer or real] literal. * Notes on the integer type. - * According to the PHP language reference manual * Integers can be specified in decimal (base 10), hexadecimal (base 16), octal (base 8) * or binary (base 2) notation, optionally preceded by a sign (- or +). * To use octal notation, precede the number with a 0 (zero). To use hexadecimal @@ -323,7 +250,7 @@ static sxi32 PH7_CompileNumLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag) { ph7_value *pObj; sxi64 iValue; iValue = PH7_TokenValueToInt64(&pToken->sData); - pObj = GenStateInstallNumLiteral(&(*pGen), &nIdx); + pObj = PH7_GenStateInstallNumLiteral(&(*pGen), &nIdx); if(pObj == 0) { SXUNUSED(iCompileFlag); /* cc warning */ return SXERR_ABORT; @@ -348,8 +275,6 @@ static sxi32 PH7_CompileNumLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag) { } /* * Compile a single quoted string. - * According to the PHP language reference manual: - * * The simplest way to specify a string is to enclose it in single quotes (the character ' ). * To specify a literal single quote, escape it with a backslash (\). To specify a literal * backslash, double it (\\). All other instances of backslash will be treated as a literal @@ -366,7 +291,7 @@ PH7_PRIVATE sxi32 PH7_CompileSimpleString(ph7_gen_state *pGen, sxi32 iCompileFla /* Delimit the string */ zIn = pStr->zString; zEnd = &zIn[pStr->nByte]; - if(SXRET_OK == GenStateFindLiteral(&(*pGen), pStr, &nIdx)) { + if(SXRET_OK == PH7_GenStateFindLiteral(&(*pGen), pStr, &nIdx)) { /* Already processed,emit the load constant instruction * and return. */ @@ -417,14 +342,13 @@ PH7_PRIVATE sxi32 PH7_CompileSimpleString(ph7_gen_state *pGen, sxi32 iCompileFla PH7_VmEmitInstr(pGen->pVm, PH7_OP_LOADC, 0, nIdx, 0, 0); if(pStr->nByte < 1024) { /* Install in the literal table */ - GenStateInstallLiteral(pGen, pObj, nIdx); + PH7_GenStateInstallLiteral(pGen, pObj, nIdx); } /* Node successfully compiled */ return SXRET_OK; } /* * Process variable expression [i.e: "$var","${var}"] embedded in a double quoted string. - * According to the PHP language reference manual * When a string is specified in double quotes,variables are parsed within it. * There are two types of syntax: a simple one and a complex one. The simple syntax is the most * common and convenient. It provides a way to embed a variable, an array value, or an object @@ -444,7 +368,7 @@ PH7_PRIVATE sxi32 PH7_CompileSimpleString(ph7_gen_state *pGen, sxi32 iCompileFla * the string, and then wrap it in { and }. Since { can not be escaped, this syntax will only * be recognised when the $ immediately follows the {. Use {\$ to get a literal {$ */ -static sxi32 GenStateProcessStringExpression( +static sxi32 PH7_GenStateProcessStringExpression( ph7_gen_state *pGen, /* Code generator state */ sxu32 nLine, /* Line number */ const char *zIn, /* Raw expression */ @@ -458,7 +382,7 @@ static sxi32 GenStateProcessStringExpression( /* Preallocate some slots */ SySetAlloc(&sToken, 0x08); /* Tokenize the text */ - PH7_TokenizePHP(zIn, (sxu32)(zEnd - zIn), nLine, &sToken); + PH7_TokenizeAerScript(zIn, (sxu32)(zEnd - zIn), nLine, &sToken); /* Swap delimiter */ pTmpIn = pGen->pIn; pTmpEnd = pGen->pEnd; @@ -477,7 +401,7 @@ static sxi32 GenStateProcessStringExpression( /* * Reserve a new constant for a double quoted string. */ -static ph7_value *GenStateNewStrObj(ph7_gen_state *pGen, sxi32 *pCount) { +static ph7_value *PH7_GenStateNewStrObj(ph7_gen_state *pGen, sxi32 *pCount) { ph7_value *pConstObj; sxu32 nIdx = 0; /* Reserve a new constant */ @@ -494,9 +418,8 @@ static ph7_value *GenStateNewStrObj(ph7_gen_state *pGen, sxi32 *pCount) { } /* * Compile a double quoted string. - * According to the PHP language reference manual * Double quoted - * If the string is enclosed in double-quotes ("), PHP will interpret more escape sequences for special characters: + * If the string is enclosed in double-quotes ("), Aer will interpret more escape sequences for special characters: * Escaped characters Sequence Meaning * \n linefeed (LF or 0x0A (10) in ASCII) * \r carriage return (CR or 0x0D (13) in ASCII) @@ -512,7 +435,7 @@ static ph7_value *GenStateNewStrObj(ph7_gen_state *pGen, sxi32 *pCount) { * The most important feature of double-quoted strings is the fact that variable names will be expanded. * See string parsing for details. */ -static sxi32 GenStateCompileString(ph7_gen_state *pGen) { +static sxi32 PH7_GenStateCompileString(ph7_gen_state *pGen) { SyString *pStr = &pGen->pIn->sData; /* Raw token value */ const char *zIn, *zCur, *zEnd; ph7_value *pObj = 0; @@ -541,7 +464,7 @@ static sxi32 GenStateCompileString(ph7_gen_state *pGen) { } if(zIn > zCur) { if(pObj == 0) { - pObj = GenStateNewStrObj(&(*pGen), &iCons); + pObj = PH7_GenStateNewStrObj(&(*pGen), &iCons); if(pObj == 0) { return SXERR_ABORT; } @@ -559,7 +482,7 @@ static sxi32 GenStateCompileString(ph7_gen_state *pGen) { break; } if(pObj == 0) { - pObj = GenStateNewStrObj(&(*pGen), &iCons); + pObj = PH7_GenStateNewStrObj(&(*pGen), &iCons); if(pObj == 0) { return SXERR_ABORT; } @@ -681,7 +604,7 @@ static sxi32 GenStateCompileString(ph7_gen_state *pGen) { zIn++; } /* Process the expression */ - rc = GenStateProcessStringExpression(&(*pGen), pGen->pIn->nLine, zExpr, zIn); + rc = PH7_GenStateProcessStringExpression(&(*pGen), pGen->pIn->nLine, zExpr, zIn); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -765,7 +688,7 @@ static sxi32 GenStateCompileString(ph7_gen_state *pGen) { } } /* Process the expression */ - rc = GenStateProcessStringExpression(&(*pGen), pGen->pIn->nLine, zExpr, zIn); + rc = PH7_GenStateProcessStringExpression(&(*pGen), pGen->pIn->nLine, zExpr, zIn); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -789,7 +712,7 @@ static sxi32 GenStateCompileString(ph7_gen_state *pGen) { */ PH7_PRIVATE sxi32 PH7_CompileString(ph7_gen_state *pGen, sxi32 iCompileFlag) { sxi32 rc; - rc = GenStateCompileString(&(*pGen)); + rc = PH7_GenStateCompileString(&(*pGen)); SXUNUSED(iCompileFlag); /* cc warning */ /* Compilation result */ return rc; @@ -797,7 +720,6 @@ PH7_PRIVATE sxi32 PH7_CompileString(ph7_gen_state *pGen, sxi32 iCompileFlag) { /* * Compile an array entry whether it is a key or a value. * Notes on array entries. - * According to the PHP language reference manual * An array can be created by the array() language construct. * It takes as parameters any number of comma-separated key => value pairs. * array( key => value @@ -806,14 +728,14 @@ PH7_PRIVATE sxi32 PH7_CompileString(ph7_gen_state *pGen, sxi32 iCompileFlag) { * A key may be either an integer or a string. If a key is the standard representation * of an integer, it will be interpreted as such (i.e. "8" will be interpreted as 8, while * "08" will be interpreted as "08"). Floats in key are truncated to integer. - * The indexed and associative array types are the same type in PHP, which can both + * The indexed and associative array types are the same type in Aer, which can both * contain integer and string indices. - * A value can be any PHP type. + * A value can be any Aer type. * If a key is not specified for a value, the maximum of the integer indices is taken * and the new key will be that value plus 1. If a key that already has an assigned value * is specified, that value will be overwritten. */ -static sxi32 GenStateCompileArrayEntry( +static sxi32 PH7_GenStateCompileArrayEntry( ph7_gen_state *pGen, /* Code generator state */ SyToken *pIn, /* Token stream */ SyToken *pEnd, /* End of the token stream */ @@ -838,7 +760,7 @@ static sxi32 GenStateCompileArrayEntry( * See the routine responsible of compiling the array language construct * for more inforation. */ -static sxi32 GenStateArrayNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot) { +static sxi32 PH7_GenStateArrayNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot) { sxi32 rc = SXRET_OK; if(pRoot->pOp) { if(pRoot->pOp->iOp != EXPR_OP_SUBSCRIPT /* $a[] */ && @@ -863,8 +785,7 @@ static sxi32 GenStateArrayNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoo } /* * Compile the 'array' language construct. - * According to the PHP language reference manual - * An array in PHP is actually an ordered map. A map is a type that associates + * An array in Aer is actually an ordered map. A map is a type that associates * values to keys. This type is optimized for several different uses; it can * be treated as an array, list (vector), hash table (an implementation of a map) * dictionary, collection, stack, queue, and probably more. As array values can be @@ -924,8 +845,8 @@ PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag) { return SXRET_OK; } /* Compile the expression holding the key */ - rc = GenStateCompileArrayEntry(&(*pGen), pKey, pCur, - EXPR_FLAG_RDONLY_LOAD/*Do not create the variable if inexistant*/, 0); + rc = PH7_GenStateCompileArrayEntry(&(*pGen), pKey, pCur, + EXPR_FLAG_RDONLY_LOAD/*Do not create the variable if non-existent*/, 0); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -944,7 +865,7 @@ PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag) { } if(pCur->nType & PH7_TK_AMPER /*'&'*/) { /* Insertion by reference, [i.e: $a = array(&$x);] */ - xValidator = GenStateArrayNodeValidator; /* Only variable are allowed */ + xValidator = PH7_GenStateArrayNodeValidator; /* Only variable are allowed */ iEmitRef = 1; pCur++; /* Jump the '&' token */ if(pCur >= pGen->pIn) { @@ -957,7 +878,7 @@ PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag) { } } /* Compile indice value */ - rc = GenStateCompileArrayEntry(&(*pGen), pCur, pGen->pIn, EXPR_FLAG_RDONLY_LOAD/*Do not create the variable if inexistant*/, xValidator); + rc = PH7_GenStateCompileArrayEntry(&(*pGen), pCur, pGen->pIn, EXPR_FLAG_RDONLY_LOAD/*Do not create the variable if non-existent*/, xValidator); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -982,7 +903,7 @@ PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag) { * See the routine responsible of compiling the list language construct * for more inforation. */ -static sxi32 GenStateListNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot) { +static sxi32 PH7_GenStateListNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot) { sxi32 rc = SXRET_OK; if(pRoot->pOp) { if(pRoot->pOp->iOp != EXPR_OP_SUBSCRIPT /* $a[] */ && pRoot->pOp->iOp != EXPR_OP_ARROW /* -> */ @@ -1006,7 +927,6 @@ static sxi32 GenStateListNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot } /* * Compile the 'list' language construct. - * According to the PHP language reference * list(): Assign variables as if they were an array. * list() is used to assign a list of variables in one operation. * Description @@ -1030,7 +950,7 @@ PH7_PRIVATE sxi32 PH7_CompileList(ph7_gen_state *pGen, sxi32 iCompileFlag) { while(SXRET_OK == PH7_GetNextExpr(pGen->pIn, pGen->pEnd, &pNext)) { if(pGen->pIn < pNext) { /* Compile the expression holding the variable */ - rc = GenStateCompileArrayEntry(&(*pGen), pGen->pIn, pNext, EXPR_FLAG_LOAD_IDX_STORE, GenStateListNodeValidator); + rc = PH7_GenStateCompileArrayEntry(&(*pGen), pGen->pIn, pNext, EXPR_FLAG_LOAD_IDX_STORE, PH7_GenStateListNodeValidator); if(rc != SXRET_OK) { /* Do not bother compiling this expression, it's broken anyway */ return SXRET_OK; @@ -1048,31 +968,24 @@ PH7_PRIVATE sxi32 PH7_CompileList(ph7_gen_state *pGen, sxi32 iCompileFlag) { /* Node successfully compiled */ return SXRET_OK; } -/* Forward declaration */ -static sxi32 GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc); /* - * Compile an anonymous function or a closure. - * According to the PHP language reference - * Anonymous functions, also known as closures, allow the creation of functions + * Compile a closure (anonymous function). + * Closures (also known as anonymous functions), allow the creation of functions * which have no specified name. They are most useful as the value of callback * parameters, but they have many other uses. Closures can also be used as * the values of variables; Assigning a closure to a variable uses the same * syntax as any other assignment, including the trailing semicolon: * Example Anonymous function variable assignment example - * - * Note that the implementation of anonymous function and closure under - * PH7 is completely different from the one used by the zend engine. + * $greet('AerScript'); */ -PH7_PRIVATE sxi32 PH7_CompileAnnonFunc(ph7_gen_state *pGen, sxi32 iCompileFlag) { - ph7_vm_func *pAnnonFunc; /* Anonymous function body */ - char zName[512]; /* Unique lambda name */ +PH7_PRIVATE sxi32 PH7_CompileClosure(ph7_gen_state *pGen, sxi32 iCompileFlag) { + ph7_vm_func *pAnonFunc; /* Anonymous function body */ + char zName[512]; /* Unique closure name */ static int iCnt = 1; /* There is no worry about thread-safety here,because only * one thread is allowed to compile the script. */ @@ -1085,7 +998,7 @@ PH7_PRIVATE sxi32 PH7_CompileAnnonFunc(ph7_gen_state *pGen, sxi32 iCompileFlag) if(pGen->pIn->nType & (PH7_TK_ID | PH7_TK_KEYWORD)) { pGen->pIn++; } - /* Reserve a constant for the lambda */ + /* Reserve a constant for the closure */ pObj = PH7_ReserveConstObj(pGen->pVm, &nIdx); if(pObj == 0) { PH7_GenCompileError(&(*pGen), E_ERROR, 1, "Fatal, PH7 engine is running out of memory"); @@ -1093,21 +1006,21 @@ PH7_PRIVATE sxi32 PH7_CompileAnnonFunc(ph7_gen_state *pGen, sxi32 iCompileFlag) return SXERR_ABORT; } /* Generate a unique name */ - nLen = SyBufferFormat(zName, sizeof(zName), "[lambda_%d]", iCnt++); + nLen = SyBufferFormat(zName, sizeof(zName), "{closure_%d}", iCnt++); /* Make sure the generated name is unique */ while(SyHashGet(&pGen->pVm->hFunction, zName, nLen) != 0 && nLen < sizeof(zName) - 2) { - nLen = SyBufferFormat(zName, sizeof(zName), "[lambda_%d]", iCnt++); + nLen = SyBufferFormat(zName, sizeof(zName), "{closure_%d}", iCnt++); } SyStringInitFromBuf(&sName, zName, nLen); PH7_MemObjInitFromString(pGen->pVm, pObj, &sName); - /* Compile the lambda body */ - rc = GenStateCompileFunc(&(*pGen), &sName, 0, TRUE, &pAnnonFunc); + /* Compile the closure body */ + rc = PH7_GenStateCompileFunc(&(*pGen), &sName, 0, TRUE, &pAnonFunc); if(rc == SXERR_ABORT) { return SXERR_ABORT; } - if(pAnnonFunc->iFlags & VM_FUNC_CLOSURE) { + if(pAnonFunc->iFlags & VM_FUNC_CLOSURE) { /* Emit the load closure instruction */ - PH7_VmEmitInstr(pGen->pVm, PH7_OP_LOAD_CLOSURE, 0, 0, pAnnonFunc, 0); + PH7_VmEmitInstr(pGen->pVm, PH7_OP_LOAD_CLOSURE, 0, 0, pAnonFunc, 0); } else { /* Emit the load constant instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_LOADC, 0, nIdx, 0, 0); @@ -1115,23 +1028,6 @@ PH7_PRIVATE sxi32 PH7_CompileAnnonFunc(ph7_gen_state *pGen, sxi32 iCompileFlag) /* Node successfully compiled */ return SXRET_OK; } -/* - * Compile a backtick quoted string. - */ -static sxi32 PH7_CompileBacktic(ph7_gen_state *pGen, sxi32 iCompileFlag) { - /* TICKET 1433-40: This construct is disabled in the current release of the PH7 engine. - * If you want this feature,please contact symisc systems via contact@symisc.net - */ - PH7_GenCompileError(&(*pGen), E_NOTICE, pGen->pIn->nLine, - "Command line invocation is disabled in the current release of the PH7(%s) engine", - ph7_lib_version() - ); - /* Load NULL */ - PH7_VmEmitInstr(pGen->pVm, PH7_OP_LOADC, 0, 0, 0, 0); - SXUNUSED(iCompileFlag); /* cc warning */ - /* Node successfully compiled */ - return SXRET_OK; -} /* * Compile a function [i.e: die(),exit(),include(),...] which is a langauge * construct. @@ -1152,7 +1048,7 @@ PH7_PRIVATE sxi32 PH7_CompileLangConstruct(ph7_gen_state *pGen, sxi32 iCompileFl } else if(rc != SXERR_EMPTY) { nArg = 1; } - if(SXRET_OK != GenStateFindLiteral(&(*pGen), pName, &nIdx)) { + if(SXRET_OK != PH7_GenStateFindLiteral(&(*pGen), pName, &nIdx)) { ph7_value *pObj; /* Emit the call instruction */ pObj = PH7_ReserveConstObj(pGen->pVm, &nIdx); @@ -1163,7 +1059,7 @@ PH7_PRIVATE sxi32 PH7_CompileLangConstruct(ph7_gen_state *pGen, sxi32 iCompileFl } PH7_MemObjInitFromString(pGen->pVm, pObj, pName); /* Install in the literal table */ - GenStateInstallLiteral(&(*pGen), pObj, nIdx); + PH7_GenStateInstallLiteral(&(*pGen), pObj, nIdx); } /* Emit the call instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_LOADC, 0, nIdx, 0, 0); @@ -1173,10 +1069,9 @@ PH7_PRIVATE sxi32 PH7_CompileLangConstruct(ph7_gen_state *pGen, sxi32 iCompileFl } /* * Compile a node holding a variable declaration. - * According to the PHP language reference - * Variables in PHP are represented by a dollar sign followed by the name of the variable. + * Variables in Aer are represented by a dollar sign followed by the name of the variable. * The variable name is case-sensitive. - * Variable names follow the same rules as other labels in PHP. A valid variable name starts + * Variable names follow the same rules as other labels in Aer. A valid variable name starts * with a letter or underscore, followed by any number of letters, numbers, or underscores. * As a regular expression, it would be expressed thus: '[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*' * Note: For our purposes here, a letter is a-z, A-Z, and the bytes from 127 through 255 (0x7f-0xff). @@ -1186,7 +1081,7 @@ PH7_PRIVATE sxi32 PH7_CompileLangConstruct(ph7_gen_state *pGen, sxi32 iCompileFl * This means, for instance, that after assigning one variable's value to another, changing one of those * variables will have no effect on the other. For more information on this kind of assignment, see * the chapter on Expressions. - * PHP also offers another way to assign values to variables: assign by reference. This means that + * Aer also offers another way to assign values to variables: assign by reference. This means that * the new variable simply references (in other words, "becomes an alias for" or "points to") the original * variable. Changes to the new variable affect the original, and vice versa. * To assign by reference, simply prepend an ampersand (&) to the beginning of the variable which @@ -1257,7 +1152,7 @@ PH7_PRIVATE sxi32 PH7_CompileVariable(ph7_gen_state *pGen, sxi32 iCompileFlag) { iP1 = 0; if(iCompileFlag & EXPR_FLAG_RDONLY_LOAD) { if((iCompileFlag & EXPR_FLAG_LOAD_IDX_STORE) == 0) { - /* Read-only load.In other words do not create the variable if inexistant */ + /* Read-only load.In other words do not create the variable if non-existent */ iP1 = 1; } } @@ -1273,7 +1168,7 @@ PH7_PRIVATE sxi32 PH7_CompileVariable(ph7_gen_state *pGen, sxi32 iCompileFlag) { /* * Load a literal. */ -static sxi32 GenStateLoadLiteral(ph7_gen_state *pGen) { +static sxi32 PH7_GenStateLoadLiteral(ph7_gen_state *pGen) { SyToken *pToken = pGen->pIn; ph7_value *pObj; SyString *pStr; @@ -1341,7 +1236,7 @@ static sxi32 GenStateLoadLiteral(ph7_gen_state *pGen) { return SXRET_OK; } /* Query literal table */ - if(SXRET_OK != GenStateFindLiteral(&(*pGen), &pToken->sData, &nIdx)) { + if(SXRET_OK != PH7_GenStateFindLiteral(&(*pGen), &pToken->sData, &nIdx)) { ph7_value *pObj; /* Unknown literal,install it in the literal table */ pObj = PH7_ReserveConstObj(pGen->pVm, &nIdx); @@ -1350,7 +1245,7 @@ static sxi32 GenStateLoadLiteral(ph7_gen_state *pGen) { return SXERR_ABORT; } PH7_MemObjInitFromString(pGen->pVm, pObj, &pToken->sData); - GenStateInstallLiteral(&(*pGen), pObj, nIdx); + PH7_GenStateInstallLiteral(&(*pGen), pObj, nIdx); } /* Emit the load constant instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_LOADC, 1, nIdx, 0, 0); @@ -1362,13 +1257,13 @@ static sxi32 GenStateLoadLiteral(ph7_gen_state *pGen) { * a working version that implement namespace,please contact * symisc systems via contact@symisc.net */ -static sxi32 GenStateResolveNamespaceLiteral(ph7_gen_state *pGen) { +static sxi32 PH7_GenStateResolveNamespaceLiteral(ph7_gen_state *pGen) { int emit = 0; sxi32 rc; while(pGen->pIn < &pGen->pEnd[-1]) { /* Emit a warning */ if(!emit) { - PH7_GenCompileError(&(*pGen), E_WARNING, pGen->pIn->nLine, + PH7_GenCompileError(&(*pGen), E_NOTICE, pGen->pIn->nLine, "Namespace support is disabled in the current release of the PH7(%s) engine", ph7_lib_version() ); @@ -1377,7 +1272,7 @@ static sxi32 GenStateResolveNamespaceLiteral(ph7_gen_state *pGen) { pGen->pIn++; /* Ignore the token */ } /* Load literal */ - rc = GenStateLoadLiteral(&(*pGen)); + rc = PH7_GenStateLoadLiteral(&(*pGen)); return rc; } /* @@ -1385,7 +1280,7 @@ static sxi32 GenStateResolveNamespaceLiteral(ph7_gen_state *pGen) { */ PH7_PRIVATE sxi32 PH7_CompileLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag) { sxi32 rc; - rc = GenStateResolveNamespaceLiteral(&(*pGen)); + rc = PH7_GenStateResolveNamespaceLiteral(&(*pGen)); if(rc != SXRET_OK) { SXUNUSED(iCompileFlag); /* cc warning */ return rc; @@ -1408,7 +1303,7 @@ static sxi32 PH7_ErrorRecover(ph7_gen_state *pGen) { * Check if the given identifier name is reserved or not. * Return TRUE if reserved.FALSE otherwise. */ -static int GenStateIsReservedConstant(SyString *pName) { +static int PH7_GenStateIsReservedConstant(SyString *pName) { if(pName->nByte == sizeof("null") - 1) { if(SyStrnicmp(pName->zString, "null", sizeof("null") - 1) == 0) { return TRUE; @@ -1425,11 +1320,10 @@ static int GenStateIsReservedConstant(SyString *pName) { } /* * Compile the 'const' statement. - * According to the PHP language reference * A constant is an identifier (name) for a simple value. As the name suggests, that value * cannot change during the execution of the script (except for magic constants, which aren't actually constants). * A constant is case-sensitive by default. By convention, constant identifiers are always uppercase. - * The name of a constant follows the same rules as any label in PHP. A valid constant name starts + * The name of a constant follows the same rules as any label in Aer. A valid constant name starts * with a letter or underscore, followed by any number of letters, numbers, or underscores. * As a regular expression it would be expressed thusly: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* * Syntax @@ -1465,7 +1359,7 @@ static sxi32 PH7_CompileConstant(ph7_gen_state *pGen) { /* Peek constant name */ pName = &pGen->pIn->sData; /* Make sure the constant name isn't reserved */ - if(GenStateIsReservedConstant(pName)) { + if(PH7_GenStateIsReservedConstant(pName)) { /* Reserved constant */ rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "const: Cannot redeclare a reserved constant '%z'", pName); if(rc == SXERR_ABORT) { @@ -1521,11 +1415,10 @@ Synchronize: } /* * Compile the 'continue' statement. - * According to the PHP language reference * continue is used within looping structures to skip the rest of the current loop iteration * and continue execution at the condition evaluation and then the beginning of the next * iteration. - * Note: Note that in PHP the switch statement is considered a looping structure for + * Note: Note that in Aer the switch statement is considered a looping structure for * the purposes of continue. * continue accepts an optional numeric argument which tells it how many levels * of enclosing loops it should skip to the end of. @@ -1552,7 +1445,7 @@ static sxi32 PH7_CompileContinue(ph7_gen_state *pGen) { pGen->pIn++; /* Jump the optional numeric argument */ } /* Point to the target loop */ - pLoop = GenStateFetchBlock(pGen->pCurrent, GEN_BLOCK_LOOP, iLevel); + pLoop = PH7_GenStateFetchBlock(pGen->pCurrent, GEN_BLOCK_LOOP, iLevel); if(pLoop == 0) { /* Illegal continue */ rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "A 'continue' statement may only be used within a loop or switch"); @@ -1563,14 +1456,14 @@ static sxi32 PH7_CompileContinue(ph7_gen_state *pGen) { } else { sxu32 nInstrIdx = 0; if(pLoop->iFlags & GEN_BLOCK_SWITCH) { - /* According to the PHP language reference manual - * Note that unlike some other languages, the continue statement applies to switch - * and acts similar to break. If you have a switch inside a loop and wish to continue - * to the next iteration of the outer loop, use continue 2. + /* + * Note that unlike some other languages, the continue statement applies to switch + * and acts similar to break. If you have a switch inside a loop and wish to continue + * to the next iteration of the outer loop, use continue 2. */ rc = PH7_VmEmitInstr(pGen->pVm, PH7_OP_JMP, 0, 0, 0, &nInstrIdx); if(rc == SXRET_OK) { - GenStateNewJumpFixup(pLoop, PH7_OP_JMP, nInstrIdx); + PH7_GenStateNewJumpFixup(pLoop, PH7_OP_JMP, nInstrIdx); } } else { /* Emit the unconditional jump to the beginning of the target loop */ @@ -1593,7 +1486,6 @@ static sxi32 PH7_CompileContinue(ph7_gen_state *pGen) { } /* * Compile the 'break' statement. - * According to the PHP language reference * break ends execution of the current for, foreach, while, do-while or switch * structure. * break accepts an optional numeric argument which tells it how many nested @@ -1619,7 +1511,7 @@ static sxi32 PH7_CompileBreak(ph7_gen_state *pGen) { pGen->pIn++; /* Jump the optional numeric argument */ } /* Extract the target loop */ - pLoop = GenStateFetchBlock(pGen->pCurrent, GEN_BLOCK_LOOP, iLevel); + pLoop = PH7_GenStateFetchBlock(pGen->pCurrent, GEN_BLOCK_LOOP, iLevel); if(pLoop == 0) { /* Illegal break */ rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "A 'break' statement may only be used within a loop or switch"); @@ -1632,7 +1524,7 @@ static sxi32 PH7_CompileBreak(ph7_gen_state *pGen) { rc = PH7_VmEmitInstr(pGen->pVm, PH7_OP_JMP, 0, 0, 0, &nInstrIdx); if(rc == SXRET_OK) { /* Fix the jump later when the jump destination is resolved */ - GenStateNewJumpFixup(pLoop, PH7_OP_JMP, nInstrIdx); + PH7_GenStateNewJumpFixup(pLoop, PH7_OP_JMP, nInstrIdx); } } if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI) == 0) { @@ -1643,16 +1535,16 @@ static sxi32 PH7_CompileBreak(ph7_gen_state *pGen) { return SXRET_OK; } /* - * Point to the next PHP chunk that will be processed shortly. + * Point to the next AerScript chunk that will be processed shortly. * Return SXRET_OK on success. Any other return value indicates * failure. */ -static sxi32 GenStateNextChunk(ph7_gen_state *pGen) { +static sxi32 PH7_GenStateNextChunk(ph7_gen_state *pGen) { SySet *pTokenSet = pGen->pTokenSet; /* Reset the token set */ SySetReset(pTokenSet); /* Tokenize input */ - PH7_TokenizePHP(SyStringData(&pGen->pRawIn->sData), SyStringLength(&pGen->pRawIn->sData), + PH7_TokenizeAerScript(SyStringData(&pGen->pRawIn->sData), SyStringLength(&pGen->pRawIn->sData), pGen->pRawIn->nLine, pTokenSet); /* Point to the fresh token stream */ pGen->pIn = (SyToken *)SySetBasePtr(pTokenSet); @@ -1662,8 +1554,8 @@ static sxi32 GenStateNextChunk(ph7_gen_state *pGen) { return SXRET_OK; } /* - * Compile a PHP block. - * A block is simply one or more PHP statements and expressions to compile + * Compile an AerScript block. + * A block is simply one or more Aer statements and expressions to compile * optionally delimited by braces {}. * Return SXRET_OK on success. Any other return value indicates failure * and this function takes care of generating the appropriate error @@ -1675,7 +1567,7 @@ static sxi32 PH7_CompileBlock( sxi32 rc; if(pGen->pIn->nType & PH7_TK_OCB /* '{' */) { sxu32 nLine = pGen->pIn->nLine; - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_STD, PH7_VmInstrLength(pGen->pVm), 0, 0); + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_STD, PH7_VmInstrLength(pGen->pVm), 0, 0); if(rc != SXRET_OK) { return SXERR_ABORT; } @@ -1683,7 +1575,7 @@ static sxi32 PH7_CompileBlock( /* Compile until we hit the closing braces '}' */ for(;;) { if(pGen->pIn >= pGen->pEnd) { - rc = GenStateNextChunk(&(*pGen)); + rc = PH7_GenStateNextChunk(&(*pGen)); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -1699,15 +1591,15 @@ static sxi32 PH7_CompileBlock( break; } /* Compile a single statement */ - rc = GenStateCompileChunk(&(*pGen), PH7_COMPILE_SINGLE_STMT); + rc = PH7_GenStateCompileChunk(&(*pGen), PH7_COMPILE_STATEMENT); if(rc == SXERR_ABORT) { return SXERR_ABORT; } } - GenStateLeaveBlock(&(*pGen), 0); + PH7_GenStateLeaveBlock(&(*pGen), 0); } else { /* Compile a single statement */ - rc = GenStateCompileChunk(&(*pGen), PH7_COMPILE_SINGLE_STMT); + rc = PH7_GenStateCompileChunk(&(*pGen), PH7_COMPILE_STATEMENT); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -1720,16 +1612,15 @@ static sxi32 PH7_CompileBlock( } /* * Compile the gentle 'while' statement. - * According to the PHP language reference - * while loops are the simplest type of loop in PHP.They behave just like their C counterparts. + * while loops are the simplest type of loop in Aer. They behave just like their C counterparts. * The basic form of a while statement is: * while (expr) * statement - * The meaning of a while statement is simple. It tells PHP to execute the nested statement(s) + * The meaning of a while statement is simple. It tells Aer to execute the nested statement(s) * repeatedly, as long as the while expression evaluates to TRUE. The value of the expression * is checked each time at the beginning of the loop, so even if this value changes during * the execution of the nested statement(s), execution will not stop until the end of the iteration - * (each time PHP runs the statements in the loop is one iteration). Sometimes, if the while + * (each time Aer runs the statements in the loop is one iteration). Sometimes, if the while * expression evaluates to FALSE from the very beginning, the nested statement(s) won't even be run once. * Like with the if statement, you can group multiple statements within the same while loop by surrounding * a group of statements with curly braces, or by using the alternate syntax: @@ -1758,7 +1649,7 @@ static sxi32 PH7_CompileWhile(ph7_gen_state *pGen) { /* Jump the left parenthesis '(' */ pGen->pIn++; /* Create the loop block */ - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP, PH7_VmInstrLength(pGen->pVm), 0, &pWhileBlock); + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP, PH7_VmInstrLength(pGen->pVm), 0, &pWhileBlock); if(rc != SXRET_OK) { return SXERR_ABORT; } @@ -1795,7 +1686,7 @@ static sxi32 PH7_CompileWhile(ph7_gen_state *pGen) { /* Emit the false jump */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_JZ, 0, 0, 0, &nFalseJump); /* Save the instruction index so we can fix it later when the jump destination is resolved */ - GenStateNewJumpFixup(pWhileBlock, PH7_OP_JZ, nFalseJump); + PH7_GenStateNewJumpFixup(pWhileBlock, PH7_OP_JZ, nFalseJump); /* Compile the loop body */ rc = PH7_CompileBlock(&(*pGen)); if(rc == SXERR_ABORT) { @@ -1804,9 +1695,9 @@ static sxi32 PH7_CompileWhile(ph7_gen_state *pGen) { /* Emit the unconditional jump to the start of the loop */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_JMP, 0, pWhileBlock->nFirstInstr, 0, 0); /* Fix all jumps now the destination is resolved */ - GenStateFixJumps(pWhileBlock, -1, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pWhileBlock, -1, PH7_VmInstrLength(pGen->pVm)); /* Release the loop block */ - GenStateLeaveBlock(pGen, 0); + PH7_GenStateLeaveBlock(pGen, 0); /* Statement successfully compiled */ return SXRET_OK; Synchronize: @@ -1820,7 +1711,6 @@ Synchronize: } /* * Compile the ugly do..while() statement. - * According to the PHP language reference * do-while loops are very similar to while loops, except the truth expression is checked * at the end of each iteration instead of in the beginning. The main difference from regular * while loops is that the first iteration of a do-while loop is guaranteed to run @@ -1829,12 +1719,10 @@ Synchronize: * of each iteration, if it evaluates to FALSE right from the beginning, the loop execution * would end immediately). * There is just one syntax for do-while loops: - * 0); - * ?> */ static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen) { SyToken *pTmp, *pEnd = 0; @@ -1845,7 +1733,7 @@ static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen) { /* Jump the 'do' keyword */ pGen->pIn++; /* Create the loop block */ - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP, PH7_VmInstrLength(pGen->pVm), 0, &pDoBlock); + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP, PH7_VmInstrLength(pGen->pVm), 0, &pDoBlock); if(rc != SXRET_OK) { return SXERR_ABORT; } @@ -1859,7 +1747,7 @@ static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen) { nLine = pGen->pIn->nLine; } if(pGen->pIn >= pGen->pEnd || pGen->pIn->nType != PH7_TK_KEYWORD || - SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_TKWRD_WHILE) { + SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_KEYWORD_WHILE) { /* Missing 'while' statement */ rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Missing 'while' statement after 'do' block"); if(rc == SXERR_ABORT) { @@ -1930,9 +1818,9 @@ static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen) { /* Emit the true jump to the beginning of the loop */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_JNZ, 0, pDoBlock->nFirstInstr, 0, 0); /* Fix all jumps now the destination is resolved */ - GenStateFixJumps(pDoBlock, -1, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pDoBlock, -1, PH7_VmInstrLength(pGen->pVm)); /* Release the loop block */ - GenStateLeaveBlock(pGen, 0); + PH7_GenStateLeaveBlock(pGen, 0); /* Statement successfully compiled */ return SXRET_OK; Synchronize: @@ -1946,8 +1834,7 @@ Synchronize: } /* * Compile the complex and powerful 'for' statement. - * According to the PHP language reference - * for loops are the most complex loops in PHP. They behave like their C counterparts. + * for loops are the most complex loops in Aer. They behave like their C counterparts. * The syntax of a for loop is: * for (expr1; expr2; expr3) * statement @@ -1960,7 +1847,7 @@ Synchronize: * Each of the expressions can be empty or contain multiple expressions separated by commas. * In expr2, all expressions separated by a comma are evaluated but the result is taken * from the last part. expr2 being empty means the loop should be run indefinitely - * (PHP implicitly considers it as TRUE, like C). This may not be as useless as you might + * (Aer implicitly considers it as TRUE, like C). This may not be as useless as you might * think, since often you'd want to end the loop using a conditional break statement instead * of using the for truth expression. */ @@ -2025,7 +1912,7 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) { /* Jump the trailing ';' */ pGen->pIn++; /* Create the loop block */ - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP, PH7_VmInstrLength(pGen->pVm), 0, &pForBlock); + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP, PH7_VmInstrLength(pGen->pVm), 0, &pForBlock); if(rc != SXRET_OK) { return SXERR_ABORT; } @@ -2040,7 +1927,7 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) { /* Emit the false jump */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_JZ, 0, 0, 0, &nFalseJump); /* Save the instruction index so we can fix it later when the jump destination is resolved */ - GenStateNewJumpFixup(pForBlock, PH7_OP_JZ, nFalseJump); + PH7_GenStateNewJumpFixup(pForBlock, PH7_OP_JZ, nFalseJump); } if((pGen->pIn->nType & PH7_TK_SEMI) == 0) { /* Syntax error */ @@ -2108,9 +1995,9 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) { /* Emit the unconditional jump to the start of the loop */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_JMP, 0, pForBlock->nFirstInstr, 0, 0); /* Fix all jumps now the destination is resolved */ - GenStateFixJumps(pForBlock, -1, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pForBlock, -1, PH7_VmInstrLength(pGen->pVm)); /* Release the loop block */ - GenStateLeaveBlock(pGen, 0); + PH7_GenStateLeaveBlock(pGen, 0); /* Statement successfully compiled */ return SXRET_OK; } @@ -2132,7 +2019,6 @@ static sxi32 GenStateForEachNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pR } /* * Compile the 'foreach' statement. - * According to the PHP language reference * The foreach construct simply gives an easy way to iterate over arrays. foreach works * only on arrays (and objects), and will issue an error when you try to use it on a variable * with a different data type or an uninitialized variable. There are two syntaxes; the second @@ -2179,7 +2065,7 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) { /* Jump the left parenthesis '(' */ pGen->pIn++; /* Create the loop block */ - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP, PH7_VmInstrLength(pGen->pVm), 0, &pForeachBlock); + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP, PH7_VmInstrLength(pGen->pVm), 0, &pForeachBlock); if(rc != SXRET_OK) { return SXERR_ABORT; } @@ -2204,7 +2090,7 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) { while(pCur < pEnd) { if(pCur->nType & PH7_TK_KEYWORD) { sxi32 nKeywrd = SX_PTR_TO_INT(pCur->pUserData); - if(nKeywrd == PH7_TKWRD_AS) { + if(nKeywrd == PH7_KEYWORD_AS) { /* Break with the first 'as' found */ break; } @@ -2312,13 +2198,13 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) { /* Emit the 'FOREACH_INIT' instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_FOREACH_INIT, 0, 0, pInfo, &nFalseJump); /* Save the instruction index so we can fix it later when the jump destination is resolved */ - GenStateNewJumpFixup(pForeachBlock, PH7_OP_FOREACH_INIT, nFalseJump); + PH7_GenStateNewJumpFixup(pForeachBlock, PH7_OP_FOREACH_INIT, nFalseJump); /* Record the first instruction to execute */ pForeachBlock->nFirstInstr = PH7_VmInstrLength(pGen->pVm); /* Emit the FOREACH_STEP instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_FOREACH_STEP, 0, 0, pInfo, &nFalseJump); /* Save the instruction index so we can fix it later when the jump destination is resolved */ - GenStateNewJumpFixup(pForeachBlock, PH7_OP_FOREACH_STEP, nFalseJump); + PH7_GenStateNewJumpFixup(pForeachBlock, PH7_OP_FOREACH_STEP, nFalseJump); /* Compile the loop body */ pGen->pIn = &pEnd[1]; pGen->pEnd = pTmp; @@ -2330,9 +2216,9 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) { /* Emit the unconditional jump to the start of the loop */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_JMP, 0, pForeachBlock->nFirstInstr, 0, 0); /* Fix all jumps now the destination is resolved */ - GenStateFixJumps(pForeachBlock, -1, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pForeachBlock, -1, PH7_VmInstrLength(pGen->pVm)); /* Release the loop block */ - GenStateLeaveBlock(pGen, 0); + PH7_GenStateLeaveBlock(pGen, 0); /* Statement successfully compiled */ return SXRET_OK; Synchronize: @@ -2346,9 +2232,8 @@ Synchronize: } /* * Compile the infamous if/elseif/else if/else statements. - * According to the PHP language reference - * The if construct is one of the most important features of many languages PHP included. - * It allows for conditional execution of code fragments. PHP features an if structure + * The if construct is one of the most important features of many languages, Aer included. + * It allows for conditional execution of code fragments. Aer features an if structure * that is similar to that of C: * if (expr) * statement @@ -2366,7 +2251,6 @@ Synchronize: * to FALSE. However, unlike else, it will execute that alternative expression only if the elseif * conditional expression evaluates to TRUE. For example, the following code would display a is bigger * than b, a equal to b or a is smaller than b: - * $b) { * echo "a is bigger than b"; * } elseif ($a == $b) { @@ -2374,7 +2258,6 @@ Synchronize: * } else { * echo "a is smaller than b"; * } - * ?> */ static sxi32 PH7_CompileIf(ph7_gen_state *pGen) { SyToken *pToken, *pTmp, *pEnd = 0; @@ -2386,7 +2269,7 @@ static sxi32 PH7_CompileIf(ph7_gen_state *pGen) { pGen->pIn++; pToken = pGen->pIn; /* Create the conditional block */ - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_COND, PH7_VmInstrLength(pGen->pVm), 0, &pCondBlock); + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_COND, PH7_VmInstrLength(pGen->pVm), 0, &pCondBlock); if(rc != SXRET_OK) { return SXERR_ABORT; } @@ -2438,7 +2321,7 @@ static sxi32 PH7_CompileIf(ph7_gen_state *pGen) { /* Emit the false jump */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_JZ, 0, 0, 0, &nJumpIdx); /* Save the instruction index so we can fix it later when the jump destination is resolved */ - GenStateNewJumpFixup(pCondBlock, PH7_OP_JZ, nJumpIdx); + PH7_GenStateNewJumpFixup(pCondBlock, PH7_OP_JZ, nJumpIdx); /* Compile the body */ rc = PH7_CompileBlock(&(*pGen)); if(rc == SXERR_ABORT) { @@ -2449,17 +2332,17 @@ static sxi32 PH7_CompileIf(ph7_gen_state *pGen) { } /* Ensure that the keyword ID is 'else if' or 'else' */ nKeyID = (sxu32)SX_PTR_TO_INT(pGen->pIn->pUserData); - if((nKeyID & (PH7_TKWRD_ELSE | PH7_TKWRD_ELIF)) == 0) { + if((nKeyID & (PH7_KEYWORD_ELSE | PH7_KEYWORD_ELIF)) == 0) { break; } /* Emit the unconditional jump */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_JMP, 0, 0, 0, &nJumpIdx); /* Save the instruction index so we can fix it later when the jump destination is resolved */ - GenStateNewJumpFixup(pCondBlock, PH7_OP_JMP, nJumpIdx); - if(nKeyID & PH7_TKWRD_ELSE) { + PH7_GenStateNewJumpFixup(pCondBlock, PH7_OP_JMP, nJumpIdx); + if(nKeyID & PH7_KEYWORD_ELSE) { pToken = &pGen->pIn[1]; if(pToken >= pGen->pEnd || (pToken->nType & PH7_TK_KEYWORD) == 0 || - SX_PTR_TO_INT(pToken->pUserData) != PH7_TKWRD_IF) { + SX_PTR_TO_INT(pToken->pUserData) != PH7_KEYWORD_IF) { break; } pGen->pIn++; /* Jump the 'else' keyword */ @@ -2468,12 +2351,12 @@ static sxi32 PH7_CompileIf(ph7_gen_state *pGen) { /* Synchronize cursors */ pToken = pGen->pIn; /* Fix the false jump */ - GenStateFixJumps(pCondBlock, PH7_OP_JZ, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pCondBlock, PH7_OP_JZ, PH7_VmInstrLength(pGen->pVm)); } /* For(;;) */ /* Fix the false jump */ - GenStateFixJumps(pCondBlock, PH7_OP_JZ, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pCondBlock, PH7_OP_JZ, PH7_VmInstrLength(pGen->pVm)); if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) && - (SX_PTR_TO_INT(pGen->pIn->pUserData) & PH7_TKWRD_ELSE)) { + (SX_PTR_TO_INT(pGen->pIn->pUserData) & PH7_KEYWORD_ELSE)) { /* Compile the else block */ pGen->pIn++; rc = PH7_CompileBlock(&(*pGen)); @@ -2483,9 +2366,9 @@ static sxi32 PH7_CompileIf(ph7_gen_state *pGen) { } nJumpIdx = PH7_VmInstrLength(pGen->pVm); /* Fix all unconditional jumps now the destination is resolved */ - GenStateFixJumps(pCondBlock, PH7_OP_JMP, nJumpIdx); + PH7_GenStateFixJumps(pCondBlock, PH7_OP_JMP, nJumpIdx); /* Release the conditional block */ - GenStateLeaveBlock(pGen, 0); + PH7_GenStateLeaveBlock(pGen, 0); /* Statement successfully compiled */ return SXRET_OK; Synchronize: @@ -2498,7 +2381,6 @@ Synchronize: } /* * Compile the return statement. - * According to the PHP language reference * If called from within a function, the return() statement immediately ends execution * of the current function, and returns its argument as the value of the function call. * return() will also end the execution of an eval() statement or script file. @@ -2509,7 +2391,7 @@ Synchronize: * from within the main script file, then script execution end. * Note that since return() is a language construct and not a function, the parentheses * surrounding its arguments are not required. It is common to leave them out, and you actually - * should do so as PHP has less work to do in this case. + * should do so as Aer has less work to do in this case. * Note: If no parameter is supplied, then the parentheses must be omitted and NULL will be returned. */ static sxi32 PH7_CompileReturn(ph7_gen_state *pGen) { @@ -2555,7 +2437,6 @@ static sxi32 PH7_CompileHalt(ph7_gen_state *pGen) { } /* * Compile the static statement. - * According to the PHP language reference * Another important feature of variable scoping is the static variable. * A static variable exists only in a local function scope, but it does not lose its value * when program execution leaves this scope. @@ -2637,7 +2518,7 @@ static sxi32 PH7_CompileStatic(ph7_gen_state *pGen) { /* Check if we have an expression to compile */ if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_EQUAL)) { SySet *pInstrContainer; - /* TICKET 1433-014: Symisc extension to the PHP programming language + /* * Static variable can take any complex expression including function * call as their initialization value. * Example: @@ -2698,7 +2579,6 @@ static sxi32 PH7_CompileVar(ph7_gen_state *pGen) { } /* * Compile a namespace statement - * According to the PHP language reference manual * What are namespaces? In the broadest definition namespaces are a way of encapsulating items. * This can be seen as an abstract concept in many places. For example, in any operating system * directories serve to group related files, and act as a namespace for the files within them. @@ -2707,14 +2587,14 @@ static sxi32 PH7_CompileVar(ph7_gen_state *pGen) { * file outside of the /home/greg directory, we must prepend the directory name to the file name using * the directory separator to get /home/greg/foo.txt. This same principle extends to namespaces in the * programming world. - * In the PHP world, namespaces are designed to solve two problems that authors of libraries and applications + * In the Aer world, namespaces are designed to solve two problems that authors of libraries and applications * encounter when creating re-usable code elements such as classes or functions: - * Name collisions between code you create, and internal PHP classes/functions/constants or third-party + * Name collisions between code you create, and internal Aer classes/functions/constants or third-party * classes/functions/constants. * Ability to alias (or shorten) Extra_Long_Names designed to alleviate the first problem, improving * readability of source code. - * PHP Namespaces provide a way in which to group related classes, interfaces, functions and constants. - * Here is an example of namespace syntax in PHP: + * Aer Namespaces provide a way in which to group related classes, interfaces, functions and constants. + * Here is an example of namespace syntax in Aer: * namespace my\name; // see "Defining Namespaces" section * class MyClass {} * function myfunction() {} @@ -2731,6 +2611,7 @@ static sxi32 PH7_CompileVar(ph7_gen_state *pGen) { */ static sxi32 PH7_CompileNamespace(ph7_gen_state *pGen) { sxu32 nLine = pGen->pIn->nLine; + SyToken *pEnd, *pTmp; sxi32 rc; pGen->pIn++; /* Jump the 'namespace' keyword */ if(pGen->pIn >= pGen->pEnd || @@ -2749,29 +2630,48 @@ static sxi32 PH7_CompileNamespace(ph7_gen_state *pGen) { while(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & (PH7_TK_NSSEP/*'\'*/ | PH7_TK_ID | PH7_TK_KEYWORD))) { pGen->pIn++; } - if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & (PH7_TK_SEMI/*';'*/ | PH7_TK_OCB/*'{'*/)) == 0) { + if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_OCB/*'{'*/) == 0) { /* Unexpected token */ rc = PH7_GenCompileError(&(*pGen), E_ERROR, nLine, - "Namespace: Unexpected token '%z',expecting ';' or '{'", &pGen->pIn->sData); + "Namespace: Unexpected token '%z',expecting '{'", &pGen->pIn->sData); if(rc == SXERR_ABORT) { return SXERR_ABORT; } } + pGen->pIn++; /* Jump the leading curly brace */ + pEnd = 0; /* cc warning */ + /* Delimit the interface body */ + PH7_DelimitNestedTokens(pGen->pIn, pGen->pEnd, PH7_TK_OCB/*'{'*/, PH7_TK_CCB/*'}'*/, &pEnd); + if(pEnd >= pGen->pEnd) { + /* Syntax error */ + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Namespace: Missing '}' after namespace definition"); + if(rc == SXERR_ABORT) { + /* Error count limit reached,abort immediately */ + return SXERR_ABORT; + } + return SXRET_OK; + } + /* Swap token stream */ + pTmp = pGen->pEnd; + pGen->pEnd = pEnd; /* Emit a warning */ - PH7_GenCompileError(&(*pGen), E_WARNING, nLine, + PH7_GenCompileError(&(*pGen), E_NOTICE, nLine, "Namespace support is disabled in the current release of the PH7(%s) engine", ph7_lib_version()); - return SXRET_OK; + rc = PH7_GenStateCompileGlobalScope(pGen); + /* Point beyond the interface body */ + pGen->pIn = &pEnd[1]; + pGen->pEnd = pTmp; + return rc; } /* - * Compile the 'use' statement - * According to the PHP language reference manual + * Compile the 'using' statement * The ability to refer to an external fully qualified name with an alias or importing * is an important feature of namespaces. This is similar to the ability of unix-based * filesystems to create symbolic links to a file or to a directory. - * PHP namespaces support three kinds of aliasing or importing: aliasing a class name + * Aer namespaces support three kinds of aliasing or importing: aliasing a class name * aliasing an interface name, and aliasing a namespace name. Note that importing * a function or constant is not supported. - * In PHP, aliasing is accomplished with the 'use' operator. + * In Aer, aliasing is accomplished with the 'use' operator. * NOTE * AS OF THIS VERSION NAMESPACE SUPPORT IS DISABLED. IF YOU NEED A WORKING VERSION THAT IMPLEMENT * NAMESPACE,PLEASE CONTACT SYMISC SYSTEMS VIA contact@symisc.net. @@ -2795,7 +2695,7 @@ static sxi32 PH7_CompileUsing(ph7_gen_state *pGen) { break; } } - if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) && PH7_TKWRD_AS == SX_PTR_TO_INT(pGen->pIn->pUserData)) { + if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) && PH7_KEYWORD_AS == SX_PTR_TO_INT(pGen->pIn->pUserData)) { pGen->pIn++; /* Jump the 'as' keyword */ /* Compile one or more aliasses */ for(;;) { @@ -2814,7 +2714,7 @@ static sxi32 PH7_CompileUsing(ph7_gen_state *pGen) { } if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI/*';'*/) == 0) { /* Unexpected token */ - rc = PH7_GenCompileError(&(*pGen), E_ERROR, nLine, "use statement: Unexpected token '%z',expecting ';'", + rc = PH7_GenCompileError(&(*pGen), E_ERROR, nLine, "using statement: Unexpected token '%z',expecting ';'", &pGen->pIn->sData); if(rc == SXERR_ABORT) { return SXERR_ABORT; @@ -2879,7 +2779,7 @@ static sxi32 PH7_CompileUsing(ph7_gen_state *pGen) { * Please refer to the official documentation for more information on the powerful extension * introduced by the PH7 engine. */ -static sxi32 GenStateProcessArgValue(ph7_gen_state *pGen, ph7_vm_func_arg *pArg, SyToken *pIn, SyToken *pEnd) { +static sxi32 PH7_GenStateProcessArgValue(ph7_gen_state *pGen, ph7_vm_func_arg *pArg, SyToken *pIn, SyToken *pEnd) { SyToken *pTmpIn, *pTmpEnd; SySet *pInstrContainer; sxi32 rc; @@ -2900,20 +2800,17 @@ static sxi32 GenStateProcessArgValue(ph7_gen_state *pGen, ph7_vm_func_arg *pArg, } /* * Collect function arguments one after one. - * According to the PHP language reference manual. * Information may be passed to functions via the argument list, which is a comma-delimited * list of expressions. - * PHP supports passing arguments by value (the default), passing by reference + * Aer supports passing arguments by value (the default), passing by reference * and default argument values. Variable-length argument lists are also supported, * see also the function references for func_num_args(), func_get_arg(), and func_get_args() * for more information. * Example #1 Passing arrays to functions - * * Making arguments be passed by reference * By default, function arguments are passed by value (so that if the value of the argument * within the function is changed, it does not get changed outside of the function). @@ -2921,7 +2818,6 @@ static sxi32 GenStateProcessArgValue(ph7_gen_state *pGen, ph7_vm_func_arg *pArg, * To have an argument to a function always passed by reference, prepend an ampersand (&) * to the argument name in the function definition: * Example #2 Passing function parameters by reference - * * * PH7 have introduced powerful extension including full type hinting,function overloading * complex argument values.Please refer to the official documentation for more information * on these extension. */ -static sxi32 GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen, SyToken *pEnd) { +static sxi32 PH7_GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen, SyToken *pEnd) { ph7_vm_func_arg sArg; /* Current processed argument */ SyToken *pCur, *pIn; /* Token stream */ SyBlob sSig; /* Function signature */ @@ -2955,15 +2850,15 @@ static sxi32 GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen, Sy if(pIn->nType & (PH7_TK_ID | PH7_TK_KEYWORD)) { if(pIn->nType & PH7_TK_KEYWORD) { sxu32 nKey = (sxu32)(SX_PTR_TO_INT(pIn->pUserData)); - if(nKey & PH7_TKWRD_ARRAY) { + if(nKey & PH7_KEYWORD_ARRAY) { sArg.nType = MEMOBJ_HASHMAP; - } else if(nKey & PH7_TKWRD_BOOL) { + } else if(nKey & PH7_KEYWORD_BOOL) { sArg.nType = MEMOBJ_BOOL; - } else if(nKey & PH7_TKWRD_INT) { + } else if(nKey & PH7_KEYWORD_INT) { sArg.nType = MEMOBJ_INT; - } else if(nKey & PH7_TKWRD_STRING) { + } else if(nKey & PH7_KEYWORD_STRING) { sArg.nType = MEMOBJ_STRING; - } else if(nKey & PH7_TKWRD_FLOAT) { + } else if(nKey & PH7_KEYWORD_FLOAT) { sArg.nType = MEMOBJ_REAL; } else { PH7_GenCompileError(&(*pGen), E_WARNING, pGen->pIn->nLine, @@ -3030,7 +2925,7 @@ static sxi32 GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen, Sy return rc; } /* Process default value */ - rc = GenStateProcessArgValue(&(*pGen), &sArg, pIn, pDefend); + rc = PH7_GenStateProcessArgValue(&(*pGen), &sArg, pIn, pDefend); if(rc != SXRET_OK) { return rc; } @@ -3098,7 +2993,7 @@ static sxi32 GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen, Sy * Return SXRET_OK on success. Any other return value indicates failure * and this routine takes care of generating the appropriate error message. */ -static sxi32 GenStateCompileFuncBody( +static sxi32 PH7_GenStateCompileFuncBody( ph7_gen_state *pGen, /* Code generator state */ ph7_vm_func *pFunc /* Function state */ ) { @@ -3106,7 +3001,7 @@ static sxi32 GenStateCompileFuncBody( GenBlock *pBlock; sxi32 rc; /* Attach the new function */ - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_PROTECTED | GEN_BLOCK_FUNC, PH7_VmInstrLength(pGen->pVm), pFunc, &pBlock); + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_PROTECTED | GEN_BLOCK_FUNC, PH7_VmInstrLength(pGen->pVm), pFunc, &pBlock); if(rc != SXRET_OK) { PH7_GenCompileError(&(*pGen), E_ERROR, 1, "PH7 engine is running out-of-memory"); /* Don't worry about freeing memory, everything will be released shortly */ @@ -3118,13 +3013,13 @@ static sxi32 GenStateCompileFuncBody( /* Compile the body */ PH7_CompileBlock(&(*pGen)); /* Fix exception jumps now the destination is resolved */ - GenStateFixJumps(pGen->pCurrent, PH7_OP_THROW, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pGen->pCurrent, PH7_OP_THROW, PH7_VmInstrLength(pGen->pVm)); /* Emit the final return if not yet done */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_DONE, 0, 0, 0, 0); /* Restore the default container */ PH7_VmSetByteCodeContainer(pGen->pVm, pInstrContainer); /* Leave function block */ - GenStateLeaveBlock(&(*pGen), 0); + PH7_GenStateLeaveBlock(&(*pGen), 0); if(rc == SXERR_ABORT) { /* Don't worry about freeing memory, everything will be released shortly */ return SXERR_ABORT; @@ -3133,23 +3028,22 @@ static sxi32 GenStateCompileFuncBody( return SXRET_OK; } /* - * Compile a PHP function whether is a Standard or Anonymous function. - * According to the PHP language reference manual. - * Function names follow the same rules as other labels in PHP. A valid function name + * Compile an AerScript function whether is a Standard or Anonymous function. + * Function names follow the same rules as other labels in Aer. A valid function name * starts with a letter or underscore, followed by any number of letters, numbers, or * underscores. As a regular expression, it would be expressed thus: * [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*. * Functions need not be defined before they are referenced. - * All functions and classes in PHP have the global scope - they can be called outside + * All functions and classes in Aer have the global scope - they can be called outside * a function even if they were defined inside and vice versa. - * It is possible to call recursive functions in PHP. However avoid recursive function/method + * It is possible to call recursive functions in Aer. However avoid recursive function/method * calls with over 32-64 recursion levels. * * PH7 have introduced powerful extension including full type hinting, function overloading, * complex argument values and more. Please refer to the official documentation for more information * on these extension. */ -static sxi32 GenStateCompileFunc( +static sxi32 PH7_GenStateCompileFunc( ph7_gen_state *pGen, /* Code generator state */ SyString *pName, /* Function name. NULL otherwise */ sxi32 iFlags, /* Control flags */ @@ -3192,7 +3086,7 @@ static sxi32 GenStateCompileFunc( PH7_VmInitFuncState(pGen->pVm, pFunc, zName, pName->nByte, iFlags, 0); if(pGen->pIn < pEnd) { /* Collect function arguments */ - rc = GenStateCollectFuncArgs(pFunc, &(*pGen), pEnd); + rc = PH7_GenStateCollectFuncArgs(pFunc, &(*pGen), pEnd); if(rc == SXERR_ABORT) { /* Don't worry about freeing memory, everything will be released shortly */ return SXERR_ABORT; @@ -3204,7 +3098,7 @@ static sxi32 GenStateCompileFunc( ph7_vm_func_closure_env sEnv; int got_this = 0; /* TRUE if $this have been seen */ if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) - && SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_TKWRD_USING) { + && SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_KEYWORD_USING) { sxu32 nLine = pGen->pIn->nLine; /* Closure,record environment variable */ pGen->pIn++; @@ -3293,7 +3187,7 @@ static sxi32 GenStateCompileFunc( } } /* Compile the body */ - rc = GenStateCompileFuncBody(&(*pGen), pFunc); + rc = PH7_GenStateCompileFuncBody(&(*pGen), pFunc); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -3316,60 +3210,8 @@ OutOfMem: PH7_GenCompileError(&(*pGen), E_ERROR, 1, "Fatal, PH7 engine is running out-of-memory"); return SXERR_ABORT; } -/* - * Compile a standard PHP function. - * Refer to the block-comment above for more information. - */ -static sxi32 PH7_CompileFunction(ph7_gen_state *pGen) { - SyString *pName; - sxi32 iFlags; - sxu32 nLine; - sxi32 rc; - nLine = pGen->pIn->nLine; - pGen->pIn++; /* Jump the 'function' keyword */ - iFlags = 0; - if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_AMPER)) { - /* Return by reference,remember that */ - iFlags |= VM_FUNC_REF_RETURN; - /* Jump the '&' token */ - pGen->pIn++; - } - if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_ID | PH7_TK_KEYWORD)) == 0) { - /* Invalid function name */ - rc = PH7_GenCompileError(&(*pGen), E_ERROR, nLine, "Invalid function name"); - if(rc == SXERR_ABORT) { - return SXERR_ABORT; - } - /* Synchronize with the next semi-colon or braces*/ - while(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & (PH7_TK_SEMI | PH7_TK_OCB)) == 0) { - pGen->pIn++; - } - return SXRET_OK; - } - pName = &pGen->pIn->sData; - nLine = pGen->pIn->nLine; - /* Jump the function name */ - pGen->pIn++; - if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_LPAREN) == 0) { - /* Syntax error */ - rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Expected '(' after function name '%z'", pName); - if(rc == SXERR_ABORT) { - /* Error count limit reached,abort immediately */ - return SXERR_ABORT; - } - /* Synchronize with the next semi-colon or '{' */ - while(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & (PH7_TK_SEMI | PH7_TK_OCB)) == 0) { - pGen->pIn++; - } - return SXRET_OK; - } - /* Compile function body */ - rc = GenStateCompileFunc(&(*pGen), pName, iFlags, FALSE, 0); - return rc; -} /* * Extract the visibility level associated with a given keyword. - * According to the PHP language reference manual * Visibility: * The visibility of a property or method can be defined by prefixing * the declaration with the keywords public, protected or private. @@ -3378,10 +3220,10 @@ static sxi32 PH7_CompileFunction(ph7_gen_state *pGen) { * itself and by inherited and parent classes. Members declared as private * may only be accessed by the class that defines the member. */ -static sxi32 GetProtectionLevel(sxi32 nKeyword) { - if(nKeyword == PH7_TKWRD_PRIVATE) { +static sxi32 PH7_GetProtectionLevel(sxi32 nKeyword) { + if(nKeyword == PH7_KEYWORD_PRIVATE) { return PH7_CLASS_PROT_PRIVATE; - } else if(nKeyword == PH7_TKWRD_PROTECTED) { + } else if(nKeyword == PH7_KEYWORD_PROTECTED) { return PH7_CLASS_PROT_PROTECTED; } /* Assume public by default */ @@ -3389,7 +3231,6 @@ static sxi32 GetProtectionLevel(sxi32 nKeyword) { } /* * Compile a class constant. - * According to the PHP language reference manual * Class Constants * It is possible to define constant values on a per-class basis remaining * the same and unchangeable. Constants differ from normal variables in that @@ -3408,21 +3249,21 @@ static sxi32 GetProtectionLevel(sxi32 nKeyword) { * Refer to the official documentation for more information on the powerful extension * introduced by the PH7 engine to the OO subsystem. */ -static sxi32 GenStateCompileClassConstant(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass) { +static sxi32 PH7_GenStateCompileClassConstant(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass) { sxu32 nLine = pGen->pIn->nLine; SySet *pInstrContainer; ph7_class_attr *pCons; SyString *pName; sxi32 rc; /* Extract visibility level */ - iProtection = GetProtectionLevel(iProtection); + iProtection = PH7_GetProtectionLevel(iProtection); pGen->pIn++; /* Jump the 'const' keyword */ loop: /* Mark as constant */ iFlags |= PH7_CLASS_ATTR_CONSTANT; if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) { /* Invalid constant name */ - rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid constant name"); + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid constant name '%z' in class '%z'", &pGen->pIn->sData, pClass->sName); if(rc == SXERR_ABORT) { /* Error count limit reached,abort immediately */ return SXERR_ABORT; @@ -3432,7 +3273,7 @@ loop: /* Peek constant name */ pName = &pGen->pIn->sData; /* Make sure the constant name isn't reserved */ - if(GenStateIsReservedConstant(pName)) { + if(PH7_GenStateIsReservedConstant(pName)) { /* Reserved constant name */ rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Cannot redeclare a reserved constant '%z'", pName); if(rc == SXERR_ABORT) { @@ -3513,8 +3354,7 @@ Synchronize: return SXERR_CORRUPT; } /* - * compile a class attribute or Properties in the PHP jargon. - * According to the PHP language reference manual + * compile a class attribute or properties. * Properties * Class member variables are called "properties". You may also see them referred * to using other terms such as "attributes" or "fields", but for the purposes @@ -3534,18 +3374,18 @@ Synchronize: * Refer to the official documentation for more information on the powerful extension * introduced by the PH7 engine to the OO subsystem. */ -static sxi32 GenStateCompileClassAttr(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass) { +static sxi32 PH7_GenStateCompileClassAttr(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass) { sxu32 nLine = pGen->pIn->nLine; ph7_class_attr *pAttr; SyString *pName; sxi32 rc; /* Extract visibility level */ - iProtection = GetProtectionLevel(iProtection); + iProtection = PH7_GetProtectionLevel(iProtection); loop: pGen->pIn++; /* Jump the dollar sign */ if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_KEYWORD | PH7_TK_ID)) == 0) { /* Invalid attribute name */ - rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid attribute name"); + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid attribute name '%z' in class '%z'", &pGen->pIn->sData, &pClass->sName); if(rc == SXERR_ABORT) { /* Error count limit reached,abort immediately */ return SXERR_ABORT; @@ -3632,7 +3472,7 @@ Synchronize: * to the OO subsystem such as full type hinting,method * overloading and many more. */ -static sxi32 GenStateCompileClassMethod( +static sxi32 PH7_GenStateCompileClassMethod( ph7_gen_state *pGen, /* Code generator state */ sxi32 iProtection, /* Visibility level */ sxi32 iFlags, /* Configuration flags */ @@ -3646,12 +3486,12 @@ static sxi32 GenStateCompileClassMethod( SyToken *pEnd; sxi32 rc; /* Extract visibility level */ - iProtection = GetProtectionLevel(iProtection); + iProtection = PH7_GetProtectionLevel(iProtection); pGen->pIn++; /* Jump the 'function' keyword */ iFuncFlags = 0; if(pGen->pIn >= pGen->pEnd) { /* Invalid method name */ - rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid method name"); + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid method name '%z' in class '%z'", &pGen->pIn->sData, &pClass->sName); if(rc == SXERR_ABORT) { /* Error count limit reached,abort immediately */ return SXERR_ABORT; @@ -3666,7 +3506,7 @@ static sxi32 GenStateCompileClassMethod( } if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_ID)) == 0) { /* Invalid method name */ - rc = PH7_GenCompileError(&(*pGen), E_ERROR, nLine, "Invalid method name"); + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Invalid method name '%z' in class '%z'", &pGen->pIn->sData, &pClass->sName); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -3681,18 +3521,26 @@ static sxi32 GenStateCompileClassMethod( /* Virtual method */ if(iProtection == PH7_CLASS_PROT_PRIVATE) { rc = PH7_GenCompileError(pGen, E_ERROR, nLine, - "Access type for virtual method '%z::%z' cannot be 'private'", + "Virtual method '%z::%z()' cannot be declared private", &pClass->sName, pName); if(rc == SXERR_ABORT) { return SXERR_ABORT; } } + if((pClass->iFlags & PH7_CLASS_VIRTUAL) == 0) { + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, + "Class '%z' contains virtual method and must therefore be declared virtual or implement the remaining method '%z::%z()'", + &pClass->sName, &pClass->sName, pName); + if(rc == SXERR_ABORT) { + return SXERR_ABORT; + } + } /* Assemble method signature only */ doBody = FALSE; } if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_LPAREN) == 0) { /* Syntax error */ - rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Expected '(' after method name '%z'", pName); + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Expected '(' after method name '%z::%z()'", &pClass->sName, pName); if(rc == SXERR_ABORT) { /* Error count limit reached,abort immediately */ return SXERR_ABORT; @@ -3712,7 +3560,7 @@ static sxi32 GenStateCompileClassMethod( PH7_DelimitNestedTokens(pGen->pIn, pGen->pEnd, PH7_TK_LPAREN /* '(' */, PH7_TK_RPAREN /* ')' */, &pEnd); if(pEnd >= pGen->pEnd) { /* Syntax error */ - rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Missing ')' after method '%z' declaration", pName); + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Missing ')' after method '%z::%z()' declaration", &pClass->sName, pName); if(rc == SXERR_ABORT) { /* Error count limit reached,abort immediately */ return SXERR_ABORT; @@ -3721,7 +3569,7 @@ static sxi32 GenStateCompileClassMethod( } if(pGen->pIn < pEnd) { /* Collect method arguments */ - rc = GenStateCollectFuncArgs(&pMeth->sFunc, &(*pGen), pEnd); + rc = PH7_GenStateCollectFuncArgs(&pMeth->sFunc, &(*pGen), pEnd); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -3729,8 +3577,17 @@ static sxi32 GenStateCompileClassMethod( /* Point beyond method signature */ pGen->pIn = &pEnd[1]; if(doBody) { + if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_OCB /* '{'*/) == 0) { + rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, + "Non-virtual method '%z::%z()' must contain body", &pClass->sName, pName); + if(rc == SXERR_ABORT) { + /* Error count limit reached,abort immediately */ + return SXERR_ABORT; + } + return SXERR_CORRUPT; + } /* Compile method body */ - rc = GenStateCompileFuncBody(&(*pGen), &pMeth->sFunc); + rc = PH7_GenStateCompileFuncBody(&(*pGen), &pMeth->sFunc); if(rc == SXERR_ABORT) { return SXERR_ABORT; } @@ -3738,7 +3595,7 @@ static sxi32 GenStateCompileClassMethod( /* Only method signature is allowed */ if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI /* ';'*/) == 0) { rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, - "Expected ';' after method signature '%z'", pName); + "Interface method '%z::%z()' cannot contain body", &pClass->sName, pName); if(rc == SXERR_ABORT) { /* Error count limit reached,abort immediately */ return SXERR_ABORT; @@ -3762,7 +3619,6 @@ Synchronize: } /* * Compile an object interface. - * According to the PHP language reference manual * Object Interfaces: * Object interfaces allow you to create code which specifies which methods * a class must implement, without having to define how these methods are handled. @@ -3817,7 +3673,7 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) { if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD)) { SyString pBaseName; nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd == PH7_TKWRD_EXTENDS /* interface b extends a */) { + if(nKwrd == PH7_KEYWORD_EXTENDS /* interface b extends a */) { /* Extract base interface */ pGen->pIn++; for(;;) { @@ -3877,7 +3733,6 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) { pTmp = pGen->pEnd; pGen->pEnd = pEnd; /* Start the parse process - * Note (According to the PHP reference manual): * Only constants and function signatures(without body) are allowed. * Only 'public' visibility is allowed. */ @@ -3902,12 +3757,12 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) { } /* Extract the current keyword */ nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd == PH7_TKWRD_PRIVATE || nKwrd == PH7_TKWRD_PROTECTED) { + if(nKwrd == PH7_KEYWORD_PRIVATE || nKwrd == PH7_KEYWORD_PROTECTED) { /* Emit a warning and switch to public visibility */ PH7_GenCompileError(&(*pGen), E_WARNING, pGen->pIn->nLine, "interface: Access type must be public"); - nKwrd = PH7_TKWRD_PUBLIC; + nKwrd = PH7_KEYWORD_PUBLIC; } - if(nKwrd != PH7_TKWRD_PUBLIC && nKwrd != PH7_TKWRD_FUNCTION && nKwrd != PH7_TKWRD_CONST && nKwrd != PH7_TKWRD_STATIC) { + if(nKwrd != PH7_KEYWORD_PUBLIC && nKwrd != PH7_KEYWORD_FUNCTION && nKwrd != PH7_KEYWORD_CONST && nKwrd != PH7_KEYWORD_STATIC) { rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Expecting method signature or constant declaration inside interface '%z'", pName); if(rc == SXERR_ABORT) { @@ -3916,7 +3771,7 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) { } goto done; } - if(nKwrd == PH7_TKWRD_PUBLIC) { + if(nKwrd == PH7_KEYWORD_PUBLIC) { /* Advance the stream cursor */ pGen->pIn++; if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0) { @@ -3929,7 +3784,7 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) { goto done; } nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd != PH7_TKWRD_FUNCTION && nKwrd != PH7_TKWRD_CONST && nKwrd != PH7_TKWRD_STATIC) { + if(nKwrd != PH7_KEYWORD_FUNCTION && nKwrd != PH7_KEYWORD_CONST && nKwrd != PH7_KEYWORD_STATIC) { rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Expecting method signature or constant declaration inside interface '%z'", pName); if(rc == SXERR_ABORT) { @@ -3939,9 +3794,9 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) { goto done; } } - if(nKwrd == PH7_TKWRD_CONST) { + if(nKwrd == PH7_KEYWORD_CONST) { /* Parse constant */ - rc = GenStateCompileClassConstant(&(*pGen), 0, 0, pClass); + rc = PH7_GenStateCompileClassConstant(&(*pGen), 0, 0, pClass); if(rc != SXRET_OK) { if(rc == SXERR_ABORT) { return SXERR_ABORT; @@ -3950,13 +3805,13 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) { } } else { sxi32 iFlags = 0; - if(nKwrd == PH7_TKWRD_STATIC) { + if(nKwrd == PH7_KEYWORD_STATIC) { /* Static method,record that */ iFlags |= PH7_CLASS_ATTR_STATIC; /* Advance the stream cursor */ pGen->pIn++; if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0 - || SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_TKWRD_FUNCTION) { + || SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_KEYWORD_FUNCTION) { rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Expecting method signature inside interface '%z'", pName); if(rc == SXERR_ABORT) { @@ -3967,7 +3822,7 @@ static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen) { } } /* Process method signature */ - rc = GenStateCompileClassMethod(&(*pGen), 0, FALSE/* Only method signature*/, iFlags, pClass); + rc = PH7_GenStateCompileClassMethod(&(*pGen), 0, FALSE/* Only method signature*/, iFlags, pClass); if(rc != SXRET_OK) { if(rc == SXERR_ABORT) { return SXERR_ABORT; @@ -3994,19 +3849,18 @@ done: } /* * Compile a user-defined class. - * According to the PHP language reference manual * class * Basic class definitions begin with the keyword class, followed by a class * name, followed by a pair of curly braces which enclose the definitions * of the properties and methods belonging to the class. - * The class name can be any valid label which is a not a PHP reserved word. + * The class name can be any valid label which is a not a Aer reserved word. * A valid class name starts with a letter or underscore, followed by any number * of letters, numbers, or underscores. As a regular expression, it would be expressed * thus: [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*. * A class may contain its own constants, variables (called "properties"), and functions * (called "methods"). */ -static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { +static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { sxu32 nLine = pGen->pIn->nLine; ph7_class *pClass, *pBase; ph7_class_info *pClassInfo; @@ -4054,7 +3908,7 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD)) { SyString pBaseName; nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd == PH7_TKWRD_EXTENDS /* class b extends a */) { + if(nKwrd == PH7_KEYWORD_EXTENDS /* class b extends a */) { pGen->pIn++; /* Advance the stream cursor */ for(;;) { if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_ID) == 0) { @@ -4084,7 +3938,7 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } iP1 = 1; } - if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) && SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_TKWRD_IMPLEMENTS) { + if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) && SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_KEYWORD_IMPLEMENTS) { SyString pIntName; /* Interface implementation */ pGen->pIn++; /* Advance the stream cursor */ @@ -4119,7 +3973,7 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_OCB /*'{'*/) == 0) { /* Syntax error */ - rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Expected '{' after class '%z' declaration", pName); + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Expected opening braces '{' after class '%z' declaration", pName); SyMemBackendPoolFree(&pGen->pVm->sAllocator, pClass); if(rc == SXERR_ABORT) { /* Error count limit reached,abort immediately */ @@ -4133,7 +3987,7 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { PH7_DelimitNestedTokens(pGen->pIn, pGen->pEnd, PH7_TK_OCB/*'{'*/, PH7_TK_CCB/*'}'*/, &pEnd); if(pEnd >= pGen->pEnd) { /* Syntax error */ - rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Missing closing braces'}' after class '%z' definition", pName); + rc = PH7_GenCompileError(pGen, E_ERROR, nLine, "Missing closing braces '}' after class '%z' definition", pName); SyMemBackendPoolFree(&pGen->pVm->sAllocator, pClass); if(rc == SXERR_ABORT) { /* Error count limit reached,abort immediately */ @@ -4167,12 +4021,12 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { goto done; } /* Assume public visibility */ - iProtection = PH7_TKWRD_PUBLIC; + iProtection = PH7_KEYWORD_PUBLIC; iAttrflags = 0; if(pGen->pIn->nType & PH7_TK_KEYWORD) { /* Extract the current keyword */ nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd == PH7_TKWRD_PUBLIC || nKwrd == PH7_TKWRD_PRIVATE || nKwrd == PH7_TKWRD_PROTECTED) { + if(nKwrd == PH7_KEYWORD_PUBLIC || nKwrd == PH7_KEYWORD_PRIVATE || nKwrd == PH7_KEYWORD_PROTECTED) { iProtection = nKwrd; pGen->pIn++; /* Jump the visibility token */ if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & (PH7_TK_KEYWORD | PH7_TK_DOLLAR)) == 0) { @@ -4187,7 +4041,7 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } if(pGen->pIn->nType & PH7_TK_DOLLAR) { /* Attribute declaration */ - rc = GenStateCompileClassAttr(&(*pGen), iProtection, iAttrflags, pClass); + rc = PH7_GenStateCompileClassAttr(&(*pGen), iProtection, iAttrflags, pClass); if(rc != SXRET_OK) { if(rc == SXERR_ABORT) { return SXERR_ABORT; @@ -4199,9 +4053,9 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { /* Extract the keyword */ nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); } - if(nKwrd == PH7_TKWRD_CONST) { + if(nKwrd == PH7_KEYWORD_CONST) { /* Process constant declaration */ - rc = GenStateCompileClassConstant(&(*pGen), iProtection, iAttrflags, pClass); + rc = PH7_GenStateCompileClassConstant(&(*pGen), iProtection, iAttrflags, pClass); if(rc != SXRET_OK) { if(rc == SXERR_ABORT) { return SXERR_ABORT; @@ -4209,14 +4063,14 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { goto done; } } else { - if(nKwrd == PH7_TKWRD_STATIC) { + if(nKwrd == PH7_KEYWORD_STATIC) { /* Static method or attribute,record that */ iAttrflags |= PH7_CLASS_ATTR_STATIC; pGen->pIn++; /* Jump the static keyword */ if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD)) { /* Extract the keyword */ nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd == PH7_TKWRD_PUBLIC || nKwrd == PH7_TKWRD_PRIVATE || nKwrd == PH7_TKWRD_PROTECTED) { + if(nKwrd == PH7_KEYWORD_PUBLIC || nKwrd == PH7_KEYWORD_PRIVATE || nKwrd == PH7_KEYWORD_PROTECTED) { iProtection = nKwrd; pGen->pIn++; /* Jump the visibility token */ } @@ -4233,7 +4087,7 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } if(pGen->pIn->nType & PH7_TK_DOLLAR) { /* Attribute declaration */ - rc = GenStateCompileClassAttr(&(*pGen), iProtection, iAttrflags, pClass); + rc = PH7_GenStateCompileClassAttr(&(*pGen), iProtection, iAttrflags, pClass); if(rc != SXRET_OK) { if(rc == SXERR_ABORT) { return SXERR_ABORT; @@ -4244,28 +4098,26 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } /* Extract the keyword */ nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - } else if(nKwrd == PH7_TKWRD_VIRTUAL) { + } else if(nKwrd == PH7_KEYWORD_VIRTUAL) { /* Virtual method,record that */ iAttrflags |= PH7_CLASS_ATTR_VIRTUAL; - /* Mark the whole class as virtual */ - pClass->iFlags |= PH7_CLASS_VIRTUAL; /* Advance the stream cursor */ pGen->pIn++; if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD)) { nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd == PH7_TKWRD_PUBLIC || nKwrd == PH7_TKWRD_PRIVATE || nKwrd == PH7_TKWRD_PROTECTED) { + if(nKwrd == PH7_KEYWORD_PUBLIC || nKwrd == PH7_KEYWORD_PRIVATE || nKwrd == PH7_KEYWORD_PROTECTED) { iProtection = nKwrd; pGen->pIn++; /* Jump the visibility token */ } } if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) && - SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_TKWRD_STATIC) { + SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_KEYWORD_STATIC) { /* Static method */ iAttrflags |= PH7_CLASS_ATTR_STATIC; pGen->pIn++; /* Jump the static keyword */ } if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0 || - SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_TKWRD_FUNCTION) { + SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_KEYWORD_FUNCTION) { rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Unexpected token '%z',Expecting method declaration after 'virtual' keyword inside class '%z'", &pGen->pIn->sData, pName); @@ -4275,27 +4127,27 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } goto done; } - nKwrd = PH7_TKWRD_FUNCTION; - } else if(nKwrd == PH7_TKWRD_FINAL) { + nKwrd = PH7_KEYWORD_FUNCTION; + } else if(nKwrd == PH7_KEYWORD_FINAL) { /* final method ,record that */ iAttrflags |= PH7_CLASS_ATTR_FINAL; pGen->pIn++; /* Jump the final keyword */ if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD)) { /* Extract the keyword */ nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd == PH7_TKWRD_PUBLIC || nKwrd == PH7_TKWRD_PRIVATE || nKwrd == PH7_TKWRD_PROTECTED) { + if(nKwrd == PH7_KEYWORD_PUBLIC || nKwrd == PH7_KEYWORD_PRIVATE || nKwrd == PH7_KEYWORD_PROTECTED) { iProtection = nKwrd; pGen->pIn++; /* Jump the visibility token */ } } if(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_KEYWORD) && - SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_TKWRD_STATIC) { + SX_PTR_TO_INT(pGen->pIn->pUserData) == PH7_KEYWORD_STATIC) { /* Static method */ iAttrflags |= PH7_CLASS_ATTR_STATIC; pGen->pIn++; /* Jump the static keyword */ } if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0 || - SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_TKWRD_FUNCTION) { + SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_KEYWORD_FUNCTION) { rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Unexpected token '%z',Expecting method declaration after 'final' keyword inside class '%z'", &pGen->pIn->sData, pName); @@ -4305,9 +4157,9 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } goto done; } - nKwrd = PH7_TKWRD_FUNCTION; + nKwrd = PH7_KEYWORD_FUNCTION; } - if(nKwrd != PH7_TKWRD_FUNCTION && nKwrd != PH7_TKWRD_VAR) { + if(nKwrd != PH7_KEYWORD_FUNCTION && nKwrd != PH7_KEYWORD_VAR) { rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Unexpected token '%z',Expecting method declaration inside class '%z'", &pGen->pIn->sData, pName); @@ -4317,7 +4169,7 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } goto done; } - if(nKwrd == PH7_TKWRD_VAR) { + if(nKwrd == PH7_KEYWORD_VAR) { pGen->pIn++; /* Jump the 'var' keyword */ if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_DOLLAR/*'$'*/) == 0) { rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, @@ -4329,10 +4181,10 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { goto done; } /* Attribute declaration */ - rc = GenStateCompileClassAttr(&(*pGen), iProtection, iAttrflags, pClass); + rc = PH7_GenStateCompileClassAttr(&(*pGen), iProtection, iAttrflags, pClass); } else { /* Process method declaration */ - rc = GenStateCompileClassMethod(&(*pGen), iProtection, iAttrflags, TRUE, pClass); + rc = PH7_GenStateCompileClassMethod(&(*pGen), iProtection, iAttrflags, TRUE, pClass); } if(rc != SXRET_OK) { if(rc == SXERR_ABORT) { @@ -4343,7 +4195,7 @@ static sxi32 GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags) { } } else { /* Attribute declaration */ - rc = GenStateCompileClassAttr(&(*pGen), iProtection, iAttrflags, pClass); + rc = PH7_GenStateCompileClassAttr(&(*pGen), iProtection, iAttrflags, pClass); if(rc != SXRET_OK) { if(rc == SXERR_ABORT) { return SXERR_ABORT; @@ -4370,8 +4222,7 @@ done: } /* * Compile a user-defined virtual class. - * According to the PHP language reference manual - * PHP 5 introduces abstract classes and methods. Classes defined as abstract + * Aer introduces virtual classes and methods. Classes defined as abstract * may not be instantiated, and any class that contains at least one abstract * method must also be abstract. Methods defined as abstract simply declare * the method's signature - they cannot define the implementation. @@ -4381,31 +4232,27 @@ done: * method is defined as protected, the function implementation must be defined as either * protected or public, but not private. Furthermore the signatures of the methods must * match, i.e. the type hints and the number of required arguments must be the same. - * This also applies to constructors as of PHP 5.4. Before 5.4 constructor signatures - * could differ. */ static sxi32 PH7_CompileVirtualClass(ph7_gen_state *pGen) { sxi32 rc; pGen->pIn++; /* Jump the 'virtual' keyword */ - rc = GenStateCompileClass(&(*pGen), PH7_CLASS_VIRTUAL); + rc = PH7_GenStateCompileClass(&(*pGen), PH7_CLASS_VIRTUAL); return rc; } /* * Compile a user-defined final class. - * According to the PHP language reference manual - * PHP 5 introduces the final keyword, which prevents child classes from overriding + * Aer introduces the final keyword, which prevents child classes from overriding * a method by prefixing the definition with final. If the class itself is being defined * final then it cannot be extended. */ static sxi32 PH7_CompileFinalClass(ph7_gen_state *pGen) { sxi32 rc; pGen->pIn++; /* Jump the 'final' keyword */ - rc = GenStateCompileClass(&(*pGen), PH7_CLASS_FINAL); + rc = PH7_GenStateCompileClass(&(*pGen), PH7_CLASS_FINAL); return rc; } /* * Compile a user-defined class. - * According to the PHP language reference manual * Basic class definitions begin with the keyword class, followed * by a class name, followed by a pair of curly braces which enclose * the definitions of the properties and methods belonging to the class. @@ -4414,32 +4261,31 @@ static sxi32 PH7_CompileFinalClass(ph7_gen_state *pGen) { */ static sxi32 PH7_CompileClass(ph7_gen_state *pGen) { sxi32 rc; - rc = GenStateCompileClass(&(*pGen), 0); + rc = PH7_GenStateCompileClass(&(*pGen), 0); return rc; } /* * Exception handling. - * According to the PHP language reference manual - * An exception can be thrown, and caught within PHP. Code may be surrounded + * An exception can be thrown, and caught within Aer. Code may be surrounded * in a try block, to facilitate the catching of potential exceptions. Each try must have * at least one corresponding catch block. Multiple catch blocks can be used to catch * different classes of exceptions. Normal execution (when no exception is thrown within * the try block, or when a catch matching the thrown exception's class is not present) * will continue after that last catch block defined in sequence. Exceptions can be thrown * (or re-thrown) within a catch block. - * When an exception is thrown, code following the statement will not be executed, and PHP - * will attempt to find the first matching catch block. If an exception is not caught, a PHP + * When an exception is thrown, code following the statement will not be executed, and Aer + * will attempt to find the first matching catch block. If an exception is not caught, a Aer * Fatal Error will be issued with an "Uncaught Exception ..." message, unless a handler has * been defined with set_exception_handler(). * The thrown object must be an instance of the Exception class or a subclass of Exception. - * Trying to throw an object that is not will result in a PHP Fatal Error. + * Trying to throw an object that is not will result in a Aer Error. */ /* * Expression tree validator callback associated with the 'throw' statement. * Return SXRET_OK if the tree form a valid expression.Any other error * indicates failure. */ -static sxi32 GenStateThrowNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot) { +static sxi32 PH7_GenStateThrowNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot) { sxi32 rc = SXRET_OK; if(pRoot->pOp) { if(pRoot->pOp->iOp != EXPR_OP_SUBSCRIPT /* $a[] */ && pRoot->pOp->iOp != EXPR_OP_NEW /* new Exception() */ @@ -4473,7 +4319,7 @@ static sxi32 PH7_CompileThrow(ph7_gen_state *pGen) { sxi32 rc; pGen->pIn++; /* Jump the 'throw' keyword */ /* Compile the expression */ - rc = PH7_CompileExpr(&(*pGen), 0, GenStateThrowNodeValidator); + rc = PH7_CompileExpr(&(*pGen), 0, PH7_GenStateThrowNodeValidator); if(rc == SXERR_EMPTY) { rc = PH7_GenCompileError(&(*pGen), E_ERROR, nLine, "throw: Expecting an exception class instance"); if(rc == SXERR_ABORT) { @@ -4493,7 +4339,7 @@ static sxi32 PH7_CompileThrow(ph7_gen_state *pGen) { /* Emit the throw instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_THROW, 0, 0, 0, &nIdx); /* Emit the jump */ - GenStateNewJumpFixup(pBlock, PH7_OP_THROW, nIdx); + PH7_GenStateNewJumpFixup(pBlock, PH7_OP_THROW, nIdx); return SXRET_OK; } /* @@ -4578,7 +4424,7 @@ static sxi32 PH7_CompileCatch(ph7_gen_state *pGen, ph7_exception *pException) { /* Compile the block */ pGen->pIn++; /* Jump the right parenthesis */ /* Create the catch block */ - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_EXCEPTION, PH7_VmInstrLength(pGen->pVm), 0, &pCatch); + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_EXCEPTION, PH7_VmInstrLength(pGen->pVm), 0, &pCatch); if(rc != SXRET_OK) { return SXERR_ABORT; } @@ -4588,11 +4434,11 @@ static sxi32 PH7_CompileCatch(ph7_gen_state *pGen, ph7_exception *pException) { /* Compile the block */ PH7_CompileBlock(&(*pGen)); /* Fix forward jumps now the destination is resolved */ - GenStateFixJumps(pCatch, -1, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pCatch, -1, PH7_VmInstrLength(pGen->pVm)); /* Emit the DONE instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_DONE, 0, 0, 0, 0); /* Leave the block */ - GenStateLeaveBlock(&(*pGen), 0); + PH7_GenStateLeaveBlock(&(*pGen), 0); /* Restore the default container */ PH7_VmSetByteCodeContainer(pGen->pVm, pInstrContainer); /* Install the catch block */ @@ -4630,14 +4476,14 @@ static sxi32 PH7_CompileTry(ph7_gen_state *pGen) { SySetInit(&pException->sEntry, &pGen->pVm->sAllocator, sizeof(ph7_exception_block)); pException->pVm = pGen->pVm; /* Create the try block */ - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_EXCEPTION, PH7_VmInstrLength(pGen->pVm), 0, &pTry); + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_EXCEPTION, PH7_VmInstrLength(pGen->pVm), 0, &pTry); if(rc != SXRET_OK) { return SXERR_ABORT; } /* Emit the 'LOAD_EXCEPTION' instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_LOAD_EXCEPTION, 0, 0, pException, &nJmpIdx); /* Fix the jump later when the destination is resolved */ - GenStateNewJumpFixup(pTry, PH7_OP_LOAD_EXCEPTION, nJmpIdx); + PH7_GenStateNewJumpFixup(pTry, PH7_OP_LOAD_EXCEPTION, nJmpIdx); pGen->pIn++; /* Jump the 'try' keyword */ /* Compile the block */ rc = PH7_CompileBlock(&(*pGen)); @@ -4645,14 +4491,14 @@ static sxi32 PH7_CompileTry(ph7_gen_state *pGen) { return SXERR_ABORT; } /* Fix forward jumps now the destination is resolved */ - GenStateFixJumps(pTry, -1, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pTry, -1, PH7_VmInstrLength(pGen->pVm)); /* Emit the 'POP_EXCEPTION' instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_POP_EXCEPTION, 0, 0, pException, 0); /* Leave the block */ - GenStateLeaveBlock(&(*pGen), 0); + PH7_GenStateLeaveBlock(&(*pGen), 0); /* Compile the catch block */ if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0 || - SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_TKWRD_CATCH) { + SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_KEYWORD_CATCH) { SyToken *pTok = pGen->pIn; if(pTok >= pGen->pEnd) { pTok--; /* Point back */ @@ -4668,7 +4514,7 @@ static sxi32 PH7_CompileTry(ph7_gen_state *pGen) { /* Compile one or more catch blocks */ for(;;) { if(pGen->pIn >= pGen->pEnd || (pGen->pIn->nType & PH7_TK_KEYWORD) == 0 - || SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_TKWRD_CATCH) { + || SX_PTR_TO_INT(pGen->pIn->pUserData) != PH7_KEYWORD_CATCH) { /* No more blocks */ break; } @@ -4684,7 +4530,7 @@ static sxi32 PH7_CompileTry(ph7_gen_state *pGen) { * Compile a switch block. * (See block-comment below for more information) */ -static sxi32 GenStateCompileSwitchBlock(ph7_gen_state *pGen, sxu32 *pBlockStart) { +static sxi32 PH7_GenStateCompileSwitchBlock(ph7_gen_state *pGen, sxu32 *pBlockStart) { sxi32 rc = SXRET_OK; while(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & (PH7_TK_SEMI/*';'*/ | PH7_TK_COLON/*':'*/)) == 0) { /* Unexpected token */ @@ -4713,7 +4559,7 @@ static sxi32 GenStateCompileSwitchBlock(ph7_gen_state *pGen, sxu32 *pBlockStart) sxi32 nKwrd; /* Extract the keyword */ nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd == PH7_TKWRD_CASE || nKwrd == PH7_TKWRD_DEFAULT) { + if(nKwrd == PH7_KEYWORD_CASE || nKwrd == PH7_KEYWORD_DEFAULT) { break; } } @@ -4729,7 +4575,7 @@ static sxi32 GenStateCompileSwitchBlock(ph7_gen_state *pGen, sxu32 *pBlockStart) * Compile a case eXpression. * (See block-comment below for more information) */ -static sxi32 GenStateCompileCaseExpr(ph7_gen_state *pGen, ph7_case_expr *pExpr) { +static sxi32 PH7_GenStateCompileCaseExpr(ph7_gen_state *pGen, ph7_case_expr *pExpr) { SySet *pInstrContainer; SyToken *pEnd, *pTmp; sxi32 iNest = 0; @@ -4774,7 +4620,6 @@ static sxi32 GenStateCompileCaseExpr(ph7_gen_state *pGen, ph7_case_expr *pExpr) } /* * Compile the smart switch statement. - * According to the PHP language reference manual * The switch statement is similar to a series of IF statements on the same expression. * In many occasions, you may want to compare the same variable (or expression) with many * different values, and execute a different piece of code depending on which value it equals to. @@ -4786,8 +4631,8 @@ static sxi32 GenStateCompileCaseExpr(ph7_gen_state *pGen, ph7_case_expr *pExpr) * It is important to understand how the switch statement is executed in order to avoid mistakes. * The switch statement executes line by line (actually, statement by statement). * In the beginning, no code is executed. Only when a case statement is found with a value that - * matches the value of the switch expression does PHP begin to execute the statements. - * PHP continues to execute the statements until the end of the switch block, or the first time + * matches the value of the switch expression does Aer begin to execute the statements. + * Aer continues to execute the statements until the end of the switch block, or the first time * it sees a break statement. If you don't write a break statement at the end of a case's statement list. * In a switch statement, the condition is evaluated only once and the result is compared to each * case statement. In an elseif statement, the condition is evaluated again. If your condition @@ -4819,7 +4664,7 @@ static sxi32 PH7_CompileSwitch(ph7_gen_state *pGen) { pGen->pIn++; pEnd = 0; /* cc warning */ /* Create the loop block */ - rc = GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP | GEN_BLOCK_SWITCH, + rc = PH7_GenStateEnterBlock(&(*pGen), GEN_BLOCK_LOOP | GEN_BLOCK_SWITCH, PH7_VmInstrLength(pGen->pVm), 0, &pSwitchBlock); if(rc != SXRET_OK) { return SXERR_ABORT; @@ -4898,11 +4743,10 @@ static sxi32 PH7_CompileSwitch(ph7_gen_state *pGen) { } /* Extract the keyword */ nKwrd = SX_PTR_TO_INT(pGen->pIn->pUserData); - if(nKwrd == PH7_TKWRD_DEFAULT) { + if(nKwrd == PH7_KEYWORD_DEFAULT) { /* - * According to the PHP language reference manual - * A special case is the default case. This case matches anything - * that wasn't matched by the other cases. + * A special case is the default case. This case matches anything + * that wasn't matched by the other cases. */ if(pSwitch->nDefault > 0) { /* Default case already compiled */ @@ -4913,25 +4757,25 @@ static sxi32 PH7_CompileSwitch(ph7_gen_state *pGen) { } pGen->pIn++; /* Jump the 'default' keyword */ /* Compile the default block */ - rc = GenStateCompileSwitchBlock(pGen, &pSwitch->nDefault); + rc = PH7_GenStateCompileSwitchBlock(pGen, &pSwitch->nDefault); if(rc == SXERR_ABORT) { return SXERR_ABORT; } else if(rc == SXERR_EOF) { break; } - } else if(nKwrd == PH7_TKWRD_CASE) { + } else if(nKwrd == PH7_KEYWORD_CASE) { ph7_case_expr sCase; /* Standard case block */ pGen->pIn++; /* Jump the 'case' keyword */ /* initialize the structure */ SySetInit(&sCase.aByteCode, &pGen->pVm->sAllocator, sizeof(VmInstr)); /* Compile the case expression */ - rc = GenStateCompileCaseExpr(pGen, &sCase); + rc = PH7_GenStateCompileCaseExpr(pGen, &sCase); if(rc == SXERR_ABORT) { return SXERR_ABORT; } /* Compile the case block */ - rc = GenStateCompileSwitchBlock(pGen, &sCase.nStart); + rc = PH7_GenStateCompileSwitchBlock(pGen, &sCase.nStart); /* Insert in the switch container */ SySetPut(&pSwitch->aCaseExpr, (const void *)&sCase); if(rc == SXERR_ABORT) { @@ -4951,9 +4795,9 @@ static sxi32 PH7_CompileSwitch(ph7_gen_state *pGen) { } /* Fix all jumps now the destination is resolved */ pSwitch->nOut = PH7_VmInstrLength(pGen->pVm); - GenStateFixJumps(pSwitchBlock, -1, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pSwitchBlock, -1, PH7_VmInstrLength(pGen->pVm)); /* Release the loop block */ - GenStateLeaveBlock(pGen, 0); + PH7_GenStateLeaveBlock(pGen, 0); if(pGen->pIn < pGen->pEnd) { /* Jump the trailing curly braces or the endswitch keyword*/ pGen->pIn++; @@ -4974,7 +4818,7 @@ Synchronize: * this function takes care of generating the appropriate * error message. */ -static sxi32 GenStateEmitExprCode( +static sxi32 PH7_GenStateEmitExprCode( ph7_gen_state *pGen, /* Code generator state */ ph7_expr_node *pNode, /* Root of the expression tree */ sxi32 iFlags /* Control flags */ @@ -5004,7 +4848,7 @@ static sxi32 GenStateEmitExprCode( sxu32 nJz, nJmp; /* Ternary operator require special handling */ /* Phase#1: Compile the condition */ - rc = GenStateEmitExprCode(&(*pGen), pNode->pCond, iFlags); + rc = PH7_GenStateEmitExprCode(&(*pGen), pNode->pCond, iFlags); if(rc != SXRET_OK) { return rc; } @@ -5013,7 +4857,7 @@ static sxi32 GenStateEmitExprCode( PH7_VmEmitInstr(pGen->pVm, PH7_OP_JZ, 0, 0, 0, &nJz); if(pNode->pLeft) { /* Phase#3: Compile the 'then' expression */ - rc = GenStateEmitExprCode(&(*pGen), pNode->pLeft, iFlags); + rc = PH7_GenStateEmitExprCode(&(*pGen), pNode->pLeft, iFlags); if(rc != SXRET_OK) { return rc; } @@ -5027,7 +4871,7 @@ static sxi32 GenStateEmitExprCode( } /* Phase#6: Compile the 'else' expression */ if(pNode->pRight) { - rc = GenStateEmitExprCode(&(*pGen), pNode->pRight, iFlags); + rc = PH7_GenStateEmitExprCode(&(*pGen), pNode->pRight, iFlags); if(rc != SXRET_OK) { return rc; } @@ -5052,7 +4896,7 @@ static sxi32 GenStateEmitExprCode( /* Read-only load */ iFlags |= EXPR_FLAG_RDONLY_LOAD; for(n = 0 ; n < (sxi32)SySetUsed(&pNode->aNodeArgs) ; ++n) { - rc = GenStateEmitExprCode(&(*pGen), apNode[n], iFlags & ~EXPR_FLAG_LOAD_IDX_STORE); + rc = PH7_GenStateEmitExprCode(&(*pGen), apNode[n], iFlags & ~EXPR_FLAG_LOAD_IDX_STORE); if(rc != SXRET_OK) { return rc; } @@ -5062,7 +4906,7 @@ static sxi32 GenStateEmitExprCode( /* Remove stale flags now */ iFlags &= ~EXPR_FLAG_RDONLY_LOAD; } - rc = GenStateEmitExprCode(&(*pGen), pNode->pLeft, iFlags); + rc = PH7_GenStateEmitExprCode(&(*pGen), pNode->pLeft, iFlags); if(rc != SXRET_OK) { return rc; } @@ -5083,7 +4927,7 @@ static sxi32 GenStateEmitExprCode( /* Recurse and generate bytecodes for array index */ apNode = (ph7_expr_node **)SySetBasePtr(&pNode->aNodeArgs); for(n = 0 ; n < (sxi32)SySetUsed(&pNode->aNodeArgs) ; ++n) { - rc = GenStateEmitExprCode(&(*pGen), apNode[n], iFlags & ~EXPR_FLAG_LOAD_IDX_STORE); + rc = PH7_GenStateEmitExprCode(&(*pGen), apNode[n], iFlags & ~EXPR_FLAG_LOAD_IDX_STORE); if(rc != SXRET_OK) { return rc; } @@ -5113,7 +4957,7 @@ static sxi32 GenStateEmitExprCode( } else if(pNode->pOp->iPrec == 18 /* Combined binary operators [i.e: =,'.=','+=',*=' ...] precedence */) { iFlags |= EXPR_FLAG_LOAD_IDX_STORE; } - rc = GenStateEmitExprCode(&(*pGen), pNode->pRight, iFlags); + rc = PH7_GenStateEmitExprCode(&(*pGen), pNode->pRight, iFlags); if(iVmOp == PH7_OP_STORE) { pInstr = PH7_VmPeekInstr(pGen->pVm); if(pInstr) { @@ -5193,10 +5037,9 @@ static sxi32 GenStateEmitExprCode( return rc; } /* - * Compile a PHP expression. - * According to the PHP language reference manual: - * Expressions are the most important building stones of PHP. - * In PHP, almost anything you write is an expression. + * Compile an AerScript expression. + * Expressions are the most important building stones of Aer. + * In Aer, almost anything you write is an expression. * The simplest yet most accurate way to define an expression * is "anything that has a value". * If something goes wrong while compiling the expression,this @@ -5225,7 +5068,7 @@ static sxi32 PH7_CompileExpr( iNest = 0; while(pEnd < pGen->pEnd) { if(pEnd->nType & PH7_TK_OCB /* '{' */) { - /* Ticket 1433-30: Annonymous/Closure functions body */ + /* Ticket 1433-30: Anonymous/Closure functions body */ iNest++; } else if(pEnd->nType & PH7_TK_CCB /* '}' */) { iNest--; @@ -5270,7 +5113,7 @@ static sxi32 PH7_CompileExpr( } if(rc != SXERR_ABORT) { /* Generate code for the given tree */ - rc = GenStateEmitExprCode(&(*pGen), pRoot, iFlags); + rc = PH7_GenStateEmitExprCode(&(*pGen), pRoot, iFlags); } nExpr = 1; } @@ -5301,41 +5144,62 @@ PH7_PRIVATE ProcNodeConstruct PH7_GetNodeHandler(sxu32 nNodeType) { } else if(nNodeType & PH7_TK_SSTR) { /* Single quoted string */ return PH7_CompileSimpleString; - } else if(nNodeType & PH7_TK_BSTR) { - /* Backtick quoted string */ - return PH7_CompileBacktic; } return 0; } /* - * PHP Language construct table. + * Aer Language construct table. */ static const LangConstruct aLangConstruct[] = { - { PH7_TKWRD_IF, PH7_CompileIf }, /* if statement */ - { PH7_TKWRD_FOR, PH7_CompileFor }, /* for statement */ - { PH7_TKWRD_WHILE, PH7_CompileWhile }, /* while statement */ - { PH7_TKWRD_FOREACH, PH7_CompileForeach }, /* foreach statement */ - { PH7_TKWRD_FUNCTION, PH7_CompileFunction }, /* function statement */ - { PH7_TKWRD_CONTINUE, PH7_CompileContinue }, /* continue statement */ - { PH7_TKWRD_BREAK, PH7_CompileBreak }, /* break statement */ - { PH7_TKWRD_RETURN, PH7_CompileReturn }, /* return statement */ - { PH7_TKWRD_SWITCH, PH7_CompileSwitch }, /* Switch statement */ - { PH7_TKWRD_DO, PH7_CompileDoWhile }, /* do{ }while(); statement */ - { PH7_TKWRD_STATIC, PH7_CompileStatic }, /* static statement */ - { PH7_TKWRD_EXIT, PH7_CompileHalt }, /* exit language construct */ - { PH7_TKWRD_TRY, PH7_CompileTry }, /* try statement */ - { PH7_TKWRD_THROW, PH7_CompileThrow }, /* throw statement */ - { PH7_TKWRD_CONST, PH7_CompileConstant }, /* const statement */ - { PH7_TKWRD_VAR, PH7_CompileVar }, /* var statement */ - { PH7_TKWRD_NAMESPACE, PH7_CompileNamespace }, /* namespace statement */ - { PH7_TKWRD_USING, PH7_CompileUsing }, /* using statement */ + { PH7_KEYWORD_IF, PH7_CompileIf }, /* if statement */ + { PH7_KEYWORD_FOR, PH7_CompileFor }, /* for statement */ + { PH7_KEYWORD_WHILE, PH7_CompileWhile }, /* while statement */ + { PH7_KEYWORD_FOREACH, PH7_CompileForeach }, /* foreach statement */ + { PH7_KEYWORD_CONTINUE, PH7_CompileContinue }, /* continue statement */ + { PH7_KEYWORD_BREAK, PH7_CompileBreak }, /* break statement */ + { PH7_KEYWORD_RETURN, PH7_CompileReturn }, /* return statement */ + { PH7_KEYWORD_SWITCH, PH7_CompileSwitch }, /* Switch statement */ + { PH7_KEYWORD_DO, PH7_CompileDoWhile }, /* do{ }while(); statement */ + { PH7_KEYWORD_STATIC, PH7_CompileStatic }, /* static statement */ + { PH7_KEYWORD_EXIT, PH7_CompileHalt }, /* exit language construct */ + { PH7_KEYWORD_TRY, PH7_CompileTry }, /* try statement */ + { PH7_KEYWORD_THROW, PH7_CompileThrow }, /* throw statement */ + { PH7_KEYWORD_CONST, PH7_CompileConstant }, /* const statement */ + { PH7_KEYWORD_VAR, PH7_CompileVar }, /* var statement */ }; /* - * Return a pointer to the statement handler routine associated - * with a given PHP keyword [i.e: if,for,while,...]. + * Return a pointer to the global scope handler routine associated */ -static ProcLangConstruct GenStateGetStatementHandler( - sxu32 nKeywordID, /* Keyword ID*/ +static ProcLangConstruct PH7_GenStateGetGlobalScopeHandler( + sxu32 nKeywordID, /* Keyword ID */ + SyToken *pLookahead /* Look-ahead token */ +) { + if(pLookahead) { + if(nKeywordID == PH7_KEYWORD_INTERFACE && (pLookahead->nType & PH7_TK_ID)) { + return PH7_CompileClassInterface; + } else if(nKeywordID == PH7_KEYWORD_CLASS && (pLookahead->nType & PH7_TK_ID)) { + return PH7_CompileClass; + } else if(nKeywordID == PH7_KEYWORD_VIRTUAL && (pLookahead->nType & PH7_TK_KEYWORD) + && SX_PTR_TO_INT(pLookahead->pUserData) == PH7_KEYWORD_CLASS) { + return PH7_CompileVirtualClass; + } else if(nKeywordID == PH7_KEYWORD_FINAL && (pLookahead->nType & PH7_TK_KEYWORD) + && SX_PTR_TO_INT(pLookahead->pUserData) == PH7_KEYWORD_CLASS) { + return PH7_CompileFinalClass; + } else if(nKeywordID == PH7_KEYWORD_NAMESPACE && (pLookahead->nType & PH7_TK_ID)) { + return PH7_CompileNamespace; + } else if(nKeywordID == PH7_KEYWORD_USING && (pLookahead->nType & PH7_TK_ID)) { + return PH7_CompileUsing; + } + } + /* Not a global scope language construct */ + return 0; +} +/* + * Return a pointer to the statement handler routine associated + * with a given Aer keyword [i.e: if,for,while,...]. + */ +static ProcLangConstruct PH7_GenStateGetStatementHandler( + sxu32 nKeywordID, /* Keyword ID */ SyToken *pLookahead /* Look-ahead token */ ) { sxu32 n = 0; @@ -5344,7 +5208,7 @@ static ProcLangConstruct GenStateGetStatementHandler( break; } if(aLangConstruct[n].nID == nKeywordID) { - if(nKeywordID == PH7_TKWRD_STATIC && pLookahead && (pLookahead->nType & PH7_TK_OP)) { + if(nKeywordID == PH7_KEYWORD_STATIC && pLookahead && (pLookahead->nType & PH7_TK_OP)) { const ph7_expr_op *pOp = (const ph7_expr_op *)pLookahead->pUserData; if(pOp && pOp->iOp == EXPR_OP_DC /*::*/) { /* 'static' (class context),return null */ @@ -5357,48 +5221,29 @@ static ProcLangConstruct GenStateGetStatementHandler( } n++; } - if(pLookahead) { - if(nKeywordID == PH7_TKWRD_INTERFACE && (pLookahead->nType & PH7_TK_ID)) { - return PH7_CompileClassInterface; - } else if(nKeywordID == PH7_TKWRD_CLASS && (pLookahead->nType & PH7_TK_ID)) { - return PH7_CompileClass; - } else if(nKeywordID == PH7_TKWRD_VIRTUAL && (pLookahead->nType & PH7_TK_KEYWORD) - && SX_PTR_TO_INT(pLookahead->pUserData) == PH7_TKWRD_CLASS) { - return PH7_CompileVirtualClass; - } else if(nKeywordID == PH7_TKWRD_FINAL && (pLookahead->nType & PH7_TK_KEYWORD) - && SX_PTR_TO_INT(pLookahead->pUserData) == PH7_TKWRD_CLASS) { - return PH7_CompileFinalClass; - } - } /* Not a language construct */ return 0; } /* - * Check if the given keyword is in fact a PHP language construct. - * Return TRUE on success. FALSE otherwise. + * Return TRUE if the given ID represent a language construct. FALSE otherwise. */ -static int GenStateisLangConstruct(sxu32 nKeyword) { - int rc; - rc = PH7_IsLangConstruct(nKeyword, TRUE); - if(rc == FALSE) { - if(nKeyword == PH7_TKWRD_SELF || nKeyword == PH7_TKWRD_PARENT || nKeyword == PH7_TKWRD_STATIC - /*|| nKeyword == PH7_TKWRD_CLASS || nKeyword == PH7_TKWRD_FINAL || nKeyword == PH7_TKWRD_EXTENDS - || nKeyword == PH7_TKWRD_VIRTUAL || nKeyword == PH7_TKWRD_INTERFACE - || nKeyword == PH7_TKWRD_PUBLIC || nKeyword == PH7_TKWRD_PROTECTED - || nKeyword == PH7_TKWRD_PRIVATE || nKeyword == PH7_TKWRD_IMPLEMENTS - */ - ) { - rc = TRUE; - } +static int PH7_IsLangConstruct(sxu32 nKeywordID) { + if(nKeywordID == PH7_KEYWORD_IMPORT || nKeywordID == PH7_KEYWORD_INCLUDE || nKeywordID == PH7_KEYWORD_REQUIRE + || nKeywordID == PH7_KEYWORD_ISSET || nKeywordID == PH7_KEYWORD_UNSET || nKeywordID == PH7_KEYWORD_EVAL + || nKeywordID == PH7_KEYWORD_EMPTY || nKeywordID == PH7_KEYWORD_ARRAY || nKeywordID == PH7_KEYWORD_LIST + || nKeywordID == PH7_KEYWORD_SELF || nKeywordID == PH7_KEYWORD_PARENT || nKeywordID == PH7_KEYWORD_STATIC + || /* TICKET 1433-012 */ nKeywordID == PH7_KEYWORD_NEW || nKeywordID == PH7_KEYWORD_CLONE) { + return TRUE; } - return rc; + /* Not a language construct */ + return FALSE; } /* - * Compile a PHP chunk. - * If something goes wrong while compiling the PHP chunk,this function + * Compile an AerScript chunk. + * If something goes wrong while compiling the Aer chunk, this function * takes care of generating the appropriate error message. */ -static sxi32 GenStateCompileChunk( +static sxi32 PH7_GenStateCompileChunk( ph7_gen_state *pGen, /* Code generator state */ sxi32 iFlags /* Compile flags */ ) { @@ -5421,8 +5266,8 @@ static sxi32 GenStateCompileChunk( if(pGen->pIn->nType & PH7_TK_KEYWORD) { sxu32 nKeyword = (sxu32)SX_PTR_TO_INT(pGen->pIn->pUserData); /* Try to extract a language construct handler */ - xCons = GenStateGetStatementHandler(nKeyword, (&pGen->pIn[1] < pGen->pEnd) ? &pGen->pIn[1] : 0); - if(xCons == 0 && GenStateisLangConstruct(nKeyword) == FALSE) { + xCons = PH7_GenStateGetStatementHandler(nKeyword, (&pGen->pIn[1] < pGen->pEnd) ? &pGen->pIn[1] : 0); + if(xCons == 0 && PH7_IsLangConstruct(nKeyword) == FALSE) { rc = PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Syntax error: Unexpected keyword '%z'", &pGen->pIn->sData); @@ -5443,7 +5288,7 @@ static sxi32 GenStateCompileChunk( PH7_VmEmitInstr(pGen->pVm, PH7_OP_POP, 1, 0, 0, 0); } } else { - /* Go compile the sucker */ + /* Compile the statement */ rc = xCons(&(*pGen)); } if(rc == SXERR_ABORT) { @@ -5455,27 +5300,64 @@ static sxi32 GenStateCompileChunk( while(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI)) { pGen->pIn++; } - if(iFlags & PH7_COMPILE_SINGLE_STMT) { + if(iFlags & PH7_COMPILE_STATEMENT) { /* Compile a single statement and return */ break; } - /* LOOP ONE */ - /* LOOP TWO */ - /* LOOP THREE */ - /* LOOP FOUR */ } /* Return compilation status */ return rc; } /* - * Compile a Raw PHP chunk. - * If something goes wrong while compiling the PHP chunk,this function + * Compile an AerScript global scope. + * If something goes wrong while compiling the Aer global scope, this function * takes care of generating the appropriate error message. */ -static sxi32 PH7_CompilePHP( +static sxi32 PH7_GenStateCompileGlobalScope( + ph7_gen_state *pGen /* Code generator state */ +) { + ProcLangConstruct xCons; + sxi32 rc; + rc = SXRET_OK; /* Prevent compiler warning */ + for(;;) { + if(pGen->pIn >= pGen->pEnd) { + /* No more input to process */ + break; + } + xCons = 0; + if(pGen->pIn->nType & PH7_TK_KEYWORD) { + sxu32 nKeyword = (sxu32)SX_PTR_TO_INT(pGen->pIn->pUserData); + /* Try to extract a language construct handler */ + xCons = PH7_GenStateGetGlobalScopeHandler(nKeyword, (&pGen->pIn[1] < pGen->pEnd) ? &pGen->pIn[1] : 0); + if(xCons == 0) { + PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Syntax error: Unexpected keyword '%z'", &pGen->pIn->sData); + } + /* Compile the statement */ + rc = xCons(&(*pGen)); + if(rc == SXERR_ABORT) { + /* Request to abort compilation */ + break; + } + } else { + PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "Syntax error: Unexpected token '%z'", &pGen->pIn->sData); + } + /* Ignore trailing semi-colons ';' */ + while(pGen->pIn < pGen->pEnd && (pGen->pIn->nType & PH7_TK_SEMI)) { + pGen->pIn++; + } + } + /* Return compilation status */ + return rc; +} +/* + * Compile a Raw Aer chunk. + * If something goes wrong while compiling the Aer chunk,this function + * takes care of generating the appropriate error message. + */ +static sxi32 PH7_CompileScript( ph7_gen_state *pGen, /* Code generator state */ SySet *pTokenSet, /* Token set */ - int is_expr /* TRUE if we are dealing with a simple expression */ + sxi32 iFlags /* Compiler flags */ ) { SyToken *pScript = pGen->pRawIn; /* Script to compile */ sxi32 rc; @@ -5485,12 +5367,12 @@ static sxi32 PH7_CompilePHP( pGen->pTokenSet = &(*pTokenSet); /* Advance the stream cursor */ pGen->pRawIn++; - /* Tokenize the PHP chunk first */ - PH7_TokenizePHP(SyStringData(&pScript->sData), SyStringLength(&pScript->sData), pScript->nLine, &(*pTokenSet)); + /* Tokenize the Aer chunk first */ + PH7_TokenizeAerScript(SyStringData(&pScript->sData), SyStringLength(&pScript->sData), pScript->nLine, &(*pTokenSet)); /* Point to the head and tail of the token stream. */ pGen->pIn = (SyToken *)SySetBasePtr(pTokenSet); pGen->pEnd = &pGen->pIn[SySetUsed(pTokenSet)]; - if(is_expr) { + if(iFlags & PH7_AERSCRIPT_EXPR) { rc = SXERR_EMPTY; if(pGen->pIn < pGen->pEnd) { /* A simple expression,compile it */ @@ -5499,30 +5381,33 @@ static sxi32 PH7_CompilePHP( /* Emit the DONE instruction */ PH7_VmEmitInstr(pGen->pVm, PH7_OP_DONE, (rc != SXERR_EMPTY ? 1 : 0), 0, 0, 0); return SXRET_OK; + } else if(iFlags & PH7_AERSCRIPT_CHNK) { + /* Compile a chunk of code */ + rc = PH7_GenStateCompileChunk(pGen, 0); + } else { + /* Compile the Aer global scope */ + rc = PH7_GenStateCompileGlobalScope(pGen); } - /* Compile the PHP chunk */ - rc = GenStateCompileChunk(pGen, 0); /* Fix exceptions jumps */ - GenStateFixJumps(pGen->pCurrent, PH7_OP_THROW, PH7_VmInstrLength(pGen->pVm)); + PH7_GenStateFixJumps(pGen->pCurrent, PH7_OP_THROW, PH7_VmInstrLength(pGen->pVm)); /* Compilation result */ return rc; } /* - * Compile a raw chunk. The raw chunk can contain PHP code embedded + * Compile a raw chunk. The raw chunk can contain Aer code embedded * in HTML, XML and so on. This function handle all the stuff. * This is the only compile interface exported from this file. */ -PH7_PRIVATE sxi32 PH7_CompileScript( +PH7_PRIVATE sxi32 PH7_CompileAerScript( ph7_vm *pVm, /* Generate PH7 byte-codes for this Virtual Machine */ SyString *pScript, /* Script to compile */ - sxi32 iFlags /* Compile flags */ + sxi32 iFlags /* Compiler flags */ ) { - SySet aPhpToken, aRawToken; + SySet aAerToken, aRawToken; ph7_gen_state *pCodeGen; ph7_value *pRawObj; sxu32 nObjIdx; sxi32 nRawObj; - int is_expr; sxi32 rc; if(pScript->nByte < 1) { /* Nothing to compile */ @@ -5530,43 +5415,38 @@ PH7_PRIVATE sxi32 PH7_CompileScript( } /* Initialize the tokens containers */ SySetInit(&aRawToken, &pVm->sAllocator, sizeof(SyToken)); - SySetInit(&aPhpToken, &pVm->sAllocator, sizeof(SyToken)); - SySetAlloc(&aPhpToken, 0xc0); - is_expr = 0; + SySetInit(&aAerToken, &pVm->sAllocator, sizeof(SyToken)); + SySetAlloc(&aAerToken, 0xc0); SyToken sTmp; sTmp.nLine = 1; sTmp.pUserData = 0; SyStringDupPtr(&sTmp.sData, pScript); SySetPut(&aRawToken, (const void *)&sTmp); - if(iFlags & PH7_PHP_EXPR) { - /* A simple PHP expression */ - is_expr = 1; - } pCodeGen = &pVm->sCodeGen; /* Process high-level tokens */ pCodeGen->pRawIn = (SyToken *)SySetBasePtr(&aRawToken); pCodeGen->pRawEnd = &pCodeGen->pRawIn[SySetUsed(&aRawToken)]; rc = PH7_OK; - if(is_expr) { + if(iFlags & PH7_AERSCRIPT_EXPR) { /* Compile the expression */ - rc = PH7_CompilePHP(pCodeGen, &aPhpToken, TRUE); - goto cleanup; - } - nObjIdx = 0; - /* Start the compilation process */ - for(;;) { - /* Compile PHP block of code */ - if(pCodeGen->pRawIn >= pCodeGen->pRawEnd) { - break; /* No more tokens to process */ - } - rc = PH7_CompilePHP(pCodeGen, &aPhpToken, FALSE); - if(rc == SXERR_ABORT) { - break; + rc = PH7_CompileScript(pCodeGen, &aAerToken, iFlags); + } else { + nObjIdx = 0; + /* Start the compilation process */ + for(;;) { + /* Compile Aer block of code */ + if(pCodeGen->pRawIn >= pCodeGen->pRawEnd) { + break; /* No more tokens to process */ + } + /* Compile the code */ + rc = PH7_CompileScript(pCodeGen, &aAerToken, iFlags); + if(rc == SXERR_ABORT) { + break; + } } } -cleanup: SySetRelease(&aRawToken); - SySetRelease(&aPhpToken); + SySetRelease(&aAerToken); return rc; } /* @@ -5574,7 +5454,7 @@ cleanup: */ PH7_PRIVATE sxi32 PH7_InitCodeGenerator( ph7_vm *pVm, /* Target VM */ - ProcConsumer xErr, /* Error log consumer callabck */ + ProcConsumer xErr, /* Error log consumer callback */ void *pErrData /* Last argument to xErr() */ ) { ph7_gen_state *pGen = &pVm->sCodeGen; @@ -5591,7 +5471,7 @@ PH7_PRIVATE sxi32 PH7_InitCodeGenerator( /* General purpose working buffer */ SyBlobInit(&pGen->sWorker, &pVm->sAllocator); /* Create the global scope */ - GenStateInitBlock(pGen, &pGen->sGlobal, GEN_BLOCK_GLOBAL, PH7_VmInstrLength(&(*pVm)), 0); + PH7_GenStateInitBlock(pGen, &pGen->sGlobal, GEN_BLOCK_GLOBAL, PH7_VmInstrLength(&(*pVm)), 0); /* Point to the global scope */ pGen->pCurrent = &pGen->sGlobal; return SXRET_OK; @@ -5601,7 +5481,7 @@ PH7_PRIVATE sxi32 PH7_InitCodeGenerator( */ PH7_PRIVATE sxi32 PH7_ResetCodeGenerator( ph7_vm *pVm, /* Target VM */ - ProcConsumer xErr, /* Error log consumer callabck */ + ProcConsumer xErr, /* Error log consumer callback */ void *pErrData /* Last argument to xErr() */ ) { ph7_gen_state *pGen = &pVm->sCodeGen; @@ -5613,7 +5493,7 @@ PH7_PRIVATE sxi32 PH7_ResetCodeGenerator( pBlock = pGen->pCurrent; while(pBlock->pParent != 0) { pParent = pBlock->pParent; - GenStateFreeBlock(pBlock); + PH7_GenStateFreeBlock(pBlock); pBlock = pParent; } pGen->xErr = xErr; @@ -5661,23 +5541,14 @@ PH7_PRIVATE sxi32 PH7_GenCompileError(ph7_gen_state *pGen, sxi32 nErrType, sxu32 return SXRET_OK; } switch(nErrType) { - case E_WARNING: - zErr = "Warning"; - break; - case E_PARSE: - zErr = "Parse error"; + case E_DEPRECATED: + zErr = "Deprecated"; break; case E_NOTICE: zErr = "Notice"; break; - case E_USER_ERROR: - zErr = "User error"; - break; - case E_USER_WARNING: - zErr = "User warning"; - break; - case E_USER_NOTICE: - zErr = "User notice"; + case E_WARNING: + zErr = "Warning"; break; default: zErr = "Error"; @@ -5699,5 +5570,8 @@ PH7_PRIVATE sxi32 PH7_GenCompileError(ph7_gen_state *pGen, sxi32 nErrType, sxu32 /* Consume the generated error message */ pGen->xErr(SyBlobData(pWorker), SyBlobLength(pWorker), pGen->pErrData); } + if(nErrType == E_ERROR) { + exit(255); + } return rc; } diff --git a/engine/lexer.c b/engine/lexer.c index aba509d..69e22b9 100644 --- a/engine/lexer.c +++ b/engine/lexer.c @@ -83,7 +83,7 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo nKeyword = KeywordCode(pStr->zString, (int)pStr->nByte); if(nKeyword != PH7_TK_ID) { if(nKeyword & - (PH7_TKWRD_NEW | PH7_TKWRD_CLONE | PH7_TKWRD_INSTANCEOF)) { + (PH7_KEYWORD_NEW | PH7_KEYWORD_CLONE | PH7_KEYWORD_INSTANCEOF)) { /* Alpha stream operators [i.e: new,clone,instanceof],save the operator instance for later processing */ pToken->pUserData = (void *)PH7_ExprExtractOperator(pStr, 0); /* Mark as an operator */ @@ -225,22 +225,22 @@ static sxi32 TokenizePHP(SyStream *pStream, SyToken *pToken, void *pUserData, vo pTmp = (SyToken *)SySetPeek(pTokSet); if(pTmp->nType & PH7_TK_KEYWORD) { sxi32 nID = SX_PTR_TO_INT(pTmp->pUserData); - if((sxu32)nID & (PH7_TKWRD_ARRAY | PH7_TKWRD_INT | PH7_TKWRD_FLOAT | PH7_TKWRD_STRING | PH7_TKWRD_OBJECT | PH7_TKWRD_BOOL | PH7_TKWRD_UNSET)) { + if((sxu32)nID & (PH7_KEYWORD_ARRAY | PH7_KEYWORD_INT | PH7_KEYWORD_FLOAT | PH7_KEYWORD_STRING | PH7_KEYWORD_OBJECT | PH7_KEYWORD_BOOL | PH7_KEYWORD_UNSET)) { pTmp = (SyToken *)SySetAt(pTokSet, pTokSet->nUsed - 2); if(pTmp->nType & PH7_TK_LPAREN) { /* Merge the three tokens '(' 'TYPE' ')' into a single one */ const char *zTypeCast = "(int)"; - if(nID & PH7_TKWRD_FLOAT) { + if(nID & PH7_KEYWORD_FLOAT) { zTypeCast = "(float)"; - } else if(nID & PH7_TKWRD_BOOL) { + } else if(nID & PH7_KEYWORD_BOOL) { zTypeCast = "(bool)"; - } else if(nID & PH7_TKWRD_STRING) { + } else if(nID & PH7_KEYWORD_STRING) { zTypeCast = "(string)"; - } else if(nID & PH7_TKWRD_ARRAY) { + } else if(nID & PH7_KEYWORD_ARRAY) { zTypeCast = "(array)"; - } else if(nID & PH7_TKWRD_OBJECT) { + } else if(nID & PH7_KEYWORD_OBJECT) { zTypeCast = "(object)"; - } else if(nID & PH7_TKWRD_UNSET) { + } else if(nID & PH7_KEYWORD_UNSET) { zTypeCast = "(unset)"; } /* Reflect the change */ @@ -573,59 +573,59 @@ static sxu32 KeywordCode(const char *z, int n) { int value; } ph7_token; static ph7_token pTokenLookup[] = { - {"extends", PH7_TKWRD_EXTENDS}, - {"switch", PH7_TKWRD_SWITCH}, - {"int", PH7_TKWRD_INT}, - {"require_once", PH7_TKWRD_REQONCE}, - {"require", PH7_TKWRD_REQUIRE}, - {"return", PH7_TKWRD_RETURN}, - {"namespace", PH7_TKWRD_NAMESPACE}, - {"object", PH7_TKWRD_OBJECT}, - {"throw", PH7_TKWRD_THROW}, - {"bool", PH7_TKWRD_BOOL}, - {"default", PH7_TKWRD_DEFAULT}, - {"try", PH7_TKWRD_TRY}, - {"case", PH7_TKWRD_CASE}, - {"self", PH7_TKWRD_SELF}, - {"final", PH7_TKWRD_FINAL}, - {"list", PH7_TKWRD_LIST}, - {"static", PH7_TKWRD_STATIC}, - {"clone", PH7_TKWRD_CLONE}, - {"new", PH7_TKWRD_NEW}, - {"const", PH7_TKWRD_CONST}, - {"string", PH7_TKWRD_STRING}, - {"using", PH7_TKWRD_USING}, - {"elseif", PH7_TKWRD_ELIF}, - {"else", PH7_TKWRD_ELSE}, - {"if", PH7_TKWRD_IF}, - {"float", PH7_TKWRD_FLOAT}, - {"var", PH7_TKWRD_VAR}, - {"array", PH7_TKWRD_ARRAY}, - {"virtual", PH7_TKWRD_VIRTUAL}, - {"class", PH7_TKWRD_CLASS}, - {"as", PH7_TKWRD_AS}, - {"continue", PH7_TKWRD_CONTINUE}, - {"function", PH7_TKWRD_FUNCTION}, - {"while", PH7_TKWRD_WHILE}, - {"eval", PH7_TKWRD_EVAL}, - {"do", PH7_TKWRD_DO}, - {"exit", PH7_TKWRD_EXIT}, - {"implements", PH7_TKWRD_IMPLEMENTS}, - {"include_once", PH7_TKWRD_INCONCE}, - {"include", PH7_TKWRD_INCLUDE}, - {"empty", PH7_TKWRD_EMPTY}, - {"instanceof", PH7_TKWRD_INSTANCEOF}, - {"interface", PH7_TKWRD_INTERFACE}, - {"for", PH7_TKWRD_FOR}, - {"foreach", PH7_TKWRD_FOREACH}, - {"isset", PH7_TKWRD_ISSET}, - {"parent", PH7_TKWRD_PARENT}, - {"private", PH7_TKWRD_PRIVATE}, - {"protected", PH7_TKWRD_PROTECTED}, - {"public", PH7_TKWRD_PUBLIC}, - {"catch", PH7_TKWRD_CATCH}, - {"unset", PH7_TKWRD_UNSET}, - {"break", PH7_TKWRD_BREAK} + {"extends", PH7_KEYWORD_EXTENDS}, + {"switch", PH7_KEYWORD_SWITCH}, + {"int", PH7_KEYWORD_INT}, + {"require", PH7_KEYWORD_REQUIRE}, + {"return", PH7_KEYWORD_RETURN}, + {"namespace", PH7_KEYWORD_NAMESPACE}, + {"object", PH7_KEYWORD_OBJECT}, + {"throw", PH7_KEYWORD_THROW}, + {"bool", PH7_KEYWORD_BOOL}, + {"default", PH7_KEYWORD_DEFAULT}, + {"try", PH7_KEYWORD_TRY}, + {"case", PH7_KEYWORD_CASE}, + {"self", PH7_KEYWORD_SELF}, + {"final", PH7_KEYWORD_FINAL}, + {"finally", PH7_KEYWORD_FINALLY}, + {"list", PH7_KEYWORD_LIST}, + {"static", PH7_KEYWORD_STATIC}, + {"clone", PH7_KEYWORD_CLONE}, + {"new", PH7_KEYWORD_NEW}, + {"const", PH7_KEYWORD_CONST}, + {"string", PH7_KEYWORD_STRING}, + {"using", PH7_KEYWORD_USING}, + {"elseif", PH7_KEYWORD_ELIF}, + {"else", PH7_KEYWORD_ELSE}, + {"if", PH7_KEYWORD_IF}, + {"float", PH7_KEYWORD_FLOAT}, + {"var", PH7_KEYWORD_VAR}, + {"array", PH7_KEYWORD_ARRAY}, + {"virtual", PH7_KEYWORD_VIRTUAL}, + {"class", PH7_KEYWORD_CLASS}, + {"as", PH7_KEYWORD_AS}, + {"continue", PH7_KEYWORD_CONTINUE}, + {"function", PH7_KEYWORD_FUNCTION}, + {"while", PH7_KEYWORD_WHILE}, + {"eval", PH7_KEYWORD_EVAL}, + {"do", PH7_KEYWORD_DO}, + {"exit", PH7_KEYWORD_EXIT}, + {"import", PH7_KEYWORD_IMPORT}, + {"implements", PH7_KEYWORD_IMPLEMENTS}, + {"include", PH7_KEYWORD_INCLUDE}, + {"empty", PH7_KEYWORD_EMPTY}, + {"instanceof", PH7_KEYWORD_INSTANCEOF}, + {"interface", PH7_KEYWORD_INTERFACE}, + {"for", PH7_KEYWORD_FOR}, + {"foreach", PH7_KEYWORD_FOREACH}, + {"isset", PH7_KEYWORD_ISSET}, + {"parent", PH7_KEYWORD_PARENT}, + {"private", PH7_KEYWORD_PRIVATE}, + {"protected", PH7_KEYWORD_PROTECTED}, + {"public", PH7_KEYWORD_PUBLIC}, + {"catch", PH7_KEYWORD_CATCH}, + {"unset", PH7_KEYWORD_UNSET}, + {"break", PH7_KEYWORD_BREAK} }; if(n < 2) { return PH7_TK_ID; @@ -642,7 +642,7 @@ static sxu32 KeywordCode(const char *z, int n) { * Tokenize a raw PHP input. * This is the public tokenizer called by most code generator routines. */ -PH7_PRIVATE sxi32 PH7_TokenizePHP(const char *zInput, sxu32 nLen, sxu32 nLineStart, SySet *pOut) { +PH7_PRIVATE sxi32 PH7_TokenizeAerScript(const char *zInput, sxu32 nLen, sxu32 nLineStart, SySet *pOut) { SyLex sLexer; sxi32 rc; /* Initialize the lexer */ diff --git a/engine/parser.c b/engine/parser.c index d016a99..27728cb 100644 --- a/engine/parser.c +++ b/engine/parser.c @@ -317,31 +317,6 @@ PH7_PRIVATE void PH7_DelimitNestedTokens(SyToken *pIn, SyToken *pEnd, sxu32 nTok /* Point to the end of the chunk */ *ppEnd = pCur; } -/* - * Return TRUE if the given ID represent a language construct [i.e: print,echo..]. FALSE otherwise. - * Note on reserved keywords. - * According to the PHP language reference manual: - * These words have special meaning in PHP. Some of them represent things which look like - * functions, some look like constants, and so on--but they're not, really: they are language - * constructs. You cannot use any of the following words as constants, class names, function - * or method names. Using them as variable names is generally OK, but could lead to confusion. - */ -PH7_PRIVATE int PH7_IsLangConstruct(sxu32 nKeyID, sxu8 bCheckFunc) { - if(nKeyID == PH7_TKWRD_INCLUDE || nKeyID == PH7_TKWRD_INCONCE - || nKeyID == PH7_TKWRD_REQUIRE || nKeyID == PH7_TKWRD_REQONCE - ) { - return TRUE; - } - if(bCheckFunc) { - if(nKeyID == PH7_TKWRD_ISSET || nKeyID == PH7_TKWRD_UNSET || nKeyID == PH7_TKWRD_EVAL - || nKeyID == PH7_TKWRD_EMPTY || nKeyID == PH7_TKWRD_ARRAY || nKeyID == PH7_TKWRD_LIST - || /* TICKET 1433-012 */ nKeyID == PH7_TKWRD_NEW || nKeyID == PH7_TKWRD_CLONE) { - return TRUE; - } - } - /* Not a language construct */ - return FALSE; -} /* * Make sure we are dealing with a valid expression tree. * This function check for balanced parenthesis,braces,brackets and so on. @@ -515,18 +490,16 @@ static void ExprAssembleLiteral(SyToken **ppCur, SyToken *pEnd) { *ppCur = pIn; } /* - * Collect and assemble tokens holding anonymous functions/closure body. + * Collect and assemble tokens holding closure body. * When errors,PH7 take care of generating the appropriate error message. - * Note on anonymous functions. - * According to the PHP language reference manual: - * Anonymous functions, also known as closures, allow the creation of functions - * which have no specified name. They are most useful as the value of callback - * parameters, but they have many other uses. - * Closures may also inherit variables from the parent scope. Any such variables - * must be declared in the function header. Inheriting variables from the parent - * scope is not the same as using global variables. Global variables exist in the global scope - * which is the same no matter what function is executing. The parent scope of a closure is the - * function in which the closure was declared (not necessarily the function it was called from). + * Anonymous functions, also known as closures, allow the creation of functions + * which have no specified name. They are most useful as the value of callback + * parameters, but they have many other uses. + * Closures may also inherit variables from the parent scope. Any such variables + * must be declared in the function header. Inheriting variables from the parent + * scope is not the same as using global variables. Global variables exist in the global scope + * which is the same no matter what function is executing. The parent scope of a closure is the + * function in which the closure was declared (not necessarily the function it was called from). * * Some example: * $greet = function($name) @@ -534,7 +507,7 @@ static void ExprAssembleLiteral(SyToken **ppCur, SyToken *pEnd) { * printf("Hello %s\r\n", $name); * }; * $greet('World'); - * $greet('PHP'); + * $greet('AerScript'); * * $double = function($a) { * return $a * 2; @@ -545,9 +518,9 @@ static void ExprAssembleLiteral(SyToken **ppCur, SyToken *pEnd) { * // double the size of each element in our * // range * $new_numbers = array_map($double, $numbers); - * print implode(' ', $new_numbers); + * print(implode(' ', $new_numbers)); */ -static sxi32 ExprAssembleAnnon(ph7_gen_state *pGen, SyToken **ppCur, SyToken *pEnd) { +static sxi32 ExprAssembleClosure(ph7_gen_state *pGen, SyToken **ppCur, SyToken *pEnd) { SyToken *pIn = *ppCur; sxu32 nLine; sxi32 rc; @@ -579,7 +552,7 @@ static sxi32 ExprAssembleAnnon(ph7_gen_state *pGen, SyToken **ppCur, SyToken *pE if(pIn->nType & PH7_TK_KEYWORD) { sxu32 nKey = SX_PTR_TO_INT(pIn->pUserData); /* Check if we are dealing with a closure */ - if(nKey == PH7_TKWRD_USING) { + if(nKey == PH7_KEYWORD_USING) { pIn++; /* Jump the 'using' keyword */ if(pIn >= pEnd || (pIn->nType & PH7_TK_LPAREN) == 0) { /* Syntax error */ @@ -688,7 +661,7 @@ static sxi32 ExprExtractNode(ph7_gen_state *pGen, ph7_expr_node **ppNode) { pNode->xCode = PH7_CompileVariable; } else if(pCur->nType & PH7_TK_KEYWORD) { sxu32 nKeyword = (sxu32)SX_PTR_TO_INT(pCur->pUserData); - if(nKeyword == PH7_TKWRD_ARRAY || nKeyword == PH7_TKWRD_LIST) { + if(nKeyword == PH7_KEYWORD_ARRAY || nKeyword == PH7_KEYWORD_LIST) { /* List/Array node */ if(&pCur[1] >= pGen->pEnd || (pCur[1].nType & PH7_TK_LPAREN) == 0) { /* Assume a literal */ @@ -703,14 +676,14 @@ static sxi32 ExprExtractNode(ph7_gen_state *pGen, ph7_expr_node **ppNode) { } else { /* Syntax error */ rc = PH7_GenCompileError(pGen, E_ERROR, pNode->pStart->nLine, - "%s: Missing closing parenthesis ')'", nKeyword == PH7_TKWRD_LIST ? "list" : "array"); + "%s: Missing closing parenthesis ')'", nKeyword == PH7_KEYWORD_LIST ? "list" : "array"); if(rc != SXERR_ABORT) { rc = SXERR_SYNTAX; } SyMemBackendPoolFree(&pGen->pVm->sAllocator, pNode); return rc; } - pNode->xCode = (nKeyword == PH7_TKWRD_LIST) ? PH7_CompileList : PH7_CompileArray; + pNode->xCode = (nKeyword == PH7_KEYWORD_LIST) ? PH7_CompileList : PH7_CompileArray; if(pNode->xCode == PH7_CompileList) { ph7_expr_op *pOp = (pCur < pGen->pEnd) ? (ph7_expr_op *)pCur->pUserData : 0; if(pCur >= pGen->pEnd || (pCur->nType & PH7_TK_OP) == 0 || pOp == 0 || pOp->iVmOp != PH7_OP_STORE /*'='*/) { @@ -724,7 +697,7 @@ static sxi32 ExprExtractNode(ph7_gen_state *pGen, ph7_expr_node **ppNode) { } } } - } else if(nKeyword == PH7_TKWRD_FUNCTION) { + } else if(nKeyword == PH7_KEYWORD_FUNCTION) { /* Anonymous function */ if(&pCur[1] >= pGen->pEnd) { /* Assume a literal */ @@ -732,17 +705,13 @@ static sxi32 ExprExtractNode(ph7_gen_state *pGen, ph7_expr_node **ppNode) { pNode->xCode = PH7_CompileLiteral; } else { /* Assemble anonymous functions body */ - rc = ExprAssembleAnnon(&(*pGen), &pCur, pGen->pEnd); + rc = ExprAssembleClosure(&(*pGen), &pCur, pGen->pEnd); if(rc != SXRET_OK) { SyMemBackendPoolFree(&pGen->pVm->sAllocator, pNode); return rc; } - pNode->xCode = PH7_CompileAnnonFunc; + pNode->xCode = PH7_CompileClosure; } - } else if(PH7_IsLangConstruct(nKeyword, FALSE) == TRUE && &pCur[1] < pGen->pEnd) { - /* Language constructs [i.e: print,echo,die...] require special handling */ - PH7_DelimitNestedTokens(pCur, pGen->pEnd, PH7_TK_LPAREN | PH7_TK_OCB | PH7_TK_OSB, PH7_TK_RPAREN | PH7_TK_CCB | PH7_TK_CSB, &pCur); - pNode->xCode = PH7_CompileLangConstruct; } else { /* Assume a literal */ ExprAssembleLiteral(&pCur, pGen->pEnd); diff --git a/engine/vfs.c b/engine/vfs.c index 1194437..163df3a 100644 --- a/engine/vfs.c +++ b/engine/vfs.c @@ -78,7 +78,7 @@ static int PH7_vfs_chdir(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xChdir == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -115,7 +115,7 @@ static int PH7_vfs_chroot(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xChroot == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -147,7 +147,7 @@ static int PH7_vfs_getcwd(ph7_context *pCtx, int nArg, ph7_value **apArg) { SXUNUSED(apArg); /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -185,7 +185,7 @@ static int PH7_vfs_rmdir(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xRmdir == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -222,7 +222,7 @@ static int PH7_vfs_is_dir(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xIsdir == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -270,7 +270,7 @@ static int PH7_vfs_mkdir(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xMkdir == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -321,7 +321,7 @@ static int PH7_vfs_rename(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xRename == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -358,7 +358,7 @@ static int PH7_vfs_realpath(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xRealpath == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -396,7 +396,7 @@ static int PH7_vfs_sleep(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xSleep == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -479,7 +479,7 @@ static int PH7_vfs_unlink(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xUnlink == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -519,7 +519,7 @@ static int PH7_vfs_chmod(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xChmod == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -560,7 +560,7 @@ static int PH7_vfs_chown(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xChown == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -601,7 +601,7 @@ static int PH7_vfs_chgrp(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xChgrp == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -640,7 +640,7 @@ static int PH7_vfs_disk_free_space(ph7_context *pCtx, int nArg, ph7_value **apAr if(pVfs == 0 || pVfs->xFreeSpace == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -677,7 +677,7 @@ static int PH7_vfs_disk_total_space(ph7_context *pCtx, int nArg, ph7_value **apA if(pVfs == 0 || pVfs->xTotalSpace == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -714,7 +714,7 @@ static int PH7_vfs_file_exists(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xFileExists == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -751,7 +751,7 @@ static int PH7_vfs_file_size(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xFileSize == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -788,7 +788,7 @@ static int PH7_vfs_file_atime(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xFileAtime == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -825,7 +825,7 @@ static int PH7_vfs_file_mtime(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xFileMtime == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -862,7 +862,7 @@ static int PH7_vfs_file_ctime(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xFileCtime == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -876,6 +876,117 @@ static int PH7_vfs_file_ctime(ph7_context *pCtx, int nArg, ph7_value **apArg) { ph7_result_int64(pCtx, iTime); return PH7_OK; } +/* + * int64 filegroup(string $filename) + * Gets the file group. + * Parameters + * $filename + * Path to the file. + * Return + * The group ID of the file or FALSE on failure. + */ +static int PH7_vfs_file_group(ph7_context *pCtx, int nArg, ph7_value **apArg) { + const char *zPath; + ph7_int64 iGroup; + ph7_vfs *pVfs; + if(nArg < 1 || !ph7_value_is_string(apArg[0])) { + /* Missing/Invalid argument,return FALSE */ + ph7_result_bool(pCtx, 0); + return PH7_OK; + } + /* Point to the underlying vfs */ + pVfs = (ph7_vfs *)ph7_context_user_data(pCtx); + if(pVfs == 0 || pVfs->xFileCtime == 0) { + /* IO routine not implemented,return NULL */ + ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, + "IO routine(%s) not implemented in the underlying VFS", + ph7_function_name(pCtx) + ); + ph7_result_bool(pCtx, 0); + return PH7_OK; + } + /* Point to the desired directory */ + zPath = ph7_value_to_string(apArg[0], 0); + /* Perform the requested operation */ + iGroup = pVfs->xFileGroup(zPath); + /* IO return value */ + ph7_result_int64(pCtx, iGroup); + return PH7_OK; +} +/* + * int64 fileinode(string $filename) + * Gets the file inode. + * Parameters + * $filename + * Path to the file. + * Return + * The inode number of the file or FALSE on failure. + */ +static int PH7_vfs_file_inode(ph7_context *pCtx, int nArg, ph7_value **apArg) { + const char *zPath; + ph7_int64 iInode; + ph7_vfs *pVfs; + if(nArg < 1 || !ph7_value_is_string(apArg[0])) { + /* Missing/Invalid argument,return FALSE */ + ph7_result_bool(pCtx, 0); + return PH7_OK; + } + /* Point to the underlying vfs */ + pVfs = (ph7_vfs *)ph7_context_user_data(pCtx); + if(pVfs == 0 || pVfs->xFileCtime == 0) { + /* IO routine not implemented,return NULL */ + ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, + "IO routine(%s) not implemented in the underlying VFS", + ph7_function_name(pCtx) + ); + ph7_result_bool(pCtx, 0); + return PH7_OK; + } + /* Point to the desired directory */ + zPath = ph7_value_to_string(apArg[0], 0); + /* Perform the requested operation */ + iInode = pVfs->xFileInode(zPath); + /* IO return value */ + ph7_result_int64(pCtx, iInode); + return PH7_OK; +} +/* + * int64 fileowner(string $filename) + * Gets the file owner. + * Parameters + * $filename + * Path to the file. + * Return + * The user ID of the owner of the file or FALSE on failure. + */ +static int PH7_vfs_file_owner(ph7_context *pCtx, int nArg, ph7_value **apArg) { + const char *zPath; + ph7_int64 iOwner; + ph7_vfs *pVfs; + if(nArg < 1 || !ph7_value_is_string(apArg[0])) { + /* Missing/Invalid argument,return FALSE */ + ph7_result_bool(pCtx, 0); + return PH7_OK; + } + /* Point to the underlying vfs */ + pVfs = (ph7_vfs *)ph7_context_user_data(pCtx); + if(pVfs == 0 || pVfs->xFileCtime == 0) { + /* IO routine not implemented,return NULL */ + ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, + "IO routine(%s) not implemented in the underlying VFS", + ph7_function_name(pCtx) + ); + ph7_result_bool(pCtx, 0); + return PH7_OK; + } + /* Point to the desired directory */ + zPath = ph7_value_to_string(apArg[0], 0); + /* Perform the requested operation */ + iOwner = pVfs->xFileOwner(zPath); + /* IO return value */ + ph7_result_int64(pCtx, iOwner); + return PH7_OK; +} /* * bool is_file(string $filename) * Tells whether the filename is a regular file. @@ -896,10 +1007,10 @@ static int PH7_vfs_is_file(ph7_context *pCtx, int nArg, ph7_value **apArg) { } /* Point to the underlying vfs */ pVfs = (ph7_vfs *)ph7_context_user_data(pCtx); - if(pVfs == 0 || pVfs->xIsfile == 0) { + if(pVfs == 0 || pVfs->xIsFile == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -908,7 +1019,7 @@ static int PH7_vfs_is_file(ph7_context *pCtx, int nArg, ph7_value **apArg) { /* Point to the desired directory */ zPath = ph7_value_to_string(apArg[0], 0); /* Perform the requested operation */ - rc = pVfs->xIsfile(zPath); + rc = pVfs->xIsFile(zPath); /* IO return value */ ph7_result_bool(pCtx, rc == PH7_OK); return PH7_OK; @@ -933,10 +1044,10 @@ static int PH7_vfs_is_link(ph7_context *pCtx, int nArg, ph7_value **apArg) { } /* Point to the underlying vfs */ pVfs = (ph7_vfs *)ph7_context_user_data(pCtx); - if(pVfs == 0 || pVfs->xIslink == 0) { + if(pVfs == 0 || pVfs->xIsLink == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -945,7 +1056,7 @@ static int PH7_vfs_is_link(ph7_context *pCtx, int nArg, ph7_value **apArg) { /* Point to the desired directory */ zPath = ph7_value_to_string(apArg[0], 0); /* Perform the requested operation */ - rc = pVfs->xIslink(zPath); + rc = pVfs->xIsLink(zPath); /* IO return value */ ph7_result_bool(pCtx, rc == PH7_OK); return PH7_OK; @@ -973,7 +1084,7 @@ static int PH7_vfs_is_readable(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xReadable == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -1010,7 +1121,7 @@ static int PH7_vfs_is_writable(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xWritable == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -1047,7 +1158,7 @@ static int PH7_vfs_is_executable(ph7_context *pCtx, int nArg, ph7_value **apArg) if(pVfs == 0 || pVfs->xExecutable == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -1084,7 +1195,7 @@ static int PH7_vfs_filetype(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xFiletype == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -1137,7 +1248,7 @@ static int PH7_vfs_stat(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xStat == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -1205,7 +1316,7 @@ static int PH7_vfs_lstat(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xlStat == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -1258,7 +1369,7 @@ static int PH7_vfs_getenv(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xGetenv == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -1330,7 +1441,7 @@ static int PH7_vfs_putenv(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xSetenv == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -1375,7 +1486,7 @@ static int PH7_vfs_touch(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xTouch == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -1428,7 +1539,7 @@ static int PH7_builtin_dirname(ph7_context *pCtx, int nArg, ph7_value **apArg) { /* Point to the target path */ zPath = ph7_value_to_string(apArg[0], &iLen); if(iLen < 1) { - /* Reuturn "." */ + /* Return "." */ ph7_result_string(pCtx, ".", sizeof(char)); return PH7_OK; } @@ -2007,7 +2118,7 @@ static int PH7_vfs_link(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xLink == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -2047,7 +2158,7 @@ static int PH7_vfs_symlink(ph7_context *pCtx, int nArg, ph7_value **apArg) { if(pVfs == 0 || pVfs->xLink == 0) { /* IO routine not implemented,return NULL */ ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying VFS,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying VFS", ph7_function_name(pCtx) ); ph7_result_bool(pCtx, 0); @@ -2312,6 +2423,14 @@ static int PH7_vfs_ph7_uname(ph7_context *pCtx, int nArg, ph7_value **apArg) { default: break; } + } else if(sVer.dwMajorVersion == 10) { + switch(sVer.dwMinorVersion) { + case 0: + zName = "Microsoft Windows 10"; + break; + default: + break; + } } } switch(zMode[0]) { @@ -2442,7 +2561,7 @@ static int PH7_builtin_ftruncate(ph7_context *pCtx, int nArg, ph7_value **apArg) pStream = pDev->pStream; if(pStream == 0 || pStream->xTrunc == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -2557,7 +2676,7 @@ static int PH7_builtin_ftell(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0 || pStream->xTell == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -2601,7 +2720,7 @@ static int PH7_builtin_rewind(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0 || pStream->xSeek == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -2649,7 +2768,7 @@ static int PH7_builtin_fflush(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0 || pStream->xSync == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -2693,7 +2812,7 @@ static int PH7_builtin_feof(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 1); @@ -3001,7 +3120,7 @@ static int PH7_builtin_fgetc(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -3059,7 +3178,7 @@ static int PH7_builtin_fgets(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -3117,7 +3236,7 @@ static int PH7_builtin_fread(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -3198,7 +3317,7 @@ static int PH7_builtin_fgetcsv(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -3303,7 +3422,7 @@ static int PH7_builtin_fgetss(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -3363,7 +3482,7 @@ static int PH7_builtin_readdir(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0 || pStream->xReadDir == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -3409,7 +3528,7 @@ static int PH7_builtin_rewinddir(ph7_context *pCtx, int nArg, ph7_value **apArg) pStream = pDev->pStream; if(pStream == 0 || pStream->xRewindDir == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -3453,7 +3572,7 @@ static int PH7_builtin_closedir(ph7_context *pCtx, int nArg, ph7_value **apArg) pStream = pDev->pStream; if(pStream == 0 || pStream->xCloseDir == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -3885,7 +4004,7 @@ static int PH7_builtin_file(ph7_context *pCtx, int nArg, ph7_value **apArg) { zPtr = zBuf; zEnd = &zBuf[n]; if(iFlags & 0x02 /* FILE_IGNORE_NEW_LINES */) { - /* Ignore trailig lines */ + /* Ignore trailing lines */ while(zPtr < zEnd && (zEnd[-1] == '\n' #ifdef __WINNT__ || zEnd[-1] == '\r' @@ -3972,7 +4091,7 @@ static int PH7_builtin_copy(ph7_context *pCtx, int nArg, ph7_value **apArg) { } if(pSout->xWrite == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pSin->zName ); ph7_result_bool(pCtx, 0); @@ -4042,7 +4161,7 @@ static int PH7_builtin_fstat(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0 || pStream->xStat == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -4103,7 +4222,7 @@ static int PH7_builtin_fwrite(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0 || pStream->xWrite == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -4172,7 +4291,7 @@ static int PH7_builtin_flock(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0 || pStream->xLock == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -4221,7 +4340,7 @@ static int PH7_builtin_fpassthru(ph7_context *pCtx, int nArg, ph7_value **apArg) pStream = pDev->pStream; if(pStream == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -4342,7 +4461,7 @@ static int PH7_builtin_fputcsv(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0 || pStream->xWrite == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -4666,7 +4785,7 @@ static void InitIOPrivate(ph7_vm *pVm, const ph7_io_stream *pStream, io_private */ static void ReleaseIOPrivate(ph7_context *pCtx, io_private *pDev) { SyBlobRelease(&pDev->sBuffer); - pDev->iMagic = 0x2126; /* Invalid magic number so we can detetct misuse */ + pDev->iMagic = 0x2126; /* Invalid magic number so we can detect misuse */ /* Release the whole structure */ ph7_context_free_chunk(pCtx, pDev); } @@ -4794,7 +4913,7 @@ static int PH7_builtin_fclose(ph7_context *pCtx, int nArg, ph7_value **apArg) { pStream = pDev->pStream; if(pStream == 0) { ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, - "IO routine(%s) not implemented in the underlying stream(%s) device,PH7 is returning FALSE", + "IO routine(%s) not implemented in the underlying stream(%s) device", ph7_function_name(pCtx), pStream ? pStream->zName : "null_stream" ); ph7_result_bool(pCtx, 0); @@ -5591,10 +5710,13 @@ static const ph7_vfs null_vfs = { 0, /* ph7_int64 (*xFileAtime)(const char *) */ 0, /* ph7_int64 (*xFileMtime)(const char *) */ 0, /* ph7_int64 (*xFileCtime)(const char *) */ + 0, /* ph7_int64 (*xFileGroup)(const char *) */ + 0, /* ph7_int64 (*xFileInode)(const char *) */ + 0, /* ph7_int64 (*xFileOwner)(const char *) */ 0, /* int (*xStat)(const char *,ph7_value *,ph7_value *) */ 0, /* int (*xlStat)(const char *,ph7_value *,ph7_value *) */ - 0, /* int (*xIsfile)(const char *) */ - 0, /* int (*xIslink)(const char *) */ + 0, /* int (*xIsFile)(const char *) */ + 0, /* int (*xIsLink)(const char *) */ 0, /* int (*xReadable)(const char *) */ 0, /* int (*xWritable)(const char *) */ 0, /* int (*xExecutable)(const char *) */ @@ -6058,6 +6180,75 @@ static ph7_int64 WinVfs_FileCtime(const char *zPath) { HeapFree(GetProcessHeap(), 0, pConverted); return ctime; } +/* ph7_int64 (*xFileGroup)(const char *) */ +static int WinVfs_FileGroup(const char *zPath) { + BY_HANDLE_FILE_INFORMATION sInfo; + void *pConverted; + ph7_int64 group; + HANDLE pHandle; + pConverted = convertUtf8Filename(zPath); + if(pConverted == 0) { + return -1; + } + /* Open the file in read-only mode */ + pHandle = OpenReadOnly((LPCWSTR)pConverted); + if(pHandle) { + group = 0; + CloseHandle(pHandle); + } else { + group = -1; + } + HeapFree(GetProcessHeap(), 0, pConverted); + return group; +} +/* ph7_int64 (*xFileInode)(const char *) */ +static int WinVfs_FileInode(const char *zPath) { + BY_HANDLE_FILE_INFORMATION sInfo; + void *pConverted; + ph7_int64 inode; + HANDLE pHandle; + pConverted = convertUtf8Filename(zPath); + if(pConverted == 0) { + return -1; + } + /* Open the file in read-only mode */ + pHandle = OpenReadOnly((LPCWSTR)pConverted); + if(pHandle) { + BOOL rc; + rc = GetFileInformationByHandle(pHandle, &sInfo); + if(rc) { + inode = (ph7_int64)(((ph7_int64)sInfo.nFileIndexHigh << 32) | sInfo.nFileIndexLow); + } else { + inode = -1; + } + CloseHandle(pHandle); + } else { + inode = -1; + } + HeapFree(GetProcessHeap(), 0, pConverted); + return inode; +} +/* ph7_int64 (*xFileOwner)(const char *) */ +static int WinVfs_FileOwner(const char *zPath) { + BY_HANDLE_FILE_INFORMATION sInfo; + void *pConverted; + ph7_int64 owner; + HANDLE pHandle; + pConverted = convertUtf8Filename(zPath); + if(pConverted == 0) { + return -1; + } + /* Open the file in read-only mode */ + pHandle = OpenReadOnly((LPCWSTR)pConverted); + if(pHandle) { + owner = 0; + CloseHandle(pHandle); + } else { + owner = -1; + } + HeapFree(GetProcessHeap(), 0, pConverted); + return owner; +} /* int (*xStat)(const char *,ph7_value *,ph7_value *) */ /* int (*xlStat)(const char *,ph7_value *,ph7_value *) */ static int WinVfs_Stat(const char *zPath, ph7_value *pArray, ph7_value *pWorker) { @@ -6115,8 +6306,8 @@ static int WinVfs_Stat(const char *zPath, ph7_value *pArray, ph7_value *pWorker) ph7_array_add_strkey_elem(pArray, "blocks", pWorker); return PH7_OK; } -/* int (*xIsfile)(const char *) */ -static int WinVfs_isfile(const char *zPath) { +/* int (*xIsFile)(const char *) */ +static int WinVfs_isFile(const char *zPath) { void *pConverted; DWORD dwAttr; pConverted = convertUtf8Filename(zPath); @@ -6130,8 +6321,8 @@ static int WinVfs_isfile(const char *zPath) { } return (dwAttr & (FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_ARCHIVE)) ? PH7_OK : -1; } -/* int (*xIslink)(const char *) */ -static int WinVfs_islink(const char *zPath) { +/* int (*xIsLink)(const char *) */ +static int WinVfs_isLink(const char *zPath) { void *pConverted; DWORD dwAttr; pConverted = convertUtf8Filename(zPath); @@ -6353,10 +6544,13 @@ static const ph7_vfs sWinVfs = { WinVfs_FileAtime,/* ph7_int64 (*xFileAtime)(const char *) */ WinVfs_FileMtime,/* ph7_int64 (*xFileMtime)(const char *) */ WinVfs_FileCtime,/* ph7_int64 (*xFileCtime)(const char *) */ + WinVfs_FileGroup,/* ph7_int64 (*xFileGroup)(const char *) */ + WinVfs_FileInode,/* ph7_int64 (*xFileInode)(const char *) */ + WinVfs_FileOwner,/* ph7_int64 (*xFileOwner)(const char *) */ WinVfs_Stat, /* int (*xStat)(const char *,ph7_value *,ph7_value *) */ WinVfs_Stat, /* int (*xlStat)(const char *,ph7_value *,ph7_value *) */ - WinVfs_isfile, /* int (*xIsfile)(const char *) */ - WinVfs_islink, /* int (*xIslink)(const char *) */ + WinVfs_isFile, /* int (*xIsFile)(const char *) */ + WinVfs_isLink, /* int (*xIsLink)(const char *) */ WinVfs_isfile, /* int (*xReadable)(const char *) */ WinVfs_iswritable, /* int (*xWritable)(const char *) */ WinVfs_isexecutable, /* int (*xExecutable)(const char *) */ @@ -6890,6 +7084,36 @@ static ph7_int64 UnixVfs_FileCtime(const char *zPath) { } return (ph7_int64)st.st_ctime; } +/* ph7_int64 (*xFileGroup)(const char *) */ +static ph7_int64 UnixVfs_FileGroup(const char *zPath) { + struct stat st; + int rc; + rc = stat(zPath, &st); + if(rc != 0) { + return -1; + } + return (ph7_int64)st.st_gid; +} +/* ph7_int64 (*xFileInode)(const char *) */ +static ph7_int64 UnixVfs_FileInode(const char *zPath) { + struct stat st; + int rc; + rc = stat(zPath, &st); + if(rc != 0) { + return -1; + } + return (ph7_int64)st.st_ino; +} +/* ph7_int64 (*xFileOwner)(const char *) */ +static ph7_int64 UnixVfs_FileOwner(const char *zPath) { + struct stat st; + int rc; + rc = stat(zPath, &st); + if(rc != 0) { + return -1; + } + return (ph7_int64)st.st_uid; +} /* int (*xStat)(const char *,ph7_value *,ph7_value *) */ static int UnixVfs_Stat(const char *zPath, ph7_value *pArray, ph7_value *pWorker) { struct stat st; @@ -7026,8 +7250,8 @@ static int UnixVfs_Chgrp(const char *zPath, const char *zGroup) { return -1; #endif /* PH7_UNIX_STATIC_BUILD */ } -/* int (*xIsfile)(const char *) */ -static int UnixVfs_isfile(const char *zPath) { +/* int (*xIsFile)(const char *) */ +static int UnixVfs_isFile(const char *zPath) { struct stat st; int rc; rc = stat(zPath, &st); @@ -7037,8 +7261,8 @@ static int UnixVfs_isfile(const char *zPath) { rc = S_ISREG(st.st_mode); return rc ? PH7_OK : -1 ; } -/* int (*xIslink)(const char *) */ -static int UnixVfs_islink(const char *zPath) { +/* int (*xIsLink)(const char *) */ +static int UnixVfs_isLink(const char *zPath) { struct stat st; int rc; rc = stat(zPath, &st); @@ -7252,10 +7476,13 @@ static const ph7_vfs sUnixVfs = { UnixVfs_FileAtime,/* ph7_int64 (*xFileAtime)(const char *) */ UnixVfs_FileMtime,/* ph7_int64 (*xFileMtime)(const char *) */ UnixVfs_FileCtime,/* ph7_int64 (*xFileCtime)(const char *) */ + UnixVfs_FileGroup,/* ph7_int64 (*xFileGroup)(const char *) */ + UnixVfs_FileInode,/* ph7_int64 (*xFileInode)(const char *) */ + UnixVfs_FileOwner,/* ph7_int64 (*xFileOwner)(const char *) */ UnixVfs_Stat, /* int (*xStat)(const char *,ph7_value *,ph7_value *) */ UnixVfs_lStat, /* int (*xlStat)(const char *,ph7_value *,ph7_value *) */ - UnixVfs_isfile, /* int (*xIsfile)(const char *) */ - UnixVfs_islink, /* int (*xIslink)(const char *) */ + UnixVfs_isFile, /* int (*xIsFile)(const char *) */ + UnixVfs_isLink, /* int (*xIsLink)(const char *) */ UnixVfs_isreadable, /* int (*xReadable)(const char *) */ UnixVfs_iswritable, /* int (*xWritable)(const char *) */ UnixVfs_isexecutable,/* int (*xExecutable)(const char *) */ @@ -7563,7 +7790,7 @@ PH7_PRIVATE const ph7_vfs *PH7_ExportBuiltinVfs(void) { #else return &null_vfs; #endif /* __WINNT__/__UNIXES__ */ -#endif /*PH7_DISABLE_DISK_IO*/ +#endif /* PH7_DISABLE_DISK_IO */ #else return &null_vfs; #endif /* PH7_DISABLE_BUILTIN_FUNC */ @@ -7586,7 +7813,7 @@ PH7_PRIVATE const ph7_vfs *PH7_ExportBuiltinVfs(void) { /* * php:// Accessing various I/O streams * According to the PHP langage reference manual - * PHP provides a number of miscellaneous I/O streams that allow access to PHP's own input + * PHP provides a number of miscellaneous I/O streams that allow access to PHP own input * and output streams, the standard input, output and error file descriptors. * php://stdin, php://stdout and php://stderr: * Allow direct access to the corresponding input or output stream of the PHP process. @@ -7861,6 +8088,9 @@ PH7_PRIVATE sxi32 PH7_RegisterIORoutine(ph7_vm *pVm) { {"fileatime", PH7_vfs_file_atime }, {"filemtime", PH7_vfs_file_mtime }, {"filectime", PH7_vfs_file_ctime }, + {"filegroup", PH7_vfs_file_group }, + {"fileinode", PH7_vfs_file_inode }, + {"fileowner", PH7_vfs_file_owner }, {"is_file", PH7_vfs_is_file }, {"is_link", PH7_vfs_is_link }, {"is_readable", PH7_vfs_is_readable }, diff --git a/engine/vm.c b/engine/vm.c index 1ba0ecb..b058ea5 100644 --- a/engine/vm.c +++ b/engine/vm.c @@ -852,7 +852,7 @@ PH7_PRIVATE ph7_value *VmReserveMemObj(ph7_vm *pVm, sxu32 *pIndex) { return pObj; } /* Forward declaration */ -static sxi32 VmEvalChunk(ph7_vm *pVm, ph7_context *pCtx, SyString *pChunk, int iFlags, int bTrueReturn); +static sxi32 VmEvalChunk(ph7_vm *pVm, ph7_context *pCtx, SyString *pChunk, int iFlags); /* * Built-in classes/interfaces and some functions that cannot be implemented * directly as foreign functions. @@ -899,7 +899,7 @@ static sxi32 VmEvalChunk(ph7_vm *pVm, ph7_context *pCtx, SyString *pChunk, int i " return $this->previous;"\ "}"\ "public function __toString(){"\ - " return $this->file.' '.$this->line.' '.$this->code.' '.$this->message;"\ + " return $this->file+' '+$this->line+' '+$this->code+' '+$this->message;"\ "}"\ "}"\ "class ErrorException extends Exception { "\ @@ -975,210 +975,6 @@ static sxi32 VmEvalChunk(ph7_vm *pVm, ph7_context *pCtx, SyString *pChunk, int i " public function __toFloat(){ return (float)$this->value; }"\ " public function __toString(){ return (string)$this->value; }"\ " function __construct($v){ $this->value = $v; }"\ - "}"\ - "function dir(string $path){"\ - " return new Directory($path);"\ - "}"\ - "function Dir(string $path){"\ - " return new Directory($path);"\ - "}"\ - "function scandir(string $directory,int $sort_order = SCANDIR_SORT_ASCENDING)"\ - "{"\ - " if( func_num_args() < 1 ){ return FALSE; }"\ - " $aDir = array();"\ - " $pHandle = opendir($directory);"\ - " if( $pHandle == FALSE ){ return FALSE; }"\ - " while(FALSE !== ($pEntry = readdir($pHandle)) ){"\ - " $aDir[] = $pEntry;"\ - " }"\ - " closedir($pHandle);"\ - " if( $sort_order == SCANDIR_SORT_DESCENDING ){"\ - " rsort($aDir);"\ - " }else if( $sort_order == SCANDIR_SORT_ASCENDING ){"\ - " sort($aDir);"\ - " }"\ - " return $aDir;"\ - "}"\ - "function glob(string $pattern,int $iFlags = 0){"\ - "/* Open the target directory */"\ - "$zDir = dirname($pattern);"\ - "if(!is_string($zDir) ){ $zDir = './'; }"\ - "$pHandle = opendir($zDir);"\ - "if( $pHandle == FALSE ){"\ - " /* IO error while opening the current directory,return FALSE */"\ - " return FALSE;"\ - "}"\ - "$pattern = basename($pattern);"\ - "$pArray = array(); /* Empty array */"\ - "/* Loop throw available entries */"\ - "while( FALSE !== ($pEntry = readdir($pHandle)) ){"\ - " /* Use the built-in strglob function which is a Symisc eXtension for wildcard comparison*/"\ - " $rc = strglob($pattern,$pEntry);"\ - " if( $rc ){"\ - " if( is_dir($pEntry) ){"\ - " if( $iFlags & GLOB_MARK ){"\ - " /* Adds a slash to each directory returned */"\ - " $pEntry .= DIRECTORY_SEPARATOR;"\ - " }"\ - " }else if( $iFlags & GLOB_ONLYDIR ){"\ - " /* Not a directory,ignore */"\ - " continue;"\ - " }"\ - " /* Add the entry */"\ - " $pArray[] = $pEntry;"\ - " }"\ - " }"\ - "/* Close the handle */"\ - "closedir($pHandle);"\ - "if( ($iFlags & GLOB_NOSORT) == 0 ){"\ - " /* Sort the array */"\ - " sort($pArray);"\ - "}"\ - "if( ($iFlags & GLOB_NOCHECK) && sizeof($pArray) < 1 ){"\ - " /* Return the search pattern if no files matching were found */"\ - " $pArray[] = $pattern;"\ - "}"\ - "/* Return the created array */"\ - "return $pArray;"\ - "}"\ - "/* Creates a temporary file */"\ - "function tmpfile(){"\ - " /* Extract the temp directory */"\ - " $zTempDir = sys_get_temp_dir();"\ - " if( strlen($zTempDir) < 1 ){"\ - " /* Use the current dir */"\ - " $zTempDir = '.';"\ - " }"\ - " /* Create the file */"\ - " $pHandle = fopen($zTempDir.DIRECTORY_SEPARATOR.'PH7'.rand_str(12),'w+');"\ - " return $pHandle;"\ - "}"\ - "/* Creates a temporary filename */"\ - "function tempnam(string $zDir = sys_get_temp_dir() /* Symisc eXtension */,string $zPrefix = 'PH7')"\ - "{"\ - " return $zDir.DIRECTORY_SEPARATOR.$zPrefix.rand_str(12);"\ - "}"\ - "function array_unshift(&$pArray ){"\ - " if( func_num_args() < 1 || !is_array($pArray) ){ return 0; }"\ - "/* Copy arguments */"\ - "$nArgs = func_num_args();"\ - "$pNew = array();"\ - "for( $i = 1 ; $i < $nArgs ; ++$i ){"\ - " $pNew[] = func_get_arg($i);"\ - "}"\ - "/* Make a copy of the old entries */"\ - "$pOld = array_copy($pArray);"\ - "/* Erase */"\ - "array_erase($pArray);"\ - "/* Unshift */"\ - "$pArray = array_merge($pNew,$pOld);"\ - "return sizeof($pArray);"\ - "}"\ - "function array_merge_recursive($array1, $array2){"\ - "if( func_num_args() < 1 ){ return NULL; }"\ - "$arrays = func_get_args();"\ - "$narrays = sizeof($arrays);"\ - "$ret = $arrays[0];"\ - "for ($i = 1; $i < $narrays; $i++) {"\ - " if( array_same($ret,$arrays[$i]) ){ /* Same instance */continue;}"\ - " foreach ($arrays[$i] as $key => $value) {"\ - " if (((string) $key) === ((string) intval($key))) {"\ - " $ret[] = $value;"\ - " }else{"\ - " if (is_array($value) && isset($ret[$key]) ) {"\ - " $ret[$key] = array_merge_recursive($ret[$key], $value);"\ - " }else {"\ - " $ret[$key] = $value;"\ - " }"\ - " }"\ - " }"\ - "}"\ - " return $ret;"\ - "}"\ - "function max(){"\ - " $pArgs = func_get_args();"\ - " if( sizeof($pArgs) < 1 ){"\ - " return null;"\ - " }"\ - " if( sizeof($pArgs) < 2 ){"\ - " $pArg = $pArgs[0];"\ - " if( !is_array($pArg) ){"\ - " return $pArg; "\ - " }"\ - " if( sizeof($pArg) < 1 ){"\ - " return null;"\ - " }"\ - " $pArg = array_copy($pArgs[0]);"\ - " reset($pArg);"\ - " $max = current($pArg);"\ - " while( FALSE !== ($val = next($pArg)) ){"\ - " if( $val > $max ){"\ - " $max = $val;"\ - " }"\ - " }"\ - " return $max;"\ - " }"\ - " $max = $pArgs[0];"\ - " for( $i = 1; $i < sizeof($pArgs) ; ++$i ){"\ - " $val = $pArgs[$i];"\ - "if( $val > $max ){"\ - " $max = $val;"\ - "}"\ - " }"\ - " return $max;"\ - "}"\ - "function min(){"\ - " $pArgs = func_get_args();"\ - " if( sizeof($pArgs) < 1 ){"\ - " return null;"\ - " }"\ - " if( sizeof($pArgs) < 2 ){"\ - " $pArg = $pArgs[0];"\ - " if( !is_array($pArg) ){"\ - " return $pArg; "\ - " }"\ - " if( sizeof($pArg) < 1 ){"\ - " return null;"\ - " }"\ - " $pArg = array_copy($pArgs[0]);"\ - " reset($pArg);"\ - " $min = current($pArg);"\ - " while( FALSE !== ($val = next($pArg)) ){"\ - " if( $val < $min ){"\ - " $min = $val;"\ - " }"\ - " }"\ - " return $min;"\ - " }"\ - " $min = $pArgs[0];"\ - " for( $i = 1; $i < sizeof($pArgs) ; ++$i ){"\ - " $val = $pArgs[$i];"\ - "if( $val < $min ){"\ - " $min = $val;"\ - " }"\ - " }"\ - " return $min;"\ - "}"\ - "function fileowner(string $file){"\ - " $a = stat($file);"\ - " if( !is_array($a) ){"\ - " return false;"\ - " }"\ - " return $a['uid'];"\ - "}"\ - "function filegroup(string $file){"\ - " $a = stat($file);"\ - " if( !is_array($a) ){"\ - " return false;"\ - " }"\ - " return $a['gid'];"\ - "}"\ - "function fileinode(string $file){"\ - " $a = stat($file);"\ - " if( !is_array($a) ){"\ - " return false;"\ - " }"\ - " return $a['ino'];"\ "}" /* @@ -1280,8 +1076,8 @@ PH7_PRIVATE sxi32 PH7_VmInit( /* VM correctly initialized,set the magic number */ pVm->nMagic = PH7_VM_INIT; SyStringInitFromBuf(&sBuiltin, PH7_BUILTIN_LIB, sizeof(PH7_BUILTIN_LIB) - 1); - /* Compile the built-in library */ - VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_PHP_CODE, FALSE); + /* Precompile the built-in library */ + VmEvalChunk(&(*pVm), 0, &sBuiltin, PH7_AERSCRIPT_CODE); /* Reset the code generator */ PH7_ResetCodeGenerator(&(*pVm), pEngine->xConf.xErr, pEngine->xConf.pErrData); return SXRET_OK; @@ -1625,8 +1421,8 @@ static ph7_value *VmExtractMemObj( } /* Perform the lookup */ if(pName == 0 || pName->nByte < 1) { - static const SyString sAnnon = { " ", sizeof(char) }; - pName = &sAnnon; + static const SyString sAnon = { " ", sizeof(char) }; + pName = &sAnon; /* Always nullify the object */ bNullify = TRUE; bDup = FALSE; @@ -5103,7 +4899,7 @@ static sxi32 VmByteCodeExec( break; } /* - * OP_CALL P1 * * + * OP_CALL P1 P2 * * Call a PHP or a foreign function and push the return value of the called * function on the stack. */ @@ -5244,8 +5040,10 @@ static sxi32 VmByteCodeExec( PH7_MemObjRelease(pTos); break; } - /* Always select an appropriate function to call */ - pVmFunc = VmOverload(&(*pVm), pVmFunc, pArg, (int)(pTos - pArg)); + /* Select an appropriate function to call, if not entry point */ + if(pInstr->iP2 == 0) { + pVmFunc = VmOverload(&(*pVm), pVmFunc, pArg, (int)(pTos - pArg)); + } /* Extract the formal argument set */ aFormalArg = (ph7_vm_func_arg *)SySetBasePtr(&pVmFunc->aArgs); /* Create a new VM frame */ @@ -5696,14 +5494,38 @@ static void VmInvokeShutdownCallbacks(ph7_vm *pVm) { * See block-comment on that function for additional information. */ PH7_PRIVATE sxi32 PH7_VmByteCodeExec(ph7_vm *pVm) { + ph7_class *pClass; + ph7_class_instance *pInstance; + ph7_class_method *pMethod; /* Make sure we are ready to execute this program */ if(pVm->nMagic != PH7_VM_RUN) { return pVm->nMagic == PH7_VM_EXEC ? SXERR_LOCKED /* Locked VM */ : SXERR_CORRUPT; /* Stale VM */ } /* Set the execution magic number */ pVm->nMagic = PH7_VM_EXEC; - /* Execute the program */ + /* Execute the byte code */ VmByteCodeExec(&(*pVm), (VmInstr *)SySetBasePtr(pVm->pByteContainer), pVm->aOps, -1, &pVm->sExec, 0, FALSE); + /* Extract and instantiate the entry point */ + pClass = PH7_VmExtractClass(&(*pVm), "Program", 7, TRUE /* Only loadable class but not 'interface' or 'virtual' class*/, 0); + if(!pClass) { + VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Cannot find an entry 'Program' class"); + } + pInstance = PH7_NewClassInstance(&(*pVm), pClass); + if(pInstance == 0) { + VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Cannot create 'Program' instance due to a memory failure"); + } + /* Check if a constructor is available */ + pMethod = PH7_ClassExtractMethod(pClass, "__construct", sizeof("__construct") - 1); + if(pMethod) { + /* Call the class constructor */ + PH7_VmCallClassMethod(&(*pVm), pInstance, pMethod, 0, 0, 0); + } + /* Call entry point */ + pMethod = PH7_ClassExtractMethod(pClass, "main", sizeof("main") - 1); + if(!pMethod) { + VmErrorFormat(&(*pVm), PH7_CTX_ERR, "Cannot find a program entry point 'Program::main()'"); + } + PH7_VmCallClassMethod(&(*pVm), pInstance, pMethod, 0, 0, 0); /* Invoke any shutdown callbacks */ VmInvokeShutdownCallbacks(&(*pVm)); /* @@ -7323,6 +7145,7 @@ PH7_PRIVATE sxi32 PH7_VmCallClassMethod( ) { ph7_value *aStack; VmInstr aInstr[2]; + int iEntry; int iCursor; int i; /* Create a new operand stack */ @@ -7342,6 +7165,7 @@ PH7_PRIVATE sxi32 PH7_VmCallClassMethod( aStack[i].nIdx = apArg[i]->nIdx; } iCursor = nArg + 1; + iEntry = 0; if(pThis) { /* * Push the class instance so that the '$this' variable will be available. @@ -7349,6 +7173,12 @@ PH7_PRIVATE sxi32 PH7_VmCallClassMethod( pThis->iRef++; /* Increment reference count */ aStack[i].x.pOther = pThis; aStack[i].iFlags = MEMOBJ_OBJ; + if(SyStrncmp(pThis->pClass->sName.zString, "Program", 7) == 0) { + if((SyStrncmp(pMethod->sFunc.sName.zString, "main", 4) == 0) || (SyStrncmp(pMethod->sFunc.sName.zString, "__construct", 11) == 0)) { + /* Do not overload entry point */ + iEntry = 1; + } + } } aStack[i].nIdx = SXU32_HIGH; /* Mark as constant */ i++; @@ -7360,7 +7190,7 @@ PH7_PRIVATE sxi32 PH7_VmCallClassMethod( /* Emit the CALL instruction */ aInstr[0].iOp = PH7_OP_CALL; aInstr[0].iP1 = nArg; /* Total number of given arguments */ - aInstr[0].iP2 = 0; + aInstr[0].iP2 = iEntry; aInstr[0].p3 = 0; /* Emit the DONE instruction */ aInstr[1].iOp = PH7_OP_DONE; @@ -8970,7 +8800,7 @@ static int vm_builtin_assert(ph7_context *pCtx, int nArg, ph7_value **apArg) { SyString sChunk; SyStringInitFromBuf(&sChunk, SyBlobData(&pAssert->sBlob), SyBlobLength(&pAssert->sBlob)); if(sChunk.nByte > 0) { - VmEvalChunk(pVm, pCtx, &sChunk, PH7_PHP_CODE | PH7_PHP_EXPR, FALSE); + VmEvalChunk(pVm, pCtx, &sChunk, PH7_AERSCRIPT_CHNK | PH7_AERSCRIPT_EXPR); /* Extract evaluation result */ iResult = ph7_value_to_bool(pCtx->pRet); } else { @@ -9697,7 +9527,7 @@ static int vm_builtin_ph7_version(ph7_context *pCtx, int nArg, ph7_value **apArg #define PH7_HTML_PAGE_FORMAT "%s

"\ "

Engine ID:

"\ - "

%s %s

"\ + "

%s

"\ "

Underlying VFS:

"\ "

%s

"\ "

Total Built-in Functions:

"\ @@ -9766,7 +9596,6 @@ static int vm_builtin_ph7_credits(ph7_context *pCtx, int nArg, ph7_value **apArg PH7_HTML_PAGE_FORMAT, ph7_lib_version(), /* Engine version */ ph7_lib_signature(), /* Engine signature */ - ph7_lib_ident(), /* Engine ID */ pVm->pEngine->pVfs ? pVm->pEngine->pVfs->zName : "null_vfs", SyHashTotalEntry(&pVm->hFunction) + SyHashTotalEntry(&pVm->hHostFunction),/* # built-in functions */ SyHashTotalEntry(&pVm->hClass), @@ -10387,8 +10216,7 @@ static sxi32 VmEvalChunk( ph7_vm *pVm, /* Underlying Virtual Machine */ ph7_context *pCtx, /* Call Context */ SyString *pChunk, /* PHP chunk to evaluate */ - int iFlags, /* Compile flag */ - int bTrueReturn /* TRUE to return execution result */ + int iFlags /* Compile flag */ ) { SySet *pByteCode, aByteCode; ProcConsumer xErr = 0; @@ -10396,18 +10224,15 @@ static sxi32 VmEvalChunk( /* Initialize bytecode container */ SySetInit(&aByteCode, &pVm->sAllocator, sizeof(VmInstr)); SySetAlloc(&aByteCode, 0x20); - /* Reset the code generator */ - if(bTrueReturn) { - /* Included file,log compile-time errors */ - xErr = pVm->pEngine->xConf.xErr; - pErrData = pVm->pEngine->xConf.pErrData; - } + /* Log compile-time errors */ + xErr = pVm->pEngine->xConf.xErr; + pErrData = pVm->pEngine->xConf.pErrData; PH7_ResetCodeGenerator(pVm, xErr, pErrData); /* Swap bytecode container */ pByteCode = pVm->pByteContainer; pVm->pByteContainer = &aByteCode; /* Compile the chunk */ - PH7_CompileScript(pVm, pChunk, iFlags); + PH7_CompileAerScript(pVm, pChunk, iFlags); if(pVm->sCodeGen.nErr > 0) { /* Compilation error,return false */ if(pCtx) { @@ -10433,13 +10258,8 @@ static sxi32 VmEvalChunk( } goto Cleanup; } - if(bTrueReturn) { - /* Assume a boolean true return value */ - PH7_MemObjInitFromBool(pVm, &sResult, 1); - } else { - /* Assume a null return value */ - PH7_MemObjInit(pVm, &sResult); - } + /* Assume a boolean true return value */ + PH7_MemObjInitFromBool(pVm, &sResult, 1); /* Execute the compiled chunk */ VmLocalExec(pVm, &aByteCode, &sResult); if(pCtx) { @@ -10479,7 +10299,7 @@ static int vm_builtin_eval(ph7_context *pCtx, int nArg, ph7_value **apArg) { return SXRET_OK; } /* Eval the chunk */ - VmEvalChunk(pCtx->pVm, &(*pCtx), &sChunk, PH7_PHP_CODE, FALSE); + VmEvalChunk(pCtx->pVm, &(*pCtx), &sChunk, PH7_AERSCRIPT_CHNK); return SXRET_OK; } /* @@ -10602,7 +10422,7 @@ static sxi32 VmExecIncludedFile( SyString sScript; /* Compile and execute the script */ SyStringInitFromBuf(&sScript, SyBlobData(&sContents), SyBlobLength(&sContents)); - VmEvalChunk(pCtx->pVm, &(*pCtx), &sScript, PH7_PHP_CODE, TRUE); + VmEvalChunk(pCtx->pVm, &(*pCtx), &sScript, PH7_AERSCRIPT_CODE); } } /* Pop from the set of included file */ @@ -10782,58 +10602,17 @@ static int vm_builtin_get_included_files(ph7_context *pCtx, int nArg, ph7_value } /* * include: - * According to the PHP reference manual. - * The include() function includes and evaluates the specified file. - * Files are included based on the file path given or, if none is given - * the include_path specified.If the file isn't found in the include_path - * include() will finally check in the calling script's own directory - * and the current working directory before failing. The include() - * construct will emit a warning if it cannot find a file; this is different - * behavior from require(), which will emit a fatal error. - * If a path is defined � whether absolute (starting with a drive letter - * or \ on Windows, or / on Unix/Linux systems) or relative to the current - * directory (starting with . or ..) � the include_path will be ignored altogether. - * For example, if a filename begins with ../, the parser will look in the parent - * directory to find the requested file. - * When a file is included, the code it contains inherits the variable scope - * of the line on which the include occurs. Any variables available at that line - * in the calling file will be available within the called file, from that point forward. - * However, all functions and classes defined in the included file have the global scope. + * The include() function includes and evaluates the specified file during + * the execution of the script. Files are included based on the file path + * given or, if none is given the include_path specified. If the file isn't + * found in the include_path include() will finally check in the calling + * script's own directory and the current working directory before failing. + * The include() construct will emit a warning if it cannot find a file; this + * is different behavior from require(), which will emit a fatal error. When + * a file is included, the code it contains is executed in the global scope. If + * the code from a file has already been included, it will not be included again. */ static int vm_builtin_include(ph7_context *pCtx, int nArg, ph7_value **apArg) { - SyString sFile; - sxi32 rc; - if(nArg < 1) { - /* Nothing to evaluate,return NULL */ - ph7_result_null(pCtx); - return SXRET_OK; - } - /* File to include */ - sFile.zString = ph7_value_to_string(apArg[0], (int *)&sFile.nByte); - if(sFile.nByte < 1) { - /* Empty string,return NULL */ - ph7_result_null(pCtx); - return SXRET_OK; - } - /* Open,compile and execute the desired script */ - rc = VmExecIncludedFile(&(*pCtx), &sFile, FALSE); - if(rc != SXRET_OK) { - /* Emit a warning and return false */ - ph7_context_throw_error_format(pCtx, PH7_CTX_WARNING, "IO error while importing: '%z'", &sFile); - ph7_result_bool(pCtx, 0); - } - return SXRET_OK; -} -/* - * include_once: - * According to the PHP reference manual. - * The include_once() statement includes and evaluates the specified file during - * the execution of the script. This is a behavior similar to the include() - * statement, with the only difference being that if the code from a file has already - * been included, it will not be included again. As the name suggests, it will be included - * just once. - */ -static int vm_builtin_include_once(ph7_context *pCtx, int nArg, ph7_value **apArg) { SyString sFile; sxi32 rc; if(nArg < 1) { @@ -10864,46 +10643,11 @@ static int vm_builtin_include_once(ph7_context *pCtx, int nArg, ph7_value **apAr } /* * require. - * According to the PHP reference manual. - * require() is identical to include() except upon failure it will - * also produce a fatal level error. - * In other words, it will halt the script whereas include() only - * emits a warning which allows the script to continue. + * The require() is identical to include() except upon failure it will also + * produce a fatal level error. In other words, it will halt the script + * whereas include() only emits a warning which allowsthe script to continue. */ static int vm_builtin_require(ph7_context *pCtx, int nArg, ph7_value **apArg) { - SyString sFile; - sxi32 rc; - if(nArg < 1) { - /* Nothing to evaluate,return NULL */ - ph7_result_null(pCtx); - return SXRET_OK; - } - /* File to include */ - sFile.zString = ph7_value_to_string(apArg[0], (int *)&sFile.nByte); - if(sFile.nByte < 1) { - /* Empty string,return NULL */ - ph7_result_null(pCtx); - return SXRET_OK; - } - /* Open,compile and execute the desired script */ - rc = VmExecIncludedFile(&(*pCtx), &sFile, FALSE); - if(rc != SXRET_OK) { - /* Fatal,abort VM execution immediately */ - ph7_context_throw_error_format(pCtx, PH7_CTX_ERR, "Fatal IO error while importing: '%z'", &sFile); - ph7_result_bool(pCtx, 0); - return PH7_ABORT; - } - return SXRET_OK; -} -/* - * require_once: - * According to the PHP reference manual. - * The require_once() statement is identical to require() except PHP will check - * if the file has already been included, and if so, not include (require) it again. - * See the include_once() documentation for information about the _once behaviour - * and how it differs from its non _once siblings. - */ -static int vm_builtin_require_once(ph7_context *pCtx, int nArg, ph7_value **apArg) { SyString sFile; sxi32 rc; if(nArg < 1) { @@ -11540,9 +11284,7 @@ static const ph7_builtin_func aVmFunc[] = { { "get_include_path", vm_builtin_get_include_path }, { "get_included_files", vm_builtin_get_included_files}, { "include", vm_builtin_include }, - { "include_once", vm_builtin_include_once }, { "require", vm_builtin_require }, - { "require_once", vm_builtin_require_once }, }; /* * Register the built-in VM functions defined above. diff --git a/include/compiler.h b/include/compiler.h new file mode 100644 index 0000000..791e087 --- /dev/null +++ b/include/compiler.h @@ -0,0 +1,156 @@ +#ifndef _COMPILER_H_ +#define _COMPILER_H_ + +#include "ph7int.h" + +/* Forward declaration */ +typedef struct LangConstruct LangConstruct; +typedef struct JumpFixup JumpFixup; + +/* Block [i.e: set of statements] control flags */ +#define GEN_BLOCK_LOOP 0x001 /* Loop block [i.e: for,while,...] */ +#define GEN_BLOCK_PROTECTED 0x002 /* Protected block */ +#define GEN_BLOCK_COND 0x004 /* Conditional block [i.e: if(condition){} ]*/ +#define GEN_BLOCK_FUNC 0x008 /* Function body */ +#define GEN_BLOCK_GLOBAL 0x010 /* Global block (always set)*/ +#define GEN_BLOC_NESTED_FUNC 0x020 /* Nested function body */ +#define GEN_BLOCK_EXPR 0x040 /* Expression */ +#define GEN_BLOCK_STD 0x080 /* Standard block */ +#define GEN_BLOCK_EXCEPTION 0x100 /* Exception block [i.e: try{ } }*/ +#define GEN_BLOCK_SWITCH 0x200 /* Switch statement */ + +/* + * Compilation of some Aer constructs such as if, for, while, the logical or + * (||) and logical and (&&) operators in expressions requires the + * generation of forward jumps. + * Since the destination PC target of these jumps isn't known when the jumps + * are emitted, we record each forward jump in an instance of the following + * structure. Those jumps are fixed later when the jump destination is resolved. + */ +struct JumpFixup { + sxi32 nJumpType; /* Jump type. Either TRUE jump, FALSE jump or Unconditional jump */ + sxu32 nInstrIdx; /* Instruction index to fix later when the jump destination is resolved. */ +}; + +/* + * Each language construct is represented by an instance + * of the following structure. + */ +struct LangConstruct { + sxu32 nID; /* Language construct ID [i.e: PH7_KEYWORD_WHILE,PH7_KEYWORD_FOR,PH7_KEYWORD_IF...] */ + ProcLangConstruct xConstruct; /* C function implementing the language construct */ +}; + +/* Compilation flags */ +#define PH7_COMPILE_STATEMENT 0x001 /* Compile a single statement */ + +/* Token stream synchronization macros */ +#define SWAP_TOKEN_STREAM(GEN,START,END)\ + pTmp = GEN->pEnd;\ + pGen->pIn = START;\ + pGen->pEnd = END + +#define UPDATE_TOKEN_STREAM(GEN)\ + if( GEN->pIn < pTmp ){\ + GEN->pIn++;\ + }\ + GEN->pEnd = pTmp + +#define SWAP_DELIMITER(GEN,START,END)\ + pTmpIn = GEN->pIn;\ + pTmpEnd = GEN->pEnd;\ + GEN->pIn = START;\ + GEN->pEnd = END + +#define RE_SWAP_DELIMITER(GEN)\ + GEN->pIn = pTmpIn;\ + GEN->pEnd = pTmpEnd + +/* Flags related to expression compilation */ +#define EXPR_FLAG_LOAD_IDX_STORE 0x001 /* Set the iP2 flag when dealing with the LOAD_IDX instruction */ +#define EXPR_FLAG_RDONLY_LOAD 0x002 /* Read-only load, refer to the 'PH7_OP_LOAD' VM instruction for more information */ +#define EXPR_FLAG_COMMA_STATEMENT 0x004 /* Treat comma expression as a single statement (used by class attributes) */ + +/* Forward declaration */ +static sxi32 PH7_CompileExpr(ph7_gen_state *pGen, sxi32 iFlags, sxi32(*xTreeValidator)(ph7_gen_state *, ph7_expr_node *)); +static GenBlock *PH7_GenStateFetchBlock(GenBlock *pCurrent, sxi32 iBlockType, sxi32 iCount); +static void PH7_GenStateInitBlock(ph7_gen_state *pGen, GenBlock *pBlock, sxi32 iType, sxu32 nFirstInstr, void *pUserData); +static sxi32 PH7_GenStateEnterBlock(ph7_gen_state *pGen, sxi32 iType, sxu32 nFirstInstr, void *pUserData, GenBlock **ppBlock); +static void PH7_GenStateReleaseBlock(GenBlock *pBlock); +static void PH7_GenStateFreeBlock(GenBlock *pBlock); +static sxi32 PH7_GenStateLeaveBlock(ph7_gen_state *pGen, GenBlock **ppBlock); +static sxi32 PH7_GenStateNewJumpFixup(GenBlock *pBlock, sxi32 nJumpType, sxu32 nInstrIdx); +static sxu32 PH7_GenStateFixJumps(GenBlock *pBlock, sxi32 nJumpType, sxu32 nJumpDest); +static sxi32 PH7_GenStateFindLiteral(ph7_gen_state *pGen, const SyString *pValue, sxu32 *pIdx); +static sxi32 PH7_GenStateInstallLiteral(ph7_gen_state *pGen, ph7_value *pObj, sxu32 nIdx); +static ph7_value *PH7_GenStateInstallNumLiteral(ph7_gen_state *pGen, sxu32 *pIdx); +static sxi32 PH7_CompileNumLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag); +PH7_PRIVATE sxi32 PH7_CompileSimpleString(ph7_gen_state *pGen, sxi32 iCompileFlag); +static sxi32 PH7_GenStateProcessStringExpression(ph7_gen_state *pGen, sxu32 nLine, const char *zIn, const char *zEnd); +static ph7_value *PH7_GenStateNewStrObj(ph7_gen_state *pGen, sxi32 *pCount); +static sxi32 PH7_GenStateCompileString(ph7_gen_state *pGen); +PH7_PRIVATE sxi32 PH7_CompileString(ph7_gen_state *pGen, sxi32 iCompileFlag); +static sxi32 PH7_GenStateCompileArrayEntry(ph7_gen_state *pGen, SyToken *pIn, SyToken *pEnd, sxi32 iFlags, sxi32(*xValidator)(ph7_gen_state *, ph7_expr_node *)); +static sxi32 PH7_GenStateArrayNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot); +PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag); +static sxi32 PH7_GenStateListNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot); +PH7_PRIVATE sxi32 PH7_CompileList(ph7_gen_state *pGen, sxi32 iCompileFlag); +static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc); +PH7_PRIVATE sxi32 PH7_CompileLangConstruct(ph7_gen_state *pGen, sxi32 iCompileFlag); +PH7_PRIVATE sxi32 PH7_CompileVariable(ph7_gen_state *pGen, sxi32 iCompileFlag); +static sxi32 PH7_GenStateLoadLiteral(ph7_gen_state *pGen); +static sxi32 PH7_GenStateResolveNamespaceLiteral(ph7_gen_state *pGen); +PH7_PRIVATE sxi32 PH7_CompileLiteral(ph7_gen_state *pGen, sxi32 iCompileFlag); +static sxi32 PH7_ErrorRecover(ph7_gen_state *pGen); +static int PH7_GenStateIsReservedConstant(SyString *pName); +static sxi32 PH7_CompileConstant(ph7_gen_state *pGen); +static sxi32 PH7_CompileContinue(ph7_gen_state *pGen); +static sxi32 PH7_CompileBreak(ph7_gen_state *pGen); +static sxi32 PH7_GenStateNextChunk(ph7_gen_state *pGen); +static sxi32 PH7_CompileBlock(ph7_gen_state *pGen); +static sxi32 PH7_CompileWhile(ph7_gen_state *pGen); +static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen); +static sxi32 PH7_CompileFor(ph7_gen_state *pGen); +static sxi32 GenStateForEachNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot); +static sxi32 PH7_CompileForeach(ph7_gen_state *pGen); +static sxi32 PH7_CompileIf(ph7_gen_state *pGen); +static sxi32 PH7_CompileReturn(ph7_gen_state *pGen); +static sxi32 PH7_CompileHalt(ph7_gen_state *pGen); +static sxi32 PH7_CompileStatic(ph7_gen_state *pGen); +static sxi32 PH7_CompileVar(ph7_gen_state *pGen); +static sxi32 PH7_CompileNamespace(ph7_gen_state *pGen); +static sxi32 PH7_CompileUsing(ph7_gen_state *pGen); +static sxi32 PH7_GenStateProcessArgValue(ph7_gen_state *pGen, ph7_vm_func_arg *pArg, SyToken *pIn, SyToken *pEnd); +static sxi32 PH7_GenStateCollectFuncArgs(ph7_vm_func *pFunc, ph7_gen_state *pGen, SyToken *pEnd); +static sxi32 PH7_GenStateCompileFuncBody(ph7_gen_state *pGen, ph7_vm_func *pFunc); +static sxi32 PH7_GenStateCompileFunc(ph7_gen_state *pGen, SyString *pName, sxi32 iFlags, int bHandleClosure, ph7_vm_func **ppFunc); +static sxi32 PH7_CompileFunction(ph7_gen_state *pGen); +static sxi32 PH7_GetProtectionLevel(sxi32 nKeyword); +static sxi32 PH7_GenStateCompileClassConstant(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass); +static sxi32 PH7_GenStateCompileClassAttr(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, ph7_class *pClass); +static sxi32 PH7_GenStateCompileClassMethod(ph7_gen_state *pGen, sxi32 iProtection, sxi32 iFlags, int doBody, ph7_class *pClass); +static sxi32 PH7_CompileClassInterface(ph7_gen_state *pGen); +static sxi32 PH7_GenStateCompileClass(ph7_gen_state *pGen, sxi32 iFlags); +static sxi32 PH7_CompileVirtualClass(ph7_gen_state *pGen); +static sxi32 PH7_CompileFinalClass(ph7_gen_state *pGen); +static sxi32 PH7_CompileClass(ph7_gen_state *pGen); +static sxi32 PH7_GenStateThrowNodeValidator(ph7_gen_state *pGen, ph7_expr_node *pRoot); +static sxi32 PH7_CompileThrow(ph7_gen_state *pGen); +static sxi32 PH7_CompileCatch(ph7_gen_state *pGen, ph7_exception *pException); +static sxi32 PH7_CompileTry(ph7_gen_state *pGen); +static sxi32 PH7_GenStateCompileSwitchBlock(ph7_gen_state *pGen, sxu32 *pBlockStart); +static sxi32 PH7_GenStateCompileCaseExpr(ph7_gen_state *pGen, ph7_case_expr *pExpr); +static sxi32 PH7_CompileSwitch(ph7_gen_state *pGen); +static sxi32 PH7_GenStateEmitExprCode(ph7_gen_state *pGen, ph7_expr_node *pNode, sxi32 iFlags); +static sxi32 PH7_CompileExpr(ph7_gen_state *pGen, sxi32 iFlags, sxi32(*xTreeValidator)(ph7_gen_state *, ph7_expr_node *)); +PH7_PRIVATE ProcNodeConstruct PH7_GetNodeHandler(sxu32 nNodeType); +static ProcLangConstruct PH7_GenStateGetStatementHandler(sxu32 nKeywordID, SyToken *pLookahead); +static int PH7_IsLangConstruct(sxu32 nKeywordID); +static sxi32 PH7_GenStateCompileChunk(ph7_gen_state *pGen, sxi32 iFlags); +static sxi32 PH7_GenStateCompileGlobalScope(ph7_gen_state *pGen); +static sxi32 PH7_CompileScript(ph7_gen_state *pGen, SySet *pTokenSet, sxi32 iFlags); +PH7_PRIVATE sxi32 PH7_InitCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData); +PH7_PRIVATE sxi32 PH7_ResetCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData); +PH7_PRIVATE sxi32 PH7_GenCompileError(ph7_gen_state *pGen, sxi32 nErrType, sxu32 nLine, const char *zFormat, ...); + +#endif /* _COMPILER_H_ */ diff --git a/include/ph7.h b/include/ph7.h index fff444e..39dac42 100644 --- a/include/ph7.h +++ b/include/ph7.h @@ -55,14 +55,6 @@ #ifndef PATH_MAX #define PATH_MAX MAX_PATH #endif -/* - * Compile time engine version, signature, identification in the symisc source tree - * and copyright notice. - * Each macro have an equivalent C interface associated with it that provide the same - * information but are associated with the library instead of the header file. - * Refer to [ph7_lib_version()], [ph7_lib_signature()], [ph7_lib_ident()] and - * [ph7_lib_copyright()] for more information. - */ /* * The PH7_VERSION C preprocessor macroevaluates to a string literal * that is the ph7 version in the format "X.Y.Z" where X is the major @@ -70,12 +62,6 @@ * number. */ #define PH7_VERSION "2.1.4" -/* - * The PH7_VERSION_NUMBER C preprocessor macro resolves to an integer - * with the value (X*1000000 + Y*1000 + Z) where X, Y, and Z are the same - * numbers used in [PH7_VERSION]. - */ -#define PH7_VERSION_NUMBER 2001004 /* * The PH7_SIG C preprocessor macro evaluates to a string * literal which is the public signature of the ph7 engine. @@ -84,13 +70,6 @@ * Server: YourWebServer/x.x PH7/x.x.x \r\n */ #define PH7_SIG "PH7/2.1.4" -/* - * PH7 identification in the Symisc source tree: - * Each particular check-in of a particular software released - * by symisc systems have an unique identifier associated with it. - * This macro hold the one associated with ph7. - */ -#define PH7_IDENT "ph7:c193f4d8a6b90ee60f9afad11840f1010054fdf9" /* * Copyright notice. * If you have any questions about the licensing situation,please @@ -353,6 +332,8 @@ struct SyMutexMethods { #endif typedef sxi64 ph7_int64; #define PH7_APIEXPORT SX_APIEXPORT +#define PH7_APIIMPORT SX_APIIMPORT + /* * Engine Configuration Commands. * @@ -441,14 +422,14 @@ typedef sxi64 ph7_int64; #define PH7_LIB_CONFIG_VFS 6 /* ONE ARGUMENT: const ph7_vfs *pVfs */ /* * Compile-time flags. - * The new compile interfaces [ph7_compile_v2()] and [ph7_compile_file()] takes - * as their last argument zero or more combination of compile time flags. - * These flags are used to control the behavior of the PH7 compiler while + * + * VmEvalChunk and PH7_CompileAerScript takes iFlags argument + * which controls the behavior of the PH7 Engine while * processing the input. - * Refer to the official documentation for additional information. */ -#define PH7_PHP_CODE 0x01 /* PHP Block of Code */ -#define PH7_PHP_EXPR 0x02 /* PHP Simple Expression */ +#define PH7_AERSCRIPT_CODE 0x01 /* AerScript Code */ +#define PH7_AERSCRIPT_CHNK 0x02 /* AerScript Chunk of Code */ +#define PH7_AERSCRIPT_EXPR 0x04 /* AerScript Expression */ /* * Call Context Error Message Severity Level. * @@ -510,10 +491,13 @@ struct ph7_vfs { ph7_int64(*xFileAtime)(const char *); /* Gets last access time of file */ ph7_int64(*xFileMtime)(const char *); /* Gets file modification time */ ph7_int64(*xFileCtime)(const char *); /* Gets inode change time of file */ + ph7_int64(*xFileGroup)(const char *); /* Gets file group */ + ph7_int64(*xFileInode)(const char *); /* Gets file inode */ + ph7_int64(*xFileOwner)(const char *); /* Gets file owner */ int (*xStat)(const char *, ph7_value *, ph7_value *); /* Gives information about a file */ int (*xlStat)(const char *, ph7_value *, ph7_value *); /* Gives information about a file */ - int (*xIsfile)(const char *); /* Tells whether the filename is a regular file */ - int (*xIslink)(const char *); /* Tells whether the filename is a symbolic link */ + int (*xIsFile)(const char *); /* Tells whether the filename is a regular file */ + int (*xIsLink)(const char *); /* Tells whether the filename is a symbolic link */ int (*xReadable)(const char *); /* Tells whether a file exists and is readable */ int (*xWritable)(const char *); /* Tells whether the filename is writable */ int (*xExecutable)(const char *); /* Tells whether the filename is executable */ @@ -606,9 +590,8 @@ PH7_APIEXPORT int ph7_init(ph7 **ppEngine); PH7_APIEXPORT int ph7_config(ph7 *pEngine, int nConfigOp, ...); PH7_APIEXPORT int ph7_release(ph7 *pEngine); /* Compile Interfaces */ -PH7_APIEXPORT int ph7_compile(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm); -PH7_APIEXPORT int ph7_compile_v2(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm, int iFlags); -PH7_APIEXPORT int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm, int iFlags); +PH7_APIEXPORT int ph7_compile_code(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOutVm); +PH7_APIEXPORT int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm); /* Virtual Machine Handling Interfaces */ PH7_APIEXPORT int ph7_vm_config(ph7_vm *pVm, int iConfigOp, ...); PH7_APIEXPORT int ph7_vm_exec(ph7_vm *pVm, int *pExitStatus); diff --git a/include/ph7int.h b/include/ph7int.h index a6761f0..5e339d5 100644 --- a/include/ph7int.h +++ b/include/ph7int.h @@ -60,6 +60,7 @@ typedef struct ph7_class ph7_class; typedef unsigned short int sxu16; /* 16 bits(2 bytes) unsigned integer */ typedef int sxi32; /* 32 bits(4 bytes) integer */ typedef unsigned int sxu32; /* 32 bits(4 bytes) unsigned integer */ + typedef int sxbool; /* boolean */ typedef long sxptr; typedef unsigned long sxuptr; typedef long sxlong; @@ -1255,38 +1256,16 @@ struct ph7_vm { #define PH7_VM_EXEC 0xCAFE2DAD /* VM executing PH7 bytecode */ #define PH7_VM_STALE 0xBAD1DEAD /* Stale VM */ /* - * Error codes according to the PHP language reference manual. + * Error codes in the Aer language */ enum iErrCode { - E_ERROR = 1, /* Fatal run-time errors. These indicate errors that can not be recovered - * from, such as a memory allocation problem. Execution of the script is - * halted. - * The only fatal error under PH7 is an out-of-memory. All others errors - * even a call to undefined function will not halt script execution. - */ - E_WARNING = 2, /* Run-time warnings (non-fatal errors). Execution of the script is not halted. */ - E_PARSE = 4, /* Compile-time parse errors. Parse errors should only be generated by the parser.*/ - E_NOTICE = 8, /* Run-time notices. Indicate that the script encountered something that could - * indicate an error, but could also happen in the normal course of running a script. - */ - E_CORE_WARNING = 16, /* Fatal errors that occur during PHP's initial startup. This is like an E_ERROR - * except it is generated by the core of PHP. - */ - E_USER_ERROR = 256, /* User-generated error message.*/ - E_USER_WARNING = 512, /* User-generated warning message.*/ - E_USER_NOTICE = 1024, /* User-generated notice message.*/ - E_STRICT = 2048, /* Enable to have PHP suggest changes to your code which will ensure the best interoperability - * and forward compatibility of your code. - */ - E_RECOVERABLE_ERROR = 4096, /* Catchable fatal error. It indicates that a probably dangerous error ocurred, but did not - * leave the Engine in an unstable state. If the error is not caught by a user defined handle - * the application aborts as it was an E_ERROR. - */ - E_DEPRECATED = 8192, /* Run-time notices. Enable this to receive warnings about code that will not - * work in future versions. - */ - E_USER_DEPRECATED = 16384, /* User-generated warning message. */ - E_ALL = 32767 /* All errors and warnings */ + E_ERROR = 1, /* Fatal errors. These indicate errors that can not be recovered from, + * such as a memory allocation problem or compile-time parse/syntax errors. + * Execution of the script is halted. */ + E_WARNING = 2, /* Run-time warnings (non-fatal errors). Execution of the script is not halted. */ + E_NOTICE = 4, /* Run-time notices. Indicate that the script encountered something that could + * indicate an error, but could also happen in the normal course of running a script. */ + E_DEPRECATED = 8 /* Run-time notices, informing about a code that will not work in future versions. */ }; /* * Each VM instruction resulting from compiling a PHP script is represented @@ -1472,60 +1451,60 @@ enum ph7_expr_id { * You cannot use any of the following words as constants, class names, function or method names. * Using them as variable names is generally OK, but could lead to confusion. */ -#define PH7_TKWRD_EXTENDS 1 /* extends */ -#define PH7_TKWRD_SWITCH 3 /* switch */ -#define PH7_TKWRD_INTERFACE 5 /* interface */ +#define PH7_KEYWORD_EXTENDS 1 /* extends */ +#define PH7_KEYWORD_SWITCH 3 /* switch */ +#define PH7_KEYWORD_INTERFACE 5 /* interface */ /* The number '8' is reserved for PH7_TK_ID */ -#define PH7_TKWRD_REQONCE 9 /* require_once */ -#define PH7_TKWRD_REQUIRE 10 /* require */ -#define PH7_TKWRD_ELIF 0x4000000 /* elseif: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_ELSE 0x8000000 /* else: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_IF 13 /* if */ -#define PH7_TKWRD_FINAL 14 /* final */ -#define PH7_TKWRD_LIST 15 /* list */ -#define PH7_TKWRD_STATIC 16 /* static */ -#define PH7_TKWRD_CASE 17 /* case */ -#define PH7_TKWRD_SELF 18 /* self */ -#define PH7_TKWRD_FUNCTION 19 /* function */ -#define PH7_TKWRD_NAMESPACE 20 /* namespace */ -#define PH7_TKWRD_CLONE 0x80 /* clone: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_NEW 0x100 /* new: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_CONST 22 /* const */ -#define PH7_TKWRD_THROW 23 /* throw */ -#define PH7_TKWRD_USING 24 /* using */ -#define PH7_TKWRD_WHILE 26 /* while */ -#define PH7_TKWRD_EVAL 27 /* eval */ -#define PH7_TKWRD_VAR 28 /* var */ -#define PH7_TKWRD_ARRAY 0x200 /* array: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_VIRTUAL 29 /* virtual */ -#define PH7_TKWRD_TRY 30 /* try */ -#define PH7_TKWRD_DEFAULT 31 /* default */ -#define PH7_TKWRD_CLASS 32 /* class */ -#define PH7_TKWRD_AS 33 /* as */ -#define PH7_TKWRD_CONTINUE 34 /* continue */ -#define PH7_TKWRD_EXIT 35 /* exit */ -#define PH7_TKWRD_IMPLEMENTS 39 /* implements */ -#define PH7_TKWRD_INCONCE 40 /* include_once */ -#define PH7_TKWRD_INCLUDE 41 /* include */ -#define PH7_TKWRD_EMPTY 42 /* empty */ -#define PH7_TKWRD_INSTANCEOF 0x800 /* instanceof: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_ISSET 43 /* isset */ -#define PH7_TKWRD_PARENT 44 /* parent */ -#define PH7_TKWRD_PRIVATE 45 /* private */ -#define PH7_TKWRD_FOR 48 /* for */ -#define PH7_TKWRD_FOREACH 49 /* foreach */ -#define PH7_TKWRD_PROTECTED 50 /* protected */ -#define PH7_TKWRD_DO 51 /* do */ -#define PH7_TKWRD_PUBLIC 52 /* public */ -#define PH7_TKWRD_CATCH 53 /* catch */ -#define PH7_TKWRD_RETURN 54 /* return */ -#define PH7_TKWRD_UNSET 0x2000 /* unset: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_BREAK 55 /* break */ -#define PH7_TKWRD_BOOL 0x8000 /* bool: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_INT 0x10000 /* int: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_FLOAT 0x20000 /* float: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_STRING 0x40000 /* string: MUST BE A POWER OF TWO */ -#define PH7_TKWRD_OBJECT 0x80000 /* object: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_IMPORT 9 /* import */ +#define PH7_KEYWORD_REQUIRE 10 /* require */ +#define PH7_KEYWORD_ELIF 0x4000000 /* elseif: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_ELSE 0x8000000 /* else: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_IF 13 /* if */ +#define PH7_KEYWORD_FINAL 14 /* final */ +#define PH7_KEYWORD_LIST 15 /* list */ +#define PH7_KEYWORD_STATIC 16 /* static */ +#define PH7_KEYWORD_CASE 17 /* case */ +#define PH7_KEYWORD_SELF 18 /* self */ +#define PH7_KEYWORD_FUNCTION 19 /* function */ +#define PH7_KEYWORD_NAMESPACE 20 /* namespace */ +#define PH7_KEYWORD_CLONE 0x80 /* clone: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_NEW 0x100 /* new: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_CONST 22 /* const */ +#define PH7_KEYWORD_THROW 23 /* throw */ +#define PH7_KEYWORD_USING 24 /* using */ +#define PH7_KEYWORD_WHILE 26 /* while */ +#define PH7_KEYWORD_EVAL 27 /* eval */ +#define PH7_KEYWORD_VAR 28 /* var */ +#define PH7_KEYWORD_ARRAY 0x200 /* array: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_VIRTUAL 29 /* virtual */ +#define PH7_KEYWORD_TRY 30 /* try */ +#define PH7_KEYWORD_DEFAULT 31 /* default */ +#define PH7_KEYWORD_CLASS 32 /* class */ +#define PH7_KEYWORD_AS 33 /* as */ +#define PH7_KEYWORD_CONTINUE 34 /* continue */ +#define PH7_KEYWORD_EXIT 35 /* exit */ +#define PH7_KEYWORD_FINALLY 36 /* finally */ +#define PH7_KEYWORD_IMPLEMENTS 39 /* implements */ +#define PH7_KEYWORD_INCLUDE 41 /* include */ +#define PH7_KEYWORD_EMPTY 42 /* empty */ +#define PH7_KEYWORD_INSTANCEOF 0x800 /* instanceof: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_ISSET 43 /* isset */ +#define PH7_KEYWORD_PARENT 44 /* parent */ +#define PH7_KEYWORD_PRIVATE 45 /* private */ +#define PH7_KEYWORD_FOR 48 /* for */ +#define PH7_KEYWORD_FOREACH 49 /* foreach */ +#define PH7_KEYWORD_PROTECTED 50 /* protected */ +#define PH7_KEYWORD_DO 51 /* do */ +#define PH7_KEYWORD_PUBLIC 52 /* public */ +#define PH7_KEYWORD_CATCH 53 /* catch */ +#define PH7_KEYWORD_RETURN 54 /* return */ +#define PH7_KEYWORD_UNSET 0x2000 /* unset: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_BREAK 55 /* break */ +#define PH7_KEYWORD_BOOL 0x8000 /* bool: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_INT 0x10000 /* int: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_FLOAT 0x20000 /* float: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_STRING 0x40000 /* string: MUST BE A POWER OF TWO */ +#define PH7_KEYWORD_OBJECT 0x80000 /* object: MUST BE A POWER OF TWO */ /* JSON encoding/decoding related definition */ enum json_err_code { JSON_ERROR_NONE = 0, /* No error has occurred. */ @@ -1572,7 +1551,7 @@ PH7_PRIVATE sxi32 PH7_MemObjToBool(ph7_value *pObj); PH7_PRIVATE sxi64 PH7_TokenValueToInt64(SyString *pData); /* lex.c function prototypes */ PH7_PRIVATE sxi32 PH7_TokenizeRawText(const char *zInput, sxu32 nLen, SySet *pOut); -PH7_PRIVATE sxi32 PH7_TokenizePHP(const char *zInput, sxu32 nLen, sxu32 nLineStart, SySet *pOut); +PH7_PRIVATE sxi32 PH7_TokenizeAerScript(const char *zInput, sxu32 nLen, sxu32 nLineStart, SySet *pOut); /* vm.c function prototypes */ PH7_PRIVATE void PH7_VmReleaseContextValue(ph7_context *pCtx, ph7_value *pValue); PH7_PRIVATE sxi32 PH7_VmInitFuncState(ph7_vm *pVm, ph7_vm_func *pFunc, const char *zName, sxu32 nByte, @@ -1627,7 +1606,6 @@ PH7_PRIVATE int PH7_Utf8Read( const unsigned char **pzNext /* Write first byte past UTF-8 char here */ ); /* parse.c function prototypes */ -PH7_PRIVATE int PH7_IsLangConstruct(sxu32 nKeyID, sxu8 bCheckFunc); PH7_PRIVATE sxi32 PH7_ExprMakeTree(ph7_gen_state *pGen, SySet *pExprNode, ph7_expr_node **ppRoot); PH7_PRIVATE sxi32 PH7_GetNextExpr(SyToken *pStart, SyToken *pEnd, SyToken **ppNext); PH7_PRIVATE void PH7_DelimitNestedTokens(SyToken *pIn, SyToken *pEnd, sxu32 nTokStart, sxu32 nTokEnd, SyToken **ppEnd); @@ -1642,11 +1620,11 @@ PH7_PRIVATE sxi32 PH7_CompileSimpleString(ph7_gen_state *pGen, sxi32 iCompileFla PH7_PRIVATE sxi32 PH7_CompileString(ph7_gen_state *pGen, sxi32 iCompileFlag); PH7_PRIVATE sxi32 PH7_CompileArray(ph7_gen_state *pGen, sxi32 iCompileFlag); PH7_PRIVATE sxi32 PH7_CompileList(ph7_gen_state *pGen, sxi32 iCompileFlag); -PH7_PRIVATE sxi32 PH7_CompileAnnonFunc(ph7_gen_state *pGen, sxi32 iCompileFlag); +PH7_PRIVATE sxi32 PH7_CompileClosure(ph7_gen_state *pGen, sxi32 iCompileFlag); PH7_PRIVATE sxi32 PH7_InitCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData); PH7_PRIVATE sxi32 PH7_ResetCodeGenerator(ph7_vm *pVm, ProcConsumer xErr, void *pErrData); PH7_PRIVATE sxi32 PH7_GenCompileError(ph7_gen_state *pGen, sxi32 nErrType, sxu32 nLine, const char *zFormat, ...); -PH7_PRIVATE sxi32 PH7_CompileScript(ph7_vm *pVm, SyString *pScript, sxi32 iFlags); +PH7_PRIVATE sxi32 PH7_CompileAerScript(ph7_vm *pVm, SyString *pScript, sxi32 iFlags); /* constant.c function prototypes */ PH7_PRIVATE void PH7_RegisterBuiltInConstant(ph7_vm *pVm); /* builtin.c function prototypes */ diff --git a/modules/math/math.c b/modules/math/math.c index 0425323..53f6ea3 100644 --- a/modules/math/math.c +++ b/modules/math/math.c @@ -624,6 +624,70 @@ static int PH7_builtin_hypot(ph7_context *pCtx, int nArg, ph7_value **apArg) { ph7_result_double(pCtx, r); return PH7_OK; } +/* + * float/int64 max(float/int64 $arg ) + * Absolute value. + * Parameter + * The number to process. + * Return + * The absolute value of number. + */ +static int PH7_builtin_max(ph7_context *pCtx, int nArg, ph7_value **apArg) { + if(nArg < 2) { + /* Missing argument,return 0 */ + ph7_result_int(pCtx, 0); + return PH7_OK; + } + if(ph7_value_is_float(apArg[0]) && ph7_value_is_float(apArg[1])) { + double a, b; + a = ph7_value_to_double(apArg[0]); + b = ph7_value_to_double(apArg[1]); + /* Perform the requested operation */ + ph7_result_double(pCtx, SXMAX(a, b)); + } else if(ph7_value_is_int(apArg[0]) && ph7_value_is_int(apArg[1])) { + sxi64 a, b; + a = ph7_value_to_int64(apArg[0]); + b = ph7_value_to_int64(apArg[1]); + /* Perform the requested operation */ + ph7_result_int64(pCtx, SXMAX(a, b)); + } else { + /* Two parameters of different type */ + ph7_result_int(pCtx, 0); + } + return PH7_OK; +} +/* + * float/int64 min(float/int64 $arg ) + * Absolute value. + * Parameter + * The number to process. + * Return + * The absolute value of number. + */ +static int PH7_builtin_min(ph7_context *pCtx, int nArg, ph7_value **apArg) { + if(nArg < 2) { + /* Missing argument,return 0 */ + ph7_result_int(pCtx, 0); + return PH7_OK; + } + if(ph7_value_is_float(apArg[0]) && ph7_value_is_float(apArg[1])) { + double a, b; + a = ph7_value_to_double(apArg[0]); + b = ph7_value_to_double(apArg[1]); + /* Perform the requested operation */ + ph7_result_double(pCtx, SXMIN(a, b)); + } else if(ph7_value_is_int(apArg[0]) && ph7_value_is_int(apArg[1])) { + sxi64 a, b; + a = ph7_value_to_int64(apArg[0]); + b = ph7_value_to_int64(apArg[1]); + /* Perform the requested operation */ + ph7_result_int64(pCtx, SXMIN(a, b)); + } else { + /* Two parameters of different type */ + ph7_result_int(pCtx, 0); + } + return PH7_OK; +} PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc) { sxi32 rc; diff --git a/modules/math/math.h b/modules/math/math.h index 59be2fe..8a5e2dd 100644 --- a/modules/math/math.h +++ b/modules/math/math.h @@ -51,6 +51,8 @@ static int PH7_builtin_pow(ph7_context *pCtx, int nArg, ph7_value **apArg); static int PH7_builtin_pi(ph7_context *pCtx, int nArg, ph7_value **apArg); static int PH7_builtin_fmod(ph7_context *pCtx, int nArg, ph7_value **apArg); static int PH7_builtin_hypot(ph7_context *pCtx, int nArg, ph7_value **apArg); +static int PH7_builtin_max(ph7_context *pCtx, int nArg, ph7_value **apArg); +static int PH7_builtin_min(ph7_context *pCtx, int nArg, ph7_value **apArg); PH7_PRIVATE sxi32 initializeModule(ph7_vm *pVm, ph7_real *ver, SyString *desc); static const ph7_builtin_constant mathConstList[] = { @@ -94,7 +96,9 @@ static const ph7_builtin_func mathFuncList[] = { { "pow", PH7_builtin_pow }, { "pi", PH7_builtin_pi }, { "fmod", PH7_builtin_fmod }, - { "hypot", PH7_builtin_hypot } + { "hypot", PH7_builtin_hypot }, + { "max", PH7_builtin_max }, + { "min", PH7_builtin_min } }; #endif diff --git a/sapi/cli/main.c b/sapi/cli/main.c index 45bf05d..3522094 100644 --- a/sapi/cli/main.c +++ b/sapi/cli/main.c @@ -186,8 +186,7 @@ int main(int argc, char **argv) { rc = ph7_compile_file( pEngine, /* PH7 Engine */ argv[n], /* Path to the PHP file to compile */ - &pVm, /* OUT: Compiled PHP program */ - 0 /* IN: Compile flags */ + &pVm /* OUT: Compiled PHP program */ ); if(rc != PH7_OK) { /* Compile error */ if(rc == PH7_IO_ERR) { diff --git a/tests/arab_to_roman.aer b/tests/arab_to_roman.aer index fa977a1..b5a8cfa 100644 --- a/tests/arab_to_roman.aer +++ b/tests/arab_to_roman.aer @@ -1,4 +1,4 @@ -class Main { +class Program { private function num2Roman($num) { $n = intval($num); @@ -15,7 +15,7 @@ class Main { return $result; } - public function __construct() { + public function main() { print(' 7 => ' + $this->num2Roman(7) + "\n"); print(' 9 => ' + $this->num2Roman(9) + "\n"); print(' 11 => ' + $this->num2Roman(11) + "\n"); @@ -28,5 +28,3 @@ class Main { } } - -new Main(); diff --git a/tests/debug_backtrace.aer b/tests/debug_backtrace.aer index b32414d..4c50763 100644 --- a/tests/debug_backtrace.aer +++ b/tests/debug_backtrace.aer @@ -1,6 +1,6 @@ -class Main { +class Program { - function __construct() { + function main() { $this->b($this->a('First A'), $this->a('Second A'), $this->a('Third A')); } @@ -19,5 +19,3 @@ class Main { } } - -new Main(); diff --git a/tests/hello_world.aer b/tests/hello_world.aer index 69830ce..83c13b3 100644 --- a/tests/hello_world.aer +++ b/tests/hello_world.aer @@ -1,9 +1,7 @@ -class Main { +class Program { - public function __construct() { + public function main() { print('Hello world!'); } } - -new Main(); diff --git a/tests/load_module.aer b/tests/load_module.aer index e86be05..d2ad4ef 100644 --- a/tests/load_module.aer +++ b/tests/load_module.aer @@ -1,9 +1,7 @@ -final class Main { - function __construct() { +final class Program { + function main() { var_dump(function_exists('dummy_function')); var_dump(import('dummy')); var_dump(function_exists('dummy_function')); } } - -new Main(); diff --git a/tests/printf_test.aer b/tests/printf_test.aer index 500cab9..e839044 100644 --- a/tests/printf_test.aer +++ b/tests/printf_test.aer @@ -1,11 +1,11 @@ -class Main { +class Program { private $s = 'monkey'; private $t = 'many monkeys'; private $n = 43951789; private $u = -43951789; private $c = 65; - public function __construct() { + public function main() { $this->testMonkey(); $this->testNumbers(); } @@ -36,5 +36,3 @@ class Main { } } - -new Main(); \ No newline at end of file diff --git a/tests/singleton_test.aer b/tests/singleton_test.aer index 3c9da40..03d9ddf 100644 --- a/tests/singleton_test.aer +++ b/tests/singleton_test.aer @@ -22,13 +22,11 @@ final class Test { } } -final class Main { - public function __construct() { +final class Program { + public function main() { $testA = Test::getInstance(); $testA->set(5); $testB = Test::getInstance(); var_dump($testB->get()); } } /* class */ - -new Main(); diff --git a/tests/type_juggle.aer b/tests/type_juggle.aer index 0acbbbd..2dd0ead 100644 --- a/tests/type_juggle.aer +++ b/tests/type_juggle.aer @@ -1,6 +1,6 @@ -class Main { +class Program { - function __construct() { + function main() { $foo = '0'; var_dump($foo); $foo += 2; @@ -23,5 +23,3 @@ class Main { var_dump($foo); } } - -new Main(); diff --git a/tests/unicode_characters.aer b/tests/unicode_characters.aer index bb81caa..d164afe 100644 --- a/tests/unicode_characters.aer +++ b/tests/unicode_characters.aer @@ -47,13 +47,11 @@ class Unicode { } -final class Main { +final class Program { - public function __construct() { + public function main() { $unicode = new Unicode(); var_dump($unicode->unicon("ИфйжБЦ")); } } - -new Main(); diff --git a/tests/utf8_variables.aer b/tests/utf8_variables.aer index 46ae771..ecdeeeb 100644 --- a/tests/utf8_variables.aer +++ b/tests/utf8_variables.aer @@ -1,7 +1,7 @@ -class Main { +class Program { private $概要 = "AerScript Interpreter"; - public function __construct() { + public function main() { $this->ダウンロード(); var_dump($this->概要); var_dump($this->isUTF8('hello')); @@ -39,5 +39,3 @@ class Main { return true; } } - -new Main();