Browse Source

Code formatting

pull/8/head
Rafal Kupiec 4 years ago
parent
commit
d898cd1e36
Signed by: belliash
GPG Key ID: 4E829243E0CFE6B4
  1. 1358
      api.c
  2. 6231
      builtin.c
  3. 4149
      compile.c
  4. 1068
      constant.c
  5. 2952
      hashmap.c
  6. 106
      interpreter.c
  7. 1020
      lexer.c
  8. 5767
      lib.c
  9. 868
      memobj.c
  10. 496
      oop.c
  11. 1965
      parser.c
  12. 340
      ph7.h
  13. 1376
      ph7int.h
  14. 5787
      vfs.c
  15. 14693
      vm.c

1358
api.c

File diff suppressed because it is too large Load Diff

6231
builtin.c

File diff suppressed because it is too large Load Diff

4149
compile.c

File diff suppressed because it is too large Load Diff

1068
constant.c

File diff suppressed because it is too large Load Diff

2952
hashmap.c

File diff suppressed because it is too large Load Diff

106
interpreter.c

@ -1,11 +1,11 @@
/*
* Compile this file together with the ph7 engine source code to generate
* the simple PH7 interpreter executable. For example:
* the simple PH7 interpreter executable. For example:
* gcc -W -Wall -O6 -D PH7_ENABLE_MATH_FUNC -o ph7 ph7_interp.c ph7.c
*/
/*
* The PH7 interpreter is a simple stand-alone PHP interpreter that allows
* the user to enter and execute PHP files against a PH7 engine.
* the user to enter and execute PHP files against a PH7 engine.
* To start the ph7 program, just type "ph7" followed by the name of the PHP file
* to compile and execute. That is, the first argument is to the interpreter, the rest
* are scripts arguments, press "Enter" and the PHP code will be executed.
@ -18,7 +18,7 @@
* ph7 scripts/mp3_tag.php /usr/local/path/to/my_mp3s
*
* The PH7 interpreter package includes more than 70 PHP scripts to test ranging from
* simple hello world programs to XML processing, ZIP archive extracting, MP3 tag extracting,
* simple hello world programs to XML processing, ZIP archive extracting, MP3 tag extracting,
* UUID generation, JSON encoding/decoding, INI processing, Base32 encoding/decoding and many
* more. These scripts are available in the scripts directory from the zip archive.
*/
@ -31,11 +31,10 @@
#include <stdlib.h>
/* Make sure this header file is available.*/
#include "ph7.h"
/*
/*
* Display an error message and exit.
*/
static void Fatal(const char *zMsg)
{
static void Fatal(const char *zMsg) {
puts(zMsg);
/* Shutdown the library */
ph7_lib_shutdown();
@ -54,8 +53,7 @@ static const char zBanner[] = {
/*
* Display the banner,a help message and exit.
*/
static void Help(void)
{
static void Help(void) {
puts(zBanner);
puts("ph7 [-h|-r|-d] path/to/php_file [script args]");
puts("\t-d: Dump PH7 byte-code instructions");
@ -65,17 +63,17 @@ static void Help(void)
exit(0);
}
#ifdef __WINNT__
#include <Windows.h>
#include <Windows.h>
#else
/* Assume UNIX */
#include <unistd.h>
/* Assume UNIX */
#include <unistd.h>
#endif
/*
* The following define is used by the UNIX built and have
* no particular meaning on windows.
*/
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#define STDOUT_FILENO 1
#endif
/*
* VM output consumer callback.
@ -86,19 +84,18 @@ static void Help(void)
* This function is registered later via a call to ph7_vm_config()
* with a configuration verb set to: PH7_VM_CONFIG_OUTPUT.
*/
static int Output_Consumer(const void *pOutput,unsigned int nOutputLen,void *pUserData /* Unused */)
{
static int Output_Consumer(const void *pOutput, unsigned int nOutputLen, void *pUserData /* Unused */) {
#ifdef __WINNT__
BOOL rc;
rc = WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),pOutput,(DWORD)nOutputLen,0,0);
if( !rc ){
rc = WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), pOutput, (DWORD)nOutputLen, 0, 0);
if(!rc) {
/* Abort processing */
return PH7_ABORT;
}
#else
ssize_t nWr;
nWr = write(STDOUT_FILENO,pOutput,nOutputLen);
if( nWr < 0 ){
nWr = write(STDOUT_FILENO, pOutput, nOutputLen);
if(nWr < 0) {
/* Abort processing */
return PH7_ABORT;
}
@ -107,10 +104,9 @@ static int Output_Consumer(const void *pOutput,unsigned int nOutputLen,void *pUs
return PH7_OK;
}
/*
* Main program: Compile and execute the PHP file.
* Main program: Compile and execute the PHP file.
*/
int main(int argc,char **argv)
{
int main(int argc, char **argv) {
ph7 *pEngine; /* PH7 engine */
ph7_vm *pVm; /* Compiled PHP program */
int dump_vm = 0; /* Dump VM instructions if TRUE */
@ -118,31 +114,31 @@ int main(int argc,char **argv)
int n; /* Script arguments */
int rc;
/* Process interpreter arguments first*/
for(n = 1 ; n < argc ; ++n ){
for(n = 1 ; n < argc ; ++n) {
int c;
if( argv[n][0] != '-' ){
if(argv[n][0] != '-') {
/* No more interpreter arguments */
break;
}
c = argv[n][1];
if( c == 'd' || c == 'D' ){
if(c == 'd' || c == 'D') {
/* Dump byte-code instructions */
dump_vm = 1;
}else if( c == 'r' || c == 'R' ){
} else if(c == 'r' || c == 'R') {
/* Report run-time errors */
err_report = 1;
}else{
} else {
/* Display a help message and exit */
Help();
}
}
if( n >= argc ){
if(n >= argc) {
puts("Missing PHP file to compile");
Help();
}
/* Allocate a new PH7 engine instance */
rc = ph7_init(&pEngine);
if( rc != PH7_OK ){
if(rc != PH7_OK) {
/*
* If the supplied memory subsystem is so sick that we are unable
* to allocate a tiny chunk of memory,there is no much we can do here.
@ -152,23 +148,23 @@ int main(int argc,char **argv)
/* Set an error log consumer callback. This callback [Output_Consumer()] will
* redirect all compile-time error messages to STDOUT.
*/
ph7_config(pEngine,PH7_CONFIG_ERR_OUTPUT,
Output_Consumer, /* Error log consumer */
0 /* NULL: Callback Private data */
);
ph7_config(pEngine, PH7_CONFIG_ERR_OUTPUT,
Output_Consumer, /* Error log consumer */
0 /* NULL: Callback Private data */
);
/* Now,it's time to compile our PHP file */
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 */
);
if( rc != PH7_OK ){ /* Compile error */
if( rc == PH7_IO_ERR ){
pEngine, /* PH7 Engine */
argv[n], /* Path to the PHP file to compile */
&pVm, /* OUT: Compiled PHP program */
0 /* IN: Compile flags */
);
if(rc != PH7_OK) { /* Compile error */
if(rc == PH7_IO_ERR) {
Fatal("IO error while opening the target file");
}else if( rc == PH7_VM_ERR ){
} else if(rc == PH7_VM_ERR) {
Fatal("VM initialization error");
}else{
} else {
/* Compile-time error, your output (STDOUT) should display the error messages */
Fatal("Compile error");
}
@ -179,35 +175,35 @@ int main(int argc,char **argv)
* so that we can consume the VM output and redirect it to STDOUT.
*/
rc = ph7_vm_config(pVm,
PH7_VM_CONFIG_OUTPUT,
Output_Consumer, /* Output Consumer callback */
0 /* Callback private data */
);
if( rc != PH7_OK ){
PH7_VM_CONFIG_OUTPUT,
Output_Consumer, /* Output Consumer callback */
0 /* Callback private data */
);
if(rc != PH7_OK) {
Fatal("Error while installing the VM output consumer callback");
}
/* Register script agruments so we can access them later using the $argv[]
* array from the compiled PHP program.
*/
for( n = n + 1; n < argc ; ++n ){
ph7_vm_config(pVm,PH7_VM_CONFIG_ARGV_ENTRY,argv[n]/* Argument value */);
for(n = n + 1; n < argc ; ++n) {
ph7_vm_config(pVm, PH7_VM_CONFIG_ARGV_ENTRY, argv[n]/* Argument value */);
}
if( err_report ){
if(err_report) {
/* Report script run-time errors */
ph7_vm_config(pVm,PH7_VM_CONFIG_ERR_REPORT);
ph7_vm_config(pVm, PH7_VM_CONFIG_ERR_REPORT);
}
if( dump_vm ){
if(dump_vm) {
/* Dump PH7 byte-code instructions */
ph7_vm_dump_v2(pVm,
Output_Consumer, /* Dump consumer callback */
0
);
Output_Consumer, /* Dump consumer callback */
0
);
}
/*
* And finally, execute our program. Note that your output (STDOUT in our case)
* should display the result.
*/
ph7_vm_exec(pVm,0);
ph7_vm_exec(pVm, 0);
/* All done, cleanup the mess left behind.
*/
ph7_vm_release(pVm);

1020
lexer.c

File diff suppressed because it is too large Load Diff

5767
lib.c

File diff suppressed because it is too large Load Diff

868
memobj.c

File diff suppressed because it is too large Load Diff

496
oop.c

@ -10,7 +10,7 @@
* or visit:
* http://ph7.symisc.net/
*/
/* $SymiscID: oo.c v1.9 FeeBSD 2012-07-17 03:44 devel <chm@symisc.net> $ */
/* $SymiscID: oo.c v1.9 FeeBSD 2012-07-17 03:44 devel <chm@symisc.net> $ */
#include "ph7int.h"
/*
* This file implement an Object Oriented (OO) subsystem for the PH7 engine.
@ -19,29 +19,28 @@
* Create an empty class.
* Return a pointer to a raw class (ph7_class instance) on success. NULL otherwise.
*/
PH7_PRIVATE ph7_class * PH7_NewRawClass(ph7_vm *pVm,const SyString *pName,sxu32 nLine)
{
PH7_PRIVATE ph7_class *PH7_NewRawClass(ph7_vm *pVm, const SyString *pName, sxu32 nLine) {
ph7_class *pClass;
char *zName;
/* Allocate a new instance */
pClass = (ph7_class *)SyMemBackendPoolAlloc(&pVm->sAllocator,sizeof(ph7_class));
if( pClass == 0 ){
pClass = (ph7_class *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class));
if(pClass == 0) {
return 0;
}
/* Zero the structure */
SyZero(pClass,sizeof(ph7_class));
SyZero(pClass, sizeof(ph7_class));
/* Duplicate class name */
zName = SyMemBackendStrDup(&pVm->sAllocator,pName->zString,pName->nByte);
if( zName == 0 ){
SyMemBackendPoolFree(&pVm->sAllocator,pClass);
zName = SyMemBackendStrDup(&pVm->sAllocator, pName->zString, pName->nByte);
if(zName == 0) {
SyMemBackendPoolFree(&pVm->sAllocator, pClass);
return 0;
}
/* Initialize fields */
SyStringInitFromBuf(&pClass->sName,zName,pName->nByte);
SyHashInit(&pClass->hMethod,&pVm->sAllocator,0,0);
SyHashInit(&pClass->hAttr,&pVm->sAllocator,0,0);
SyHashInit(&pClass->hDerived,&pVm->sAllocator,0,0);
SySetInit(&pClass->aInterface,&pVm->sAllocator,sizeof(ph7_class *));
SyStringInitFromBuf(&pClass->sName, zName, pName->nByte);
SyHashInit(&pClass->hMethod, &pVm->sAllocator, 0, 0);
SyHashInit(&pClass->hAttr, &pVm->sAllocator, 0, 0);
SyHashInit(&pClass->hDerived, &pVm->sAllocator, 0, 0);
SySetInit(&pClass->aInterface, &pVm->sAllocator, sizeof(ph7_class *));
pClass->nLine = nLine;
/* All done */
return pClass;
@ -50,25 +49,24 @@ PH7_PRIVATE ph7_class * PH7_NewRawClass(ph7_vm *pVm,const SyString *pName,sxu32
* Allocate and initialize a new class attribute.
* Return a pointer to the class attribute on success. NULL otherwise.
*/
PH7_PRIVATE ph7_class_attr * PH7_NewClassAttr(ph7_vm *pVm,const SyString *pName,sxu32 nLine,sxi32 iProtection,sxi32 iFlags)
{
PH7_PRIVATE ph7_class_attr *PH7_NewClassAttr(ph7_vm *pVm, const SyString *pName, sxu32 nLine, sxi32 iProtection, sxi32 iFlags) {
ph7_class_attr *pAttr;
char *zName;
pAttr = (ph7_class_attr *)SyMemBackendPoolAlloc(&pVm->sAllocator,sizeof(ph7_class_attr));
if( pAttr == 0 ){
pAttr = (ph7_class_attr *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_attr));
if(pAttr == 0) {
return 0;
}
/* Zero the structure */
SyZero(pAttr,sizeof(ph7_class_attr));
SyZero(pAttr, sizeof(ph7_class_attr));
/* Duplicate attribute name */
zName = SyMemBackendStrDup(&pVm->sAllocator,pName->zString,pName->nByte);
if( zName == 0 ){
SyMemBackendPoolFree(&pVm->sAllocator,pAttr);
zName = SyMemBackendStrDup(&pVm->sAllocator, pName->zString, pName->nByte);
if(zName == 0) {
SyMemBackendPoolFree(&pVm->sAllocator, pAttr);
return 0;
}
/* Initialize fields */
SySetInit(&pAttr->aByteCode,&pVm->sAllocator,sizeof(VmInstr));
SyStringInitFromBuf(&pAttr->sName,zName,pName->nByte);
SySetInit(&pAttr->aByteCode, &pVm->sAllocator, sizeof(VmInstr));
SyStringInitFromBuf(&pAttr->sName, zName, pName->nByte);
pAttr->iProtection = iProtection;
pAttr->nIdx = SXU32_HIGH;
pAttr->iFlags = iFlags;
@ -81,9 +79,8 @@ PH7_PRIVATE ph7_class_attr * PH7_NewClassAttr(ph7_vm *pVm,const SyString *pName,
* This function associate with the newly created method an automatically generated
* random unique name.
*/
PH7_PRIVATE ph7_class_method * PH7_NewClassMethod(ph7_vm *pVm,ph7_class *pClass,const SyString *pName,sxu32 nLine,
sxi32 iProtection,sxi32 iFlags,sxi32 iFuncFlags)
{
PH7_PRIVATE ph7_class_method *PH7_NewClassMethod(ph7_vm *pVm, ph7_class *pClass, const SyString *pName, sxu32 nLine,
sxi32 iProtection, sxi32 iFlags, sxi32 iFuncFlags) {
ph7_class_method *pMeth;
SyHashEntry *pEntry;
SyString *pNamePtr;
@ -91,61 +88,60 @@ PH7_PRIVATE ph7_class_method * PH7_NewClassMethod(ph7_vm *pVm,ph7_class *pClass,
char *zName;
sxu32 nByte;
/* Allocate a new class method instance */
pMeth = (ph7_class_method *)SyMemBackendPoolAlloc(&pVm->sAllocator,sizeof(ph7_class_method));
if( pMeth == 0 ){
pMeth = (ph7_class_method *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_method));
if(pMeth == 0) {
return 0;
}
/* Zero the structure */
SyZero(pMeth,sizeof(ph7_class_method));
SyZero(pMeth, sizeof(ph7_class_method));
/* Check for an already installed method with the same name */
pEntry = SyHashGet(&pClass->hMethod,(const void *)pName->zString,pName->nByte);
if( pEntry == 0 ){
pEntry = SyHashGet(&pClass->hMethod, (const void *)pName->zString, pName->nByte);
if(pEntry == 0) {
/* Associate an unique VM name to this method */
nByte = sizeof(zSalt) + pName->nByte + SyStringLength(&pClass->sName)+sizeof(char)*7/*[[__'\0'*/;
zName = (char *)SyMemBackendAlloc(&pVm->sAllocator,nByte);
if( zName == 0 ){
SyMemBackendPoolFree(&pVm->sAllocator,pMeth);
nByte = sizeof(zSalt) + pName->nByte + SyStringLength(&pClass->sName) + sizeof(char) * 7/*[[__'\0'*/;
zName = (char *)SyMemBackendAlloc(&pVm->sAllocator, nByte);
if(zName == 0) {
SyMemBackendPoolFree(&pVm->sAllocator, pMeth);
return 0;
}
pNamePtr = &pMeth->sVmName;
/* Generate a random string */
PH7_VmRandomString(&(*pVm),zSalt,sizeof(zSalt));
pNamePtr->nByte = SyBufferFormat(zName,nByte,"[__%z@%z_%.*s]",&pClass->sName,pName,sizeof(zSalt),zSalt);
PH7_VmRandomString(&(*pVm), zSalt, sizeof(zSalt));
pNamePtr->nByte = SyBufferFormat(zName, nByte, "[__%z@%z_%.*s]", &pClass->sName, pName, sizeof(zSalt), zSalt);
pNamePtr->zString = zName;
}else{
} else {
/* Method is condidate for 'overloading' */
ph7_class_method *pCurrent = (ph7_class_method *)pEntry->pUserData;
pNamePtr = &pMeth->sVmName;
/* Use the same VM name */
SyStringDupPtr(pNamePtr,&pCurrent->sVmName);
SyStringDupPtr(pNamePtr, &pCurrent->sVmName);
zName = (char *)pNamePtr->zString;
}
if( iProtection != PH7_CLASS_PROT_PUBLIC ){
if( (pName->nByte == sizeof("__construct") - 1 && SyMemcmp(pName->zString,"__construct",sizeof("__construct") - 1 ) == 0)
|| (pName->nByte == sizeof("__destruct") - 1 && SyMemcmp(pName->zString,"__destruct",sizeof("__destruct") - 1 ) == 0)
|| SyStringCmp(pName,&pClass->sName,SyMemcmp) == 0 ){
/* Switch to public visibility when dealing with constructor/destructor */
iProtection = PH7_CLASS_PROT_PUBLIC;
if(iProtection != PH7_CLASS_PROT_PUBLIC) {
if((pName->nByte == sizeof("__construct") - 1 && SyMemcmp(pName->zString, "__construct", sizeof("__construct") - 1) == 0)
|| (pName->nByte == sizeof("__destruct") - 1 && SyMemcmp(pName->zString, "__destruct", sizeof("__destruct") - 1) == 0)
|| SyStringCmp(pName, &pClass->sName, SyMemcmp) == 0) {
/* Switch to public visibility when dealing with constructor/destructor */
iProtection = PH7_CLASS_PROT_PUBLIC;
}
}
/* Initialize method fields */
pMeth->iProtection = iProtection;
pMeth->iFlags = iFlags;
pMeth->nLine = nLine;
PH7_VmInitFuncState(&(*pVm),&pMeth->sFunc,&zName[sizeof(char)*4/*[__@*/+SyStringLength(&pClass->sName)],
pName->nByte,iFuncFlags|VM_FUNC_CLASS_METHOD,pClass);
PH7_VmInitFuncState(&(*pVm), &pMeth->sFunc, &zName[sizeof(char) * 4/*[__@*/ + SyStringLength(&pClass->sName)],
pName->nByte, iFuncFlags | VM_FUNC_CLASS_METHOD, pClass);
return pMeth;
}
/*
* Check if the given name have a class method associated with it.
* Return the desired method [i.e: ph7_class_method instance] on success. NULL otherwise.
*/
PH7_PRIVATE ph7_class_method * PH7_ClassExtractMethod(ph7_class *pClass,const char *zName,sxu32 nByte)
{
PH7_PRIVATE ph7_class_method *PH7_ClassExtractMethod(ph7_class *pClass, const char *zName, sxu32 nByte) {
SyHashEntry *pEntry;
/* Perform a hash lookup */
pEntry = SyHashGet(&pClass->hMethod,(const void *)zName,nByte);
if( pEntry == 0 ){
pEntry = SyHashGet(&pClass->hMethod, (const void *)zName, nByte);
if(pEntry == 0) {
/* No such entry */
return 0;
}
@ -156,12 +152,11 @@ PH7_PRIVATE ph7_class_method * PH7_ClassExtractMethod(ph7_class *pClass,const ch
* Check if the given name is a class attribute.
* Return the desired attribute [i.e: ph7_class_attr instance] on success.NULL otherwise.
*/
PH7_PRIVATE ph7_class_attr * PH7_ClassExtractAttribute(ph7_class *pClass,const char *zName,sxu32 nByte)
{
PH7_PRIVATE ph7_class_attr *PH7_ClassExtractAttribute(ph7_class *pClass, const char *zName, sxu32 nByte) {
SyHashEntry *pEntry;
/* Perform a hash lookup */
pEntry = SyHashGet(&pClass->hAttr,(const void *)zName,nByte);
if( pEntry == 0 ){
pEntry = SyHashGet(&pClass->hAttr, (const void *)zName, nByte);
if(pEntry == 0) {
/* No such entry */
return 0;
}
@ -172,22 +167,20 @@ PH7_PRIVATE ph7_class_attr * PH7_ClassExtractAttribute(ph7_class *pClass,const c
* Install a class attribute in the corresponding container.
* Return SXRET_OK on success. Any other return value indicates failure.
*/
PH7_PRIVATE sxi32 PH7_ClassInstallAttr(ph7_class *pClass,ph7_class_attr *pAttr)
{
PH7_PRIVATE sxi32 PH7_ClassInstallAttr(ph7_class *pClass, ph7_class_attr *pAttr) {
SyString *pName = &pAttr->sName;
sxi32 rc;
rc = SyHashInsert(&pClass->hAttr,(const void *)pName->zString,pName->nByte,pAttr);
rc = SyHashInsert(&pClass->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
return rc;
}
/*
* Install a class method in the corresponding container.
* Return SXRET_OK on success. Any other return value indicates failure.
*/
PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass,ph7_class_method *pMeth)
{
PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass, ph7_class_method *pMeth) {
SyString *pName = &pMeth->sFunc.sName;
sxi32 rc;
rc = SyHashInsert(&pClass->hMethod,(const void *)pName->zString,pName->nByte,pMeth);
rc = SyHashInsert(&pClass->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
return rc;
}
/*
@ -207,7 +200,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass,ph7_class_method *pMe
* {
* echo 'Foo: ' . $string . PHP_EOL;
* }
*
*
* public function printPHP()
* {
* echo 'PHP is great.' . PHP_EOL;
@ -223,7 +216,7 @@ PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass,ph7_class_method *pMe
* $foo = new foo();
* $bar = new bar();
* $foo->printItem('baz'); // Output: 'Foo: baz'
* $foo->printPHP(); // Output: 'PHP is great'
* $foo->printPHP(); // Output: 'PHP is great'
* $bar->printItem('baz'); // Output: 'Bar: baz'
* $bar->printPHP(); // Output: 'PHP is great'
*
@ -231,72 +224,70 @@ PH7_PRIVATE sxi32 PH7_ClassInstallMethod(ph7_class *pClass,ph7_class_method *pMe
* Any other return value indicates failure and the upper layer must generate an appropriate
* error message.
*/
PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_gen_state *pGen,ph7_class *pSub,ph7_class *pBase)
{
PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_gen_state *pGen, ph7_class *pSub, ph7_class *pBase) {
ph7_class_method *pMeth;
ph7_class_attr *pAttr;
SyHashEntry *pEntry;
SyString *pName;
sxi32 rc;
/* Install in the derived hashtable */
rc = SyHashInsert(&pBase->hDerived,(const void *)SyStringData(&pSub->sName),SyStringLength(&pSub->sName),pSub);
if( rc != SXRET_OK ){
rc = SyHashInsert(&pBase->hDerived, (const void *)SyStringData(&pSub->sName), SyStringLength(&pSub->sName), pSub);
if(rc != SXRET_OK) {
return rc;
}
/* Copy public/protected attributes from the base class */
SyHashResetLoopCursor(&pBase->hAttr);
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0 ){
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0) {
/* Make sure the private attributes are not redeclared in the subclass */
pAttr = (ph7_class_attr *)pEntry->pUserData;
pName = &pAttr->sName;
if( (pEntry = SyHashGet(&pSub->hAttr,(const void *)pName->zString,pName->nByte)) != 0 ){
if( pAttr->iProtection == PH7_CLASS_PROT_PRIVATE &&
((ph7_class_attr *)pEntry->pUserData)->iProtection != PH7_CLASS_PROT_PUBLIC ){
/* Cannot redeclare private attribute */
PH7_GenCompileError(&(*pGen),E_WARNING,((ph7_class_attr *)pEntry->pUserData)->nLine,
"Private attribute '%z::%z' redeclared inside child class '%z'",
&pBase->sName,pName,&pSub->sName);
if((pEntry = SyHashGet(&pSub->hAttr, (const void *)pName->zString, pName->nByte)) != 0) {
if(pAttr->iProtection == PH7_CLASS_PROT_PRIVATE &&
((ph7_class_attr *)pEntry->pUserData)->iProtection != PH7_CLASS_PROT_PUBLIC) {
/* Cannot redeclare private attribute */
PH7_GenCompileError(&(*pGen), E_WARNING, ((ph7_class_attr *)pEntry->pUserData)->nLine,
"Private attribute '%z::%z' redeclared inside child class '%z'",
&pBase->sName, pName, &pSub->sName);
}
continue;
}
/* Install the attribute */
if( pAttr->iProtection != PH7_CLASS_PROT_PRIVATE ){
rc = SyHashInsert(&pSub->hAttr,(const void *)pName->zString,pName->nByte,pAttr);
if( rc != SXRET_OK ){
if(pAttr->iProtection != PH7_CLASS_PROT_PRIVATE) {
rc = SyHashInsert(&pSub->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
if(rc != SXRET_OK) {
return rc;
}
}
}
SyHashResetLoopCursor(&pBase->hMethod);
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0 ){
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0) {
/* Make sure the private/final methods are not redeclared in the subclass */
pMeth = (ph7_class_method *)pEntry->pUserData;
pName = &pMeth->sFunc.sName;
if( (pEntry = SyHashGet(&pSub->hMethod,(const void *)pName->zString,pName->nByte)) != 0 ){
if( pMeth->iFlags & PH7_CLASS_ATTR_FINAL ){
if((pEntry = SyHashGet(&pSub->hMethod, (const void *)pName->zString, pName->nByte)) != 0) {
if(pMeth->iFlags & PH7_CLASS_ATTR_FINAL) {
/* Cannot Overwrite final method */
rc = PH7_GenCompileError(&(*pGen),E_ERROR,((ph7_class_method *)pEntry->pUserData)->nLine,
"Cannot Overwrite final method '%z:%z' inside child class '%z'",
&pBase->sName,pName,&pSub->sName);
if( rc == SXERR_ABORT ){
rc = PH7_GenCompileError(&(*pGen), E_ERROR, ((ph7_class_method *)pEntry->pUserData)->nLine,
"Cannot Overwrite final method '%z:%z' inside child class '%z'",
&pBase->sName, pName, &pSub->sName);
if(rc == SXERR_ABORT) {
return SXERR_ABORT;
}
}
continue;
}else{
if( pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT ){
} else {
if(pMeth->iFlags & PH7_CLASS_ATTR_ABSTRACT) {
/* Abstract method must be defined in the child class */
PH7_GenCompileError(&(*pGen),E_WARNING,pMeth->nLine,
"Abstract method '%z:%z' must be defined inside child class '%z'",
&pBase->sName,pName,&pSub->sName);
PH7_GenCompileError(&(*pGen), E_WARNING, pMeth->nLine,
"Abstract method '%z:%z' must be defined inside child class '%z'",
&pBase->sName, pName, &pSub->sName);
continue;
}
}
/* Install the method */
if( pMeth->iProtection != PH7_CLASS_PROT_PRIVATE ){
rc = SyHashInsert(&pSub->hMethod,(const void *)pName->zString,pName->nByte,pMeth);
if( rc != SXRET_OK ){
if(pMeth->iProtection != PH7_CLASS_PROT_PRIVATE) {
rc = SyHashInsert(&pSub->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
if(rc != SXRET_OK) {
return rc;
}
}
@ -319,39 +310,38 @@ PH7_PRIVATE sxi32 PH7_ClassInherit(ph7_gen_state *pGen,ph7_class *pSub,ph7_class
* Any other return value indicates failure and the upper layer must generate an appropriate
* error message.
*/
PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub,ph7_class *pBase)
{
PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub, ph7_class *pBase) {
ph7_class_method *pMeth;
ph7_class_attr *pAttr;
SyHashEntry *pEntry;
SyString *pName;
sxi32 rc;
/* Install in the derived hashtable */
SyHashInsert(&pBase->hDerived,(const void *)SyStringData(&pSub->sName),SyStringLength(&pSub->sName),pSub);
SyHashInsert(&pBase->hDerived, (const void *)SyStringData(&pSub->sName), SyStringLength(&pSub->sName), pSub);
SyHashResetLoopCursor(&pBase->hAttr);
/* Copy constants */
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0 ){
while((pEntry = SyHashGetNextEntry(&pBase->hAttr)) != 0) {
/* Make sure the constants are not redeclared in the subclass */
pAttr = (ph7_class_attr *)pEntry->pUserData;
pName = &pAttr->sName;
if( SyHashGet(&pSub->hAttr,(const void *)pName->zString,pName->nByte) == 0 ){
if(SyHashGet(&pSub->hAttr, (const void *)pName->zString, pName->nByte) == 0) {
/* Install the constant in the subclass */
rc = SyHashInsert(&pSub->hAttr,(const void *)pName->zString,pName->nByte,pAttr);
if( rc != SXRET_OK ){
rc = SyHashInsert(&pSub->hAttr, (const void *)pName->zString, pName->nByte, pAttr);
if(rc != SXRET_OK) {
return rc;
}
}
}
SyHashResetLoopCursor(&pBase->hMethod);
/* Copy methods signature */
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0 ){
while((pEntry = SyHashGetNextEntry(&pBase->hMethod)) != 0) {
/* Make sure the method are not redeclared in the subclass */
pMeth = (ph7_class_method *)pEntry->pUserData;
pName = &pMeth->sFunc.sName;
if( SyHashGet(&pSub->hMethod,(const void *)pName->zString,pName->nByte) == 0 ){
if(SyHashGet(&pSub->hMethod, (const void *)pName->zString, pName->nByte) == 0) {
/* Install the method */
rc = SyHashInsert(&pSub->hMethod,(const void *)pName->zString,pName->nByte,pMeth);
if( rc != SXRET_OK ){
rc = SyHashInsert(&pSub->hMethod, (const void *)pName->zString, pName->nByte, pMeth);
if(rc != SXRET_OK) {
return rc;
}
}
@ -374,30 +364,29 @@ PH7_PRIVATE sxi32 PH7_ClassInterfaceInherit(ph7_class *pSub,ph7_class *pBase)
* Any other return value indicates failure and the upper layer must generate an appropriate
* error message.
*/
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain,ph7_class *pInterface)
{
PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain, ph7_class *pInterface) {
ph7_class_attr *pAttr;
SyHashEntry *pEntry;
SyString *pName;
sxi32 rc;
/* First off,copy all constants declared inside the interface */
SyHashResetLoopCursor(&pInterface->hAttr);
while((pEntry = SyHashGetNextEntry(&pInterface->hAttr)) != 0 ){
while((pEntry = SyHashGetNextEntry(&pInterface->hAttr)) != 0) {
/* Point to the constant declaration */
pAttr = (ph7_class_attr *)pEntry->pUserData;
pName = &pAttr->sName;
/* Make sure the attribute is not redeclared in the main class */
if( SyHashGet(&pMain->hAttr,pName->zString,pName->nByte) == 0 ){
if(SyHashGet(&pMain->hAttr, pName->zString, pName->nByte) == 0) {
/* Install the attribute */
rc = SyHashInsert(&pMain->hAttr,pName->zString,pName->nByte,pAttr);
if( rc != SXRET_OK ){
rc = SyHashInsert(&pMain->hAttr, pName->zString, pName->nByte, pAttr);
if(rc != SXRET_OK) {
return rc;
}
}
}
/* Install in the interface container */
SySetPut(&pMain->aInterface,(const void *)&pInterface);
/* TICKET 1433-49/1: Symisc eXtension
SySetPut(&pMain->aInterface, (const void *)&pInterface);
/* TICKET 1433-49/1: Symisc eXtension
* A class may not implemnt all declared interface methods,so there
* is no need for a method installer loop here.
*/
@ -426,7 +415,7 @@ PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain,ph7_class *pInterface)
* In the class context, it is possible to create a new object by new self and new parent.
* When assigning an already created instance of a class to a new variable, the new variable
* will access the same instance as the object that was assigned. This behaviour is the same
* when passing instances to a function. A copy of an already created object can be made by
* when passing instances to a function. A copy of an already created object can be made by
* cloning it.
* Example #4 Object Assignment
* <?php
@ -451,7 +440,7 @@ PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain,ph7_class *pInterface)
* }
* Example #5 Creating new objects
* <?php
* class Test
* class Test
* {
* static public function getNew()
* {
@ -482,39 +471,37 @@ PH7_PRIVATE sxi32 PH7_ClassImplement(ph7_class *pMain,ph7_class *pInterface)
* };
* Refer to the official documentation for more information.
*/
static ph7_class_instance * NewClassInstance(ph7_vm *pVm,ph7_class *pClass)
{
static ph7_class_instance *NewClassInstance(ph7_vm *pVm, ph7_class *pClass) {
ph7_class_instance *pThis;
/* Allocate a new instance */
pThis = (ph7_class_instance *)SyMemBackendPoolAlloc(&pVm->sAllocator,sizeof(ph7_class_instance));
if( pThis == 0 ){
pThis = (ph7_class_instance *)SyMemBackendPoolAlloc(&pVm->sAllocator, sizeof(ph7_class_instance));
if(pThis == 0) {
return 0;
}
/* Zero the structure */
SyZero(pThis,sizeof(ph7_class_instance));
SyZero(pThis, sizeof(ph7_class_instance));
/* Initialize fields */
pThis->iRef = 1;
pThis->pVm = pVm;
pThis->pClass = pClass;
SyHashInit(&pThis->hAttr,&pVm->sAllocator,0,0);
SyHashInit(&pThis->hAttr, &pVm->sAllocator, 0, 0);
return pThis;
}
/*
* Wrapper around the NewClassInstance() function defined above.
* See the block comment above for more information.
*/
PH7_PRIVATE ph7_class_instance * PH7_NewClassInstance(ph7_vm *pVm,ph7_class *pClass)
{
PH7_PRIVATE ph7_class_instance *PH7_NewClassInstance(ph7_vm *pVm, ph7_class *pClass) {
ph7_class_instance *pNew;
sxi32 rc;
pNew = NewClassInstance(&(*pVm),&(*pClass));
if( pNew == 0 ){
pNew = NewClassInstance(&(*pVm), &(*pClass));
if(pNew == 0) {
return 0;
}
/* Associate a private VM frame with this class instance */
rc = PH7_VmCreateClassInstanceFrame(&(*pVm),pNew);
if( rc != SXRET_OK ){
SyMemBackendPoolFree(&pVm->sAllocator,pNew);
rc = PH7_VmCreateClassInstanceFrame(&(*pVm), pNew);
if(rc != SXRET_OK) {
SyMemBackendPoolFree(&pVm->sAllocator, pNew);
return 0;
}
return pNew;
@ -523,11 +510,10 @@ PH7_PRIVATE ph7_class_instance * PH7_NewClassInstance(ph7_vm *pVm,ph7_class *pCl
* Extract the value of a class instance [i.e: Object in the PHP jargon] attribute.
* This function never fail.
*/
static ph7_value * ExtractClassAttrValue(ph7_vm *pVm,VmClassAttr *pAttr)
{
static ph7_value *ExtractClassAttrValue(ph7_vm *pVm, VmClassAttr *pAttr) {
/* Extract the value */
ph7_value *pValue;
pValue = (ph7_value *)SySetAt(&pVm->aMemObj,pAttr->nIdx);
pValue = (ph7_value *)SySetAt(&pVm->aMemObj, pAttr->nIdx);
return pValue;
}
/*
@ -539,14 +525,14 @@ static ph7_value * ExtractClassAttrValue(ph7_vm *pVm,VmClassAttr *pAttr)
* According to PHP language reference manual.
* Creating a copy of an object with fully replicated properties is not always the wanted behavior.
* A good example of the need for copy constructors. Another example is if your object holds a reference
* to another object which it uses and when you replicate the parent object you want to create
* to another object which it uses and when you replicate the parent object you want to create
* a new instance of this other object so that the replica has its own separate copy.
* An object copy is created by using the clone keyword (which calls the object's __clone() method if possible).
* An object's __clone() method cannot be called directly.
* $copy_of_object = clone $object;
* When an object is cloned, PHP 5 will perform a shallow copy of all of the object's properties.
* Any properties that are references to other variables, will remain references.
* Once the cloning is complete, if a __clone() method is defined, then the newly created object's __clone() method
* Once the cloning is complete, if a __clone() method is defined, then the newly created object's __clone() method
* will be called, to allow any necessary properties that need to be changed.
* Example #1 Cloning an object
* <?php
@ -563,7 +549,7 @@ static ph7_value * ExtractClassAttrValue(ph7_vm *pVm,VmClassAttr *pAttr)
* $this->instance = ++self::$instances;
* }
* }
*
*
* class MyCloneable
* {
* public $object1;
@ -614,8 +600,7 @@ static ph7_value * ExtractClassAttrValue(ph7_vm *pVm,VmClassAttr *pAttr)
* )
* )
*/
PH7_PRIVATE ph7_class_instance * PH7_CloneClassInstance(ph7_class_instance *pSrc)
{
PH7_PRIVATE ph7_class_instance *PH7_CloneClassInstance(ph7_class_instance *pSrc) {
ph7_class_instance *pClone;
ph7_class_method *pMethod;
SyHashEntry *pEntry2;
@ -624,41 +609,41 @@ PH7_PRIVATE ph7_class_instance * PH7_CloneClassInstance(ph7_class_instance *pSrc
sxi32 rc;
/* Allocate a new instance */
pVm = pSrc->pVm;
pClone = NewClassInstance(pVm,pSrc->pClass);
if( pClone == 0 ){
pClone = NewClassInstance(pVm, pSrc->pClass);
if(pClone == 0) {
return 0;
}
/* Associate a private VM frame with this class instance */
rc = PH7_VmCreateClassInstanceFrame(pVm,pClone);
if( rc != SXRET_OK ){
SyMemBackendPoolFree(&pVm->sAllocator,pClone);
rc = PH7_VmCreateClassInstanceFrame(pVm, pClone);
if(rc != SXRET_OK) {
SyMemBackendPoolFree(&pVm->sAllocator, pClone);
return 0;
}
/* Duplicate object values */
SyHashResetLoopCursor(&pSrc->hAttr);
SyHashResetLoopCursor(&pClone->hAttr);
while((pEntry = SyHashGetNextEntry(&pSrc->hAttr)) != 0 && (pEntry2 = SyHashGetNextEntry(&pClone->hAttr)) != 0 ){
while((pEntry = SyHashGetNextEntry(&pSrc->hAttr)) != 0 && (pEntry2 = SyHashGetNextEntry(&pClone->hAttr)) != 0) {
VmClassAttr *pSrcAttr = (VmClassAttr *)pEntry->pUserData;
VmClassAttr *pDestAttr = (VmClassAttr *)pEntry2->pUserData;
/* Duplicate non-static attribute */
if( (pSrcAttr->pAttr->iFlags & (PH7_CLASS_ATTR_STATIC|PH7_CLASS_ATTR_CONSTANT)) == 0 ){
ph7_value *pvSrc,*pvDest;
pvSrc = ExtractClassAttrValue(pVm,pSrcAttr);
pvDest = ExtractClassAttrValue(pVm,pDestAttr);
if( pvSrc && pvDest ){
PH7_MemObjStore(pvSrc,pvDest);
if((pSrcAttr->pAttr->iFlags & (PH7_CLASS_ATTR_STATIC | PH7_CLASS_ATTR_CONSTANT)) == 0) {
ph7_value *pvSrc, *pvDest;
pvSrc = ExtractClassAttrValue(pVm, pSrcAttr);
pvDest = ExtractClassAttrValue(pVm, pDestAttr);
if(pvSrc && pvDest) {
PH7_MemObjStore(pvSrc, pvDest);
}
}
}
/* call the __clone method on the cloned object if available */
pMethod = PH7_ClassExtractMethod(pClone->pClass,"__clone",sizeof("__clone")-1);
if( pMethod ){
if( pMethod->iCloneDepth < 16 ){
pMethod = PH7_ClassExtractMethod(pClone->pClass, "__clone", sizeof("__clone") - 1);
if(pMethod) {
if(pMethod->iCloneDepth < 16) {
pMethod->iCloneDepth++;
PH7_VmCallClassMethod(pVm,pClone,pMethod,0,0,0);
}else{
PH7_VmCallClassMethod(pVm, pClone, pMethod, 0, 0, 0);
} else {
/* Nesting limit reached */
PH7_VmThrowError(pVm,0,PH7_CTX_ERR,"Object clone limit reached,no more call to __clone()");
PH7_VmThrowError(pVm, 0, PH7_CTX_ERR, "Object clone limit reached,no more call to __clone()");
}
/* Reset the cursor */
pMethod->iCloneDepth = 0;
@ -672,13 +657,12 @@ PH7_PRIVATE ph7_class_instance * PH7_CloneClassInstance(ph7_class_instance *pSrc
* This routine is invoked as soon as there are no other references to a particular
* class instance.
*/
static void PH7_ClassInstanceRelease(ph7_class_instance *pThis)
{
static void PH7_ClassInstanceRelease(ph7_class_instance *pThis) {
ph7_class_method *pDestr;
SyHashEntry *pEntry;
ph7_class *pClass;
ph7_vm *pVm;
if( pThis->iFlags & CLASS_INSTANCE_DESTROYED ){
if(pThis->iFlags & CLASS_INSTANCE_DESTROYED) {
/*
* Already destroyed,return immediately.
* This could happend if someone perform unset($this) in the destructor body.
@ -690,33 +674,32 @@ static void PH7_ClassInstanceRelease(ph7_class_instance *pThis)
/* Invoke any defined destructor if available */
pVm = pThis->pVm;
pClass = pThis->pClass;
pDestr = PH7_ClassExtractMethod(pClass,"__destruct",sizeof("__destruct")-1);
if( pDestr ){
pDestr = PH7_ClassExtractMethod(pClass, "__destruct", sizeof("__destruct") - 1);
if(pDestr) {
/* Invoke the destructor */
pThis->iRef = 2; /* Prevent garbage collection */
PH7_VmCallClassMethod(pVm,pThis,pDestr,0,0,0);
PH7_VmCallClassMethod(pVm, pThis, pDestr, 0, 0, 0);
}
/* Release non-static attributes */
SyHashResetLoopCursor(&pThis->hAttr);
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0 ){
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
VmClassAttr *pVmAttr = (VmClassAttr *)pEntry->pUserData;
if( (pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_STATIC|PH7_CLASS_ATTR_CONSTANT)) == 0 ){
PH7_VmUnsetMemObj(pVm,pVmAttr->nIdx,TRUE);
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_STATIC | PH7_CLASS_ATTR_CONSTANT)) == 0) {
PH7_VmUnsetMemObj(pVm, pVmAttr->nIdx, TRUE);
}
SyMemBackendPoolFree(&pVm->sAllocator,pVmAttr);
SyMemBackendPoolFree(&pVm->sAllocator, pVmAttr);
}
/* Release the whole structure */
SyHashRelease(&pThis->hAttr);
SyMemBackendPoolFree(&pVm->sAllocator,pThis);
SyMemBackendPoolFree(&pVm->sAllocator, pThis);
}
/*
* Decrement the reference count of a class instance [i.e Object in the PHP jargon].
* If the reference count reaches zero,release the whole instance.
*/
PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis)
{
PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis) {
pThis->iRef--;
if( pThis->iRef < 1 ){
if(pThis->iRef < 1) {
/* No more reference to this instance */
PH7_ClassInstanceRelease(&(*pThis));
}
@ -765,7 +748,7 @@ PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis)
* $this->flag = $flag;
* }
* }
*
*
* $o = new Flag();
* $p = new Flag();
* $q = $o;
@ -798,21 +781,20 @@ PH7_PRIVATE void PH7_ClassInstanceUnref(ph7_class_instance *pThis)
* This function return 0 if the objects are equals according to the comprison rules defined above.
* Any other return values indicates difference.
*/
PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft,ph7_class_instance *pRight,int bStrict,int iNest)
{
SyHashEntry *pEntry,*pEntry2;
ph7_value sV1,sV2;
PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft, ph7_class_instance *pRight, int bStrict, int iNest) {
SyHashEntry *pEntry, *pEntry2;
ph7_value sV1, sV2;
sxi32 rc;
if( iNest > 31 ){
if(iNest > 31) {
/* Nesting limit reached */
PH7_VmThrowError(pLeft->pVm,0,PH7_CTX_ERR,"Nesting limit reached: Infinite recursion?");
PH7_VmThrowError(pLeft->pVm, 0, PH7_CTX_ERR, "Nesting limit reached: Infinite recursion?");
return 1;
}
/* Comparison is performed only if the objects are instance of the same class */
if( pLeft->pClass != pRight->pClass ){
if(pLeft->pClass != pRight->pClass) {
return 1;
}
if( bStrict ){
if(bStrict) {
/*
* According to the PHP language reference manual:
* when using the identity operator (===), object variables
@ -824,35 +806,35 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft,ph7_class_insta
/*
* Attribute comparison.
* According to the PHP reference manual:
* When using the comparison operator (==), object variables are compared
* When using the comparison operator (==), object variables are compared
* in a simple manner, namely: Two object instances are equal if they have
* the same attributes and values, and are instances of the same class.
* the same attributes and values, and are instances of the same class.
*/
if( pLeft == pRight ){
if(pLeft == pRight) {
/* Same instance,don't bother processing,object are equals */
return 0;
}
SyHashResetLoopCursor(&pLeft->hAttr);
SyHashResetLoopCursor(&pRight->hAttr);
PH7_MemObjInit(pLeft->pVm,&sV1);
PH7_MemObjInit(pLeft->pVm,&sV2);
PH7_MemObjInit(pLeft->pVm, &sV1);
PH7_MemObjInit(pLeft->pVm, &sV2);
sV1.nIdx = sV2.nIdx = SXU32_HIGH;
while((pEntry = SyHashGetNextEntry(&pLeft->hAttr)) != 0 && (pEntry2 = SyHashGetNextEntry(&pRight->hAttr)) != 0 ){
while((pEntry = SyHashGetNextEntry(&pLeft->hAttr)) != 0 && (pEntry2 = SyHashGetNextEntry(&pRight->hAttr)) != 0) {
VmClassAttr *p1 = (VmClassAttr *)pEntry->pUserData;
VmClassAttr *p2 = (VmClassAttr *)pEntry2->pUserData;
/* Compare only non-static attribute */
if( (p1->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT|PH7_CLASS_ATTR_STATIC)) == 0 ){
ph7_value *pL,*pR;
pL = ExtractClassAttrValue(pLeft->pVm,p1);
pR = ExtractClassAttrValue(pRight->pVm,p2);
if( pL && pR ){
PH7_MemObjLoad(pL,&sV1);
PH7_MemObjLoad(pR,&sV2);
if((p1->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) == 0) {
ph7_value *pL, *pR;
pL = ExtractClassAttrValue(pLeft->pVm, p1);
pR = ExtractClassAttrValue(pRight->pVm, p2);
if(pL && pR) {
PH7_MemObjLoad(pL, &sV1);
PH7_MemObjLoad(pR, &sV2);
/* Compare the two values now */
rc = PH7_MemObjCmp(&sV1,&sV2,bStrict,iNest+1);
rc = PH7_MemObjCmp(&sV1, &sV2, bStrict, iNest + 1);
PH7_MemObjRelease(&sV1);
PH7_MemObjRelease(&sV2);
if( rc != 0 ){
if(rc != 0) {
/* Not equals */
return rc;
}
@ -871,60 +853,59 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCmp(ph7_class_instance *pLeft,ph7_class_insta
* This function SXRET_OK on success. Any other return value including
* SXERR_LIMIT(infinite recursion) indicates failure.
*/
PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut,ph7_class_instance *pThis,int ShowType,int nTab,int nDepth)
{
PH7_PRIVATE sxi32 PH7_ClassInstanceDump(SyBlob *pOut, ph7_class_instance *pThis, int ShowType, int nTab, int nDepth) {
SyHashEntry *pEntry;
ph7_value *pValue;
sxi32 rc;
int i;
if( nDepth > 31 ){
if(nDepth > 31) {
static const char zInfinite[] = "Nesting limit reached: Infinite recursion?";
/* Nesting limit reached..halt immediately*/
SyBlobAppend(&(*pOut),zInfinite,sizeof(zInfinite)-1);
if( ShowType ){
SyBlobAppend(&(*pOut),")",sizeof(char));
SyBlobAppend(&(*pOut), zInfinite, sizeof(zInfinite) - 1);
if(ShowType) {
SyBlobAppend(&(*pOut), ")", sizeof(char));
}
return SXERR_LIMIT;
}
rc = SXRET_OK;
if( !ShowType ){
SyBlobAppend(&(*pOut),"Object(",sizeof("Object(")-1);
if(!ShowType) {
SyBlobAppend(&(*pOut), "Object(", sizeof("Object(") - 1);
}
/* Append class name */
SyBlobFormat(&(*pOut),"%z) {",&pThis->pClass->sName);
SyBlobFormat(&(*pOut), "%z) {", &pThis->pClass->sName);
#ifdef __WINNT__
SyBlobAppend(&(*pOut),"\r\n",sizeof("\r\n")-1);
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
#else
SyBlobAppend(&(*pOut),"\n",sizeof(char));
SyBlobAppend(&(*pOut), "\n", sizeof(char));
#endif
/* Dump object attributes */
SyHashResetLoopCursor(&pThis->hAttr);
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0){
while((pEntry = SyHashGetNextEntry(&pThis->hAttr)) != 0) {
VmClassAttr *pVmAttr = (VmClassAttr *)pEntry->pUserData;
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT|PH7_CLASS_ATTR_STATIC)) == 0 ){
if((pVmAttr->pAttr->iFlags & (PH7_CLASS_ATTR_CONSTANT | PH7_CLASS_ATTR_STATIC)) == 0) {
/* Dump non-static/constant attribute only */
for( i = 0 ; i < nTab ; i++ ){
SyBlobAppend(&(*pOut)," ",sizeof(char));
for(i = 0 ; i < nTab ; i++) {
SyBlobAppend(&(*pOut), " ", sizeof(char));
}
pValue = ExtractClassAttrValue(pThis->pVm,pVmAttr);
if( pValue ){
SyBlobFormat(&(*pOut),"['%z'] =>",&pVmAttr->pAttr->sName);
pValue = ExtractClassAttrValue(pThis->pVm, pVmAttr);
if(pValue) {
SyBlobFormat(&(*pOut), "['%z'] =>", &pVmAttr->pAttr->sName);
#ifdef __WINNT__
SyBlobAppend(&(*pOut),"\r\n",sizeof("\r\n")-1);
SyBlobAppend(&(*pOut), "\r\n", sizeof("\r\n") - 1);
#else
SyBlobAppend(&(*pOut),"\n",sizeof(char));
SyBlobAppend(&(*pOut), "\n", sizeof(char));
#endif
rc = PH7_MemObjDump(&(*pOut),pValue,ShowType,nTab+1,nDepth,0);
if( rc == SXERR_LIMIT ){
rc = PH7_MemObjDump(&(*pOut), pValue, ShowType, nTab + 1, nDepth, 0);
if(rc == SXERR_LIMIT) {
break;
}
}
}
}
for( i = 0 ; i < nTab ; i++ ){
SyBlobAppend(&(*pOut)," ",sizeof(char));
for(i = 0 ; i < nTab ; i++) {
SyBlobAppend(&(*pOut), " ", sizeof(char));
}
SyBlobAppend(&(*pOut),"}",sizeof(char));
SyBlobAppend(&(*pOut), "}", sizeof(char));
return rc;
}
/*
@ -975,31 +956,30 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCallMagicMethod(
const char *zMethod, /* Magic method name [i.e: __toString()]*/
sxu32 nByte, /* zMethod length*/
const SyString *pAttrName /* Attribute name */
)
{
ph7_value *apArg[2] = { 0 , 0 };
) {
ph7_value *apArg[2] = { 0, 0 };
ph7_class_method *pMeth;
ph7_value sAttr; /* cc warning */
sxi32 rc;
int nArg;
/* Make sure the magic method is available */
pMeth = PH7_ClassExtractMethod(&(*pClass),zMethod,nByte);
if( pMeth == 0 ){
pMeth = PH7_ClassExtractMethod(&(*pClass), zMethod, nByte);
if(pMeth == 0) {
/* No such method,return immediately */
return SXERR_NOTFOUND;
}
nArg = 0;
/* Copy arguments */
if( pAttrName ){
PH7_MemObjInitFromString(pVm,&sAttr,pAttrName);
if(pAttrName) {
PH7_MemObjInitFromString(pVm, &sAttr, pAttrName);
sAttr.nIdx = SXU32_HIGH; /* Mark as constant */
apArg[0] = &sAttr;
nArg = 1;
}
/* Call the magic method now */
rc = PH7_VmCallClassMethod(pVm,&(*pThis),pMeth,0,nArg,apArg);
rc = PH7_VmCallClassMethod(pVm, &(*pThis), pMeth, 0, nArg, apArg);
/* Clean up */
if( pAttrName ){
if(pAttrName) {
PH7_MemObjRelease(&sAttr);
}
return rc;
@ -1008,11 +988,10 @@ PH7_PRIVATE sxi32 PH7_ClassInstanceCallMagicMethod(
* Extract the value of a class instance [i.e: Object in the PHP jargon].
* This function is simply a wrapper on ExtractClassAttrValue().
*/
PH7_PRIVATE ph7_value * PH7_ClassInstanceExtractAttrValue(ph7_class_instance *pThis,VmClassAttr *pAttr)
{
/* Extract the attribute value */
ph7_value *pValue;
pValue = ExtractClassAttrValue(pThis->pVm,pAttr);
PH7_PRIVATE ph7_value *PH7_ClassInstanceExtractAttrValue(ph7_class_instance *pThis, VmClassAttr *pAttr) {
/* Extract the attribute value */
ph7_value *pValue;
pValue = ExtractClassAttrValue(pThis->pVm, pAttr);
return pValue;
}
/*
@ -1025,7 +1004,7 @@ PH7_PRIVATE ph7_value * PH7_ClassInstanceExtractAttrValue(ph7_class_instance *pT
*