Merge for v0.1.1 #57
							
								
								
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.github/FUNDING.yml
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					custom: https://paypal.me/pools/c/8hAZMn97vE
 | 
				
			||||||
							
								
								
									
										267
									
								
								engine/api.c
									
									
									
									
									
								
							
							
						
						
									
										267
									
								
								engine/api.c
									
									
									
									
									
								
							@@ -27,14 +27,6 @@
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static struct Global_Data {
 | 
					static struct Global_Data {
 | 
				
			||||||
	SyMemBackend sAllocator;                /* Global low level memory allocator */
 | 
						SyMemBackend sAllocator;                /* Global low level memory allocator */
 | 
				
			||||||
	const SyMutexMethods *pMutexMethods;   /* Mutex methods */
 | 
					 | 
				
			||||||
	SyMutex *pMutex;                       /* Global mutex */
 | 
					 | 
				
			||||||
	sxu32 nThreadingLevel;                 /* Threading level: 0 == Single threaded/1 == Multi-Threaded
 | 
					 | 
				
			||||||
										    * The threading level can be set using the [ph7_lib_config()]
 | 
					 | 
				
			||||||
											* interface with a configuration verb set to
 | 
					 | 
				
			||||||
											* PH7_LIB_CONFIG_THREAD_LEVEL_SINGLE or
 | 
					 | 
				
			||||||
											* PH7_LIB_CONFIG_THREAD_LEVEL_MULTI
 | 
					 | 
				
			||||||
											*/
 | 
					 | 
				
			||||||
	const ph7_vfs *pVfs;                    /* Underlying virtual file system */
 | 
						const ph7_vfs *pVfs;                    /* Underlying virtual file system */
 | 
				
			||||||
	sxi32 nEngine;                          /* Total number of active engines */
 | 
						sxi32 nEngine;                          /* Total number of active engines */
 | 
				
			||||||
	ph7 *pEngines;                          /* List of active engine */
 | 
						ph7 *pEngines;                          /* List of active engine */
 | 
				
			||||||
@@ -44,23 +36,9 @@ static struct Global_Data {
 | 
				
			|||||||
	0,
 | 
						0,
 | 
				
			||||||
	0,
 | 
						0,
 | 
				
			||||||
	0,
 | 
						0,
 | 
				
			||||||
	0,
 | 
					 | 
				
			||||||
	0,
 | 
					 | 
				
			||||||
	0,
 | 
					 | 
				
			||||||
	0
 | 
						0
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
#define PH7_LIB_MAGIC  0xEA1495BA
 | 
					#define PH7_LIB_MAGIC  0xEA1495BA
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Supported threading level.
 | 
					 | 
				
			||||||
 * PH7_THREAD_LEVEL_SINGLE:
 | 
					 | 
				
			||||||
 * In this mode,mutexing is disabled and the library can only be used by a single thread.
 | 
					 | 
				
			||||||
 * PH7_THREAD_LEVEL_MULTI
 | 
					 | 
				
			||||||
 * In this mode, all mutexes including the recursive mutexes on [ph7] objects
 | 
					 | 
				
			||||||
 * are enabled so that the application is free to share the same engine
 | 
					 | 
				
			||||||
 * between different threads at the same time.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#define PH7_THREAD_LEVEL_SINGLE 1
 | 
					 | 
				
			||||||
#define PH7_THREAD_LEVEL_MULTI  2
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Configure a running PH7 engine instance.
 | 
					 * Configure a running PH7 engine instance.
 | 
				
			||||||
 * return PH7_OK on success.Any other return
 | 
					 * return PH7_OK on success.Any other return
 | 
				
			||||||
@@ -186,63 +164,6 @@ static sxi32 PH7CoreConfigure(sxi32 nOp, va_list ap) {
 | 
				
			|||||||
				sMPGlobal.sAllocator.pUserData = pUserData;
 | 
									sMPGlobal.sAllocator.pUserData = pUserData;
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		case PH7_LIB_CONFIG_USER_MUTEX: {
 | 
					 | 
				
			||||||
				/* Use an alternative low-level mutex subsystem */
 | 
					 | 
				
			||||||
				const SyMutexMethods *pMethods = va_arg(ap, const SyMutexMethods *);
 | 
					 | 
				
			||||||
				if(pMethods == 0) {
 | 
					 | 
				
			||||||
					rc = PH7_CORRUPT;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				/* Sanity check */
 | 
					 | 
				
			||||||
				if(pMethods->xEnter == 0 || pMethods->xLeave == 0 || pMethods->xNew == 0) {
 | 
					 | 
				
			||||||
					/* At least three criticial callbacks xEnter(),xLeave() and xNew() must be supplied */
 | 
					 | 
				
			||||||
					rc = PH7_CORRUPT;
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				if(sMPGlobal.pMutexMethods) {
 | 
					 | 
				
			||||||
					/* Overwrite the previous mutex subsystem */
 | 
					 | 
				
			||||||
					SyMutexRelease(sMPGlobal.pMutexMethods, sMPGlobal.pMutex);
 | 
					 | 
				
			||||||
					if(sMPGlobal.pMutexMethods->xGlobalRelease) {
 | 
					 | 
				
			||||||
						sMPGlobal.pMutexMethods->xGlobalRelease();
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					sMPGlobal.pMutex = 0;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				/* Initialize and install the new mutex subsystem */
 | 
					 | 
				
			||||||
				if(pMethods->xGlobalInit) {
 | 
					 | 
				
			||||||
					rc = pMethods->xGlobalInit();
 | 
					 | 
				
			||||||
					if(rc != PH7_OK) {
 | 
					 | 
				
			||||||
						break;
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				/* Create the global mutex */
 | 
					 | 
				
			||||||
				sMPGlobal.pMutex = pMethods->xNew(SXMUTEX_TYPE_FAST);
 | 
					 | 
				
			||||||
				if(sMPGlobal.pMutex == 0) {
 | 
					 | 
				
			||||||
					/*
 | 
					 | 
				
			||||||
					 * If the supplied mutex subsystem is so sick that we are unable to
 | 
					 | 
				
			||||||
					 * create a single mutex,there is no much we can do here.
 | 
					 | 
				
			||||||
					 */
 | 
					 | 
				
			||||||
					if(pMethods->xGlobalRelease) {
 | 
					 | 
				
			||||||
						pMethods->xGlobalRelease();
 | 
					 | 
				
			||||||
					}
 | 
					 | 
				
			||||||
					rc = PH7_CORRUPT;
 | 
					 | 
				
			||||||
					break;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				sMPGlobal.pMutexMethods = pMethods;
 | 
					 | 
				
			||||||
				if(sMPGlobal.nThreadingLevel == 0) {
 | 
					 | 
				
			||||||
					/* Set a default threading level */
 | 
					 | 
				
			||||||
					sMPGlobal.nThreadingLevel = PH7_THREAD_LEVEL_MULTI;
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				break;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		case PH7_LIB_CONFIG_THREAD_LEVEL_SINGLE:
 | 
					 | 
				
			||||||
			/* Single thread mode(Only one thread is allowed to play with the library) */
 | 
					 | 
				
			||||||
			sMPGlobal.nThreadingLevel = PH7_THREAD_LEVEL_SINGLE;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		case PH7_LIB_CONFIG_THREAD_LEVEL_MULTI:
 | 
					 | 
				
			||||||
			/* Multi-threading mode (library is thread safe and PH7 engines and virtual machines
 | 
					 | 
				
			||||||
			 * may be shared between multiple threads).
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			sMPGlobal.nThreadingLevel = PH7_THREAD_LEVEL_MULTI;
 | 
					 | 
				
			||||||
			break;
 | 
					 | 
				
			||||||
		default:
 | 
							default:
 | 
				
			||||||
			/* Unknown configuration option */
 | 
								/* Unknown configuration option */
 | 
				
			||||||
			rc = PH7_CORRUPT;
 | 
								rc = PH7_CORRUPT;
 | 
				
			||||||
@@ -278,8 +199,6 @@ int ph7_lib_config(int nConfigOp, ...) {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
static sxi32 PH7CoreInitialize(void) {
 | 
					static sxi32 PH7CoreInitialize(void) {
 | 
				
			||||||
	const ph7_vfs *pVfs; /* Built-in vfs */
 | 
						const ph7_vfs *pVfs; /* Built-in vfs */
 | 
				
			||||||
	const SyMutexMethods *pMutexMethods = 0;
 | 
					 | 
				
			||||||
	SyMutex *pMaster = 0;
 | 
					 | 
				
			||||||
	int rc;
 | 
						int rc;
 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * If the library is already initialized,then a call to this routine
 | 
						 * If the library is already initialized,then a call to this routine
 | 
				
			||||||
@@ -292,30 +211,6 @@ static sxi32 PH7CoreInitialize(void) {
 | 
				
			|||||||
	pVfs = PH7_ExportBuiltinVfs();
 | 
						pVfs = PH7_ExportBuiltinVfs();
 | 
				
			||||||
	/* Install it */
 | 
						/* Install it */
 | 
				
			||||||
	ph7_lib_config(PH7_LIB_CONFIG_VFS, pVfs);
 | 
						ph7_lib_config(PH7_LIB_CONFIG_VFS, pVfs);
 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_SINGLE) {
 | 
					 | 
				
			||||||
		pMutexMethods = sMPGlobal.pMutexMethods;
 | 
					 | 
				
			||||||
		if(pMutexMethods == 0) {
 | 
					 | 
				
			||||||
			/* Use the built-in mutex subsystem */
 | 
					 | 
				
			||||||
			pMutexMethods = SyMutexExportMethods();
 | 
					 | 
				
			||||||
			if(pMutexMethods == 0) {
 | 
					 | 
				
			||||||
				return PH7_CORRUPT; /* Can't happen */
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			/* Install the mutex subsystem */
 | 
					 | 
				
			||||||
			rc = ph7_lib_config(PH7_LIB_CONFIG_USER_MUTEX, pMutexMethods);
 | 
					 | 
				
			||||||
			if(rc != PH7_OK) {
 | 
					 | 
				
			||||||
				return rc;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		/* Obtain a static mutex so we can initialize the library without calling malloc() */
 | 
					 | 
				
			||||||
		pMaster = SyMutexNew(pMutexMethods, SXMUTEX_TYPE_STATIC_1);
 | 
					 | 
				
			||||||
		if(pMaster == 0) {
 | 
					 | 
				
			||||||
			return PH7_CORRUPT; /* Can't happen */
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Lock the master mutex */
 | 
					 | 
				
			||||||
	rc = PH7_OK;
 | 
					 | 
				
			||||||
	SyMutexEnter(pMutexMethods, pMaster); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
					 | 
				
			||||||
	if(sMPGlobal.nMagic != PH7_LIB_MAGIC) {
 | 
					 | 
				
			||||||
		if(sMPGlobal.sAllocator.pMethods == 0) {
 | 
							if(sMPGlobal.sAllocator.pMethods == 0) {
 | 
				
			||||||
			/* Install a memory subsystem */
 | 
								/* Install a memory subsystem */
 | 
				
			||||||
			rc = ph7_lib_config(PH7_LIB_CONFIG_USER_MALLOC, 0); /* zero mean use the built-in memory backend */
 | 
								rc = ph7_lib_config(PH7_LIB_CONFIG_USER_MALLOC, 0); /* zero mean use the built-in memory backend */
 | 
				
			||||||
@@ -324,20 +219,10 @@ static sxi32 PH7CoreInitialize(void) {
 | 
				
			|||||||
				goto End;
 | 
									goto End;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
 | 
					 | 
				
			||||||
			/* Protect the memory allocation subsystem */
 | 
					 | 
				
			||||||
			rc = SyMemBackendMakeThreadSafe(&sMPGlobal.sAllocator, sMPGlobal.pMutexMethods);
 | 
					 | 
				
			||||||
			if(rc != PH7_OK) {
 | 
					 | 
				
			||||||
				goto End;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		/* Our library is initialized,set the magic number */
 | 
							/* Our library is initialized,set the magic number */
 | 
				
			||||||
		sMPGlobal.nMagic = PH7_LIB_MAGIC;
 | 
							sMPGlobal.nMagic = PH7_LIB_MAGIC;
 | 
				
			||||||
		rc = PH7_OK;
 | 
							rc = PH7_OK;
 | 
				
			||||||
	} /* sMPGlobal.nMagic != PH7_LIB_MAGIC */
 | 
					 | 
				
			||||||
End:
 | 
					End:
 | 
				
			||||||
	/* Unlock the master mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(pMutexMethods, pMaster); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
					 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -391,18 +276,6 @@ static void PH7CoreShutdown(void) {
 | 
				
			|||||||
		pEngine = pNext;
 | 
							pEngine = pNext;
 | 
				
			||||||
		sMPGlobal.nEngine--;
 | 
							sMPGlobal.nEngine--;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Release the mutex subsystem */
 | 
					 | 
				
			||||||
	if(sMPGlobal.pMutexMethods) {
 | 
					 | 
				
			||||||
		if(sMPGlobal.pMutex) {
 | 
					 | 
				
			||||||
			SyMutexRelease(sMPGlobal.pMutexMethods, sMPGlobal.pMutex);
 | 
					 | 
				
			||||||
			sMPGlobal.pMutex = 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(sMPGlobal.pMutexMethods->xGlobalRelease) {
 | 
					 | 
				
			||||||
			sMPGlobal.pMutexMethods->xGlobalRelease();
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		sMPGlobal.pMutexMethods = 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	sMPGlobal.nThreadingLevel = 0;
 | 
					 | 
				
			||||||
	if(sMPGlobal.sAllocator.pMethods) {
 | 
						if(sMPGlobal.sAllocator.pMethods) {
 | 
				
			||||||
		/* Release the memory backend */
 | 
							/* Release the memory backend */
 | 
				
			||||||
		SyMemBackendRelease(&sMPGlobal.sAllocator);
 | 
							SyMemBackendRelease(&sMPGlobal.sAllocator);
 | 
				
			||||||
@@ -429,13 +302,7 @@ int ph7_lib_is_threadsafe(void) {
 | 
				
			|||||||
	if(sMPGlobal.nMagic != PH7_LIB_MAGIC) {
 | 
						if(sMPGlobal.nMagic != PH7_LIB_MAGIC) {
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
 | 
						return 0;
 | 
				
			||||||
		/* Muli-threading support is enabled */
 | 
					 | 
				
			||||||
		return 1;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		/* Single-threading */
 | 
					 | 
				
			||||||
		return 0;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * [CAPIREF: ph7_lib_version()]
 | 
					 * [CAPIREF: ph7_lib_version()]
 | 
				
			||||||
@@ -468,17 +335,9 @@ int ph7_config(ph7 *pEngine, int nConfigOp, ...) {
 | 
				
			|||||||
	if(PH7_ENGINE_MISUSE(pEngine)) {
 | 
						if(PH7_ENGINE_MISUSE(pEngine)) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* 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 */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	va_start(ap, nConfigOp);
 | 
						va_start(ap, nConfigOp);
 | 
				
			||||||
	rc = EngineConfig(&(*pEngine), nConfigOp, ap);
 | 
						rc = EngineConfig(&(*pEngine), nConfigOp, ap);
 | 
				
			||||||
	va_end(ap);
 | 
						va_end(ap);
 | 
				
			||||||
	/* Leave engine mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -510,28 +369,15 @@ int ph7_init(ph7 **ppEngine) {
 | 
				
			|||||||
	if(rc != PH7_OK) {
 | 
						if(rc != PH7_OK) {
 | 
				
			||||||
		goto Release;
 | 
							goto Release;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	SyMemBackendDisbaleMutexing(&pEngine->sAllocator);
 | 
					 | 
				
			||||||
	/* Default configuration */
 | 
						/* Default configuration */
 | 
				
			||||||
	SyBlobInit(&pEngine->xConf.sErrConsumer, &pEngine->sAllocator);
 | 
						SyBlobInit(&pEngine->xConf.sErrConsumer, &pEngine->sAllocator);
 | 
				
			||||||
	/* Install a default compile-time error consumer routine */
 | 
						/* Install a default compile-time error consumer routine */
 | 
				
			||||||
	ph7_config(pEngine, PH7_CONFIG_ERR_OUTPUT, PH7_VmBlobConsumer, &pEngine->xConf.sErrConsumer);
 | 
						ph7_config(pEngine, PH7_CONFIG_ERR_OUTPUT, PH7_VmBlobConsumer, &pEngine->xConf.sErrConsumer);
 | 
				
			||||||
	/* Built-in vfs */
 | 
						/* Built-in vfs */
 | 
				
			||||||
	pEngine->pVfs = sMPGlobal.pVfs;
 | 
						pEngine->pVfs = sMPGlobal.pVfs;
 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
 | 
					 | 
				
			||||||
		/* Associate a recursive mutex with this instance */
 | 
					 | 
				
			||||||
		pEngine->pMutex = SyMutexNew(sMPGlobal.pMutexMethods, SXMUTEX_TYPE_RECURSIVE);
 | 
					 | 
				
			||||||
		if(pEngine->pMutex == 0) {
 | 
					 | 
				
			||||||
			rc = PH7_NOMEM;
 | 
					 | 
				
			||||||
			goto Release;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Link to the list of active engines */
 | 
						/* Link to the list of active engines */
 | 
				
			||||||
	/* Enter the global mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
					 | 
				
			||||||
	MACRO_LD_PUSH(sMPGlobal.pEngines, pEngine);
 | 
						MACRO_LD_PUSH(sMPGlobal.pEngines, pEngine);
 | 
				
			||||||
	sMPGlobal.nEngine++;
 | 
						sMPGlobal.nEngine++;
 | 
				
			||||||
	/* Leave the global mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
					 | 
				
			||||||
	/* Write a pointer to the new instance */
 | 
						/* Write a pointer to the new instance */
 | 
				
			||||||
	*ppEngine = pEngine;
 | 
						*ppEngine = pEngine;
 | 
				
			||||||
	return PH7_OK;
 | 
						return PH7_OK;
 | 
				
			||||||
@@ -549,25 +395,11 @@ int ph7_release(ph7 *pEngine) {
 | 
				
			|||||||
	if(PH7_ENGINE_MISUSE(pEngine)) {
 | 
						if(PH7_ENGINE_MISUSE(pEngine)) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* 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 */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Release the engine */
 | 
						/* Release the engine */
 | 
				
			||||||
	rc = EngineRelease(&(*pEngine));
 | 
						rc = EngineRelease(&(*pEngine));
 | 
				
			||||||
	/* Leave engine mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	/* Release engine mutex */
 | 
					 | 
				
			||||||
	SyMutexRelease(sMPGlobal.pMutexMethods, pEngine->pMutex) /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	/* Enter the global mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
					 | 
				
			||||||
	/* Unlink from the list of active engines */
 | 
						/* Unlink from the list of active engines */
 | 
				
			||||||
	MACRO_LD_REMOVE(sMPGlobal.pEngines, pEngine);
 | 
						MACRO_LD_REMOVE(sMPGlobal.pEngines, pEngine);
 | 
				
			||||||
	sMPGlobal.nEngine--;
 | 
						sMPGlobal.nEngine--;
 | 
				
			||||||
	/* Leave the global mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */
 | 
					 | 
				
			||||||
	/* Release the memory chunk allocated to this engine */
 | 
						/* Release the memory chunk allocated to this engine */
 | 
				
			||||||
	SyMemBackendPoolFree(&sMPGlobal.sAllocator, pEngine);
 | 
						SyMemBackendPoolFree(&sMPGlobal.sAllocator, pEngine);
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
@@ -664,13 +496,6 @@ static sxi32 ProcessSourceFile(
 | 
				
			|||||||
	if(rc != PH7_OK) {
 | 
						if(rc != PH7_OK) {
 | 
				
			||||||
		goto Release;
 | 
							goto Release;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) {
 | 
					 | 
				
			||||||
		/* Associate a recursive mutex with this instance */
 | 
					 | 
				
			||||||
		pVm->pMutex = SyMutexNew(sMPGlobal.pMutexMethods, SXMUTEX_TYPE_RECURSIVE);
 | 
					 | 
				
			||||||
		if(pVm->pMutex == 0) {
 | 
					 | 
				
			||||||
			goto Release;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Script successfully compiled,link to the list of active virtual machines */
 | 
						/* Script successfully compiled,link to the list of active virtual machines */
 | 
				
			||||||
	MACRO_LD_PUSH(pEngine->pVms, pVm);
 | 
						MACRO_LD_PUSH(pEngine->pVms, pVm);
 | 
				
			||||||
	pEngine->iVm++;
 | 
						pEngine->iVm++;
 | 
				
			||||||
@@ -697,16 +522,8 @@ int ph7_compile_code(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOut
 | 
				
			|||||||
		nLen = (int)SyStrlen(zSource);
 | 
							nLen = (int)SyStrlen(zSource);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	SyStringInitFromBuf(&sScript, zSource, nLen);
 | 
						SyStringInitFromBuf(&sScript, zSource, nLen);
 | 
				
			||||||
	/* 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 */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Compile the script */
 | 
						/* Compile the script */
 | 
				
			||||||
	rc = ProcessSourceFile(&(*pEngine), ppOutVm, &sScript, 0);
 | 
						rc = ProcessSourceFile(&(*pEngine), ppOutVm, &sScript, 0);
 | 
				
			||||||
	/* Leave engine mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	/* Compilation result */
 | 
						/* Compilation result */
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -721,12 +538,6 @@ int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm) {
 | 
				
			|||||||
	if(PH7_ENGINE_MISUSE(pEngine) || SX_EMPTY_STR(zFilePath)) {
 | 
						if(PH7_ENGINE_MISUSE(pEngine) || SX_EMPTY_STR(zFilePath)) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* 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 */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/*
 | 
						/*
 | 
				
			||||||
	 * Check if the underlying vfs implement the memory map
 | 
						 * Check if the underlying vfs implement the memory map
 | 
				
			||||||
	 * [i.e: mmap() under UNIX/MapViewOfFile() under windows] function.
 | 
						 * [i.e: mmap() under UNIX/MapViewOfFile() under windows] function.
 | 
				
			||||||
@@ -754,8 +565,6 @@ int ph7_compile_file(ph7 *pEngine, const char *zFilePath, ph7_vm **ppOutVm) {
 | 
				
			|||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Leave engine mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	/* Compilation result */
 | 
						/* Compilation result */
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -787,18 +596,10 @@ int ph7_vm_config(ph7_vm *pVm, int iConfigOp, ...) {
 | 
				
			|||||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
						if(PH7_VM_MISUSE(pVm)) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Acquire VM mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
					 | 
				
			||||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
					 | 
				
			||||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Configure the virtual machine */
 | 
						/* Configure the virtual machine */
 | 
				
			||||||
	va_start(ap, iConfigOp);
 | 
						va_start(ap, iConfigOp);
 | 
				
			||||||
	rc = PH7_VmConfigure(&(*pVm), iConfigOp, ap);
 | 
						rc = PH7_VmConfigure(&(*pVm), iConfigOp, ap);
 | 
				
			||||||
	va_end(ap);
 | 
						va_end(ap);
 | 
				
			||||||
	/* Leave VM mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -811,20 +612,12 @@ int ph7_vm_exec(ph7_vm *pVm, int *pExitStatus) {
 | 
				
			|||||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
						if(PH7_VM_MISUSE(pVm)) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Acquire VM mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
					 | 
				
			||||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
					 | 
				
			||||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Execute PH7 byte-code */
 | 
						/* Execute PH7 byte-code */
 | 
				
			||||||
	rc = PH7_VmByteCodeExec(&(*pVm));
 | 
						rc = PH7_VmByteCodeExec(&(*pVm));
 | 
				
			||||||
	if(pExitStatus) {
 | 
						if(pExitStatus) {
 | 
				
			||||||
		/* Exit status */
 | 
							/* Exit status */
 | 
				
			||||||
		*pExitStatus = pVm->iExitStatus;
 | 
							*pExitStatus = pVm->iExitStatus;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Leave VM mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	/* Execution result */
 | 
						/* Execution result */
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -838,15 +631,7 @@ int ph7_vm_reset(ph7_vm *pVm) {
 | 
				
			|||||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
						if(PH7_VM_MISUSE(pVm)) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Acquire VM mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
					 | 
				
			||||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
					 | 
				
			||||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	rc = PH7_VmReset(&(*pVm));
 | 
						rc = PH7_VmReset(&(*pVm));
 | 
				
			||||||
	/* Leave VM mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -860,32 +645,14 @@ int ph7_vm_release(ph7_vm *pVm) {
 | 
				
			|||||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
						if(PH7_VM_MISUSE(pVm)) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Acquire VM mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
					 | 
				
			||||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
					 | 
				
			||||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pEngine = pVm->pEngine;
 | 
						pEngine = pVm->pEngine;
 | 
				
			||||||
	rc = PH7_VmRelease(&(*pVm));
 | 
						rc = PH7_VmRelease(&(*pVm));
 | 
				
			||||||
	/* Leave VM mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	/* free VM mutex */
 | 
					 | 
				
			||||||
	SyMutexRelease(sMPGlobal.pMutexMethods, pVm->pMutex);
 | 
					 | 
				
			||||||
	if(rc == PH7_OK) {
 | 
						if(rc == PH7_OK) {
 | 
				
			||||||
		/* Unlink from the list of active VM */
 | 
							/* Unlink from the list of active VM */
 | 
				
			||||||
		/* 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 */
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		MACRO_LD_REMOVE(pEngine->pVms, pVm);
 | 
							MACRO_LD_REMOVE(pEngine->pVms, pVm);
 | 
				
			||||||
		pEngine->iVm--;
 | 
							pEngine->iVm--;
 | 
				
			||||||
		/* Release the memory chunk allocated to this VM */
 | 
							/* Release the memory chunk allocated to this VM */
 | 
				
			||||||
		SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
 | 
							SyMemBackendPoolFree(&pEngine->sAllocator, pVm);
 | 
				
			||||||
		/* Leave engine mutex */
 | 
					 | 
				
			||||||
		SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -907,16 +674,8 @@ int ph7_create_function(ph7_vm *pVm, const char *zName, int (*xFunc)(ph7_context
 | 
				
			|||||||
	if(sName.nByte < 1 || xFunc == 0) {
 | 
						if(sName.nByte < 1 || xFunc == 0) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Acquire VM mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
					 | 
				
			||||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
					 | 
				
			||||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Install the foreign function */
 | 
						/* Install the foreign function */
 | 
				
			||||||
	rc = PH7_VmInstallForeignFunction(&(*pVm), &sName, xFunc, pUserData);
 | 
						rc = PH7_VmInstallForeignFunction(&(*pVm), &sName, xFunc, pUserData);
 | 
				
			||||||
	/* Leave VM mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -930,12 +689,6 @@ int ph7_delete_function(ph7_vm *pVm, const char *zName) {
 | 
				
			|||||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
						if(PH7_VM_MISUSE(pVm)) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Acquire VM mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
					 | 
				
			||||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
					 | 
				
			||||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Perform the deletion */
 | 
						/* Perform the deletion */
 | 
				
			||||||
	rc = SyHashDeleteEntry(&pVm->hHostFunction, (const void *)zName, SyStrlen(zName), (void **)&pFunc);
 | 
						rc = SyHashDeleteEntry(&pVm->hHostFunction, (const void *)zName, SyStrlen(zName), (void **)&pFunc);
 | 
				
			||||||
	if(rc == PH7_OK) {
 | 
						if(rc == PH7_OK) {
 | 
				
			||||||
@@ -944,8 +697,6 @@ int ph7_delete_function(ph7_vm *pVm, const char *zName) {
 | 
				
			|||||||
		SyMemBackendFree(&pVm->sAllocator, (void *)SyStringData(&pFunc->sName));
 | 
							SyMemBackendFree(&pVm->sAllocator, (void *)SyStringData(&pFunc->sName));
 | 
				
			||||||
		SyMemBackendPoolFree(&pVm->sAllocator, pFunc);
 | 
							SyMemBackendPoolFree(&pVm->sAllocator, pFunc);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Leave VM mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -970,16 +721,8 @@ int ph7_create_constant(ph7_vm *pVm, const char *zName, void (*xExpand)(ph7_valu
 | 
				
			|||||||
	if(xExpand == 0) {
 | 
						if(xExpand == 0) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Acquire VM mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
					 | 
				
			||||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
					 | 
				
			||||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Perform the registration */
 | 
						/* Perform the registration */
 | 
				
			||||||
	rc = PH7_VmRegisterConstant(&(*pVm), &sName, xExpand, pUserData, TRUE);
 | 
						rc = PH7_VmRegisterConstant(&(*pVm), &sName, xExpand, pUserData, TRUE);
 | 
				
			||||||
	/* Leave VM mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
@@ -993,12 +736,6 @@ int ph7_delete_constant(ph7_vm *pVm, const char *zName) {
 | 
				
			|||||||
	if(PH7_VM_MISUSE(pVm)) {
 | 
						if(PH7_VM_MISUSE(pVm)) {
 | 
				
			||||||
		return PH7_CORRUPT;
 | 
							return PH7_CORRUPT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Acquire VM mutex */
 | 
					 | 
				
			||||||
	SyMutexEnter(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE &&
 | 
					 | 
				
			||||||
			PH7_THRD_VM_RELEASE(pVm)) {
 | 
					 | 
				
			||||||
		return PH7_ABORT; /* Another thread have released this instance */
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Query the constant hashtable */
 | 
						/* Query the constant hashtable */
 | 
				
			||||||
	rc = SyHashDeleteEntry(&pVm->hConstant, (const void *)zName, SyStrlen(zName), (void **)&pCons);
 | 
						rc = SyHashDeleteEntry(&pVm->hConstant, (const void *)zName, SyStrlen(zName), (void **)&pCons);
 | 
				
			||||||
	if(rc == PH7_OK) {
 | 
						if(rc == PH7_OK) {
 | 
				
			||||||
@@ -1006,8 +743,6 @@ int ph7_delete_constant(ph7_vm *pVm, const char *zName) {
 | 
				
			|||||||
		SyMemBackendFree(&pVm->sAllocator, (void *)SyStringData(&pCons->sName));
 | 
							SyMemBackendFree(&pVm->sAllocator, (void *)SyStringData(&pCons->sName));
 | 
				
			||||||
		SyMemBackendPoolFree(&pVm->sAllocator, pCons);
 | 
							SyMemBackendPoolFree(&pVm->sAllocator, pCons);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Leave VM mutex */
 | 
					 | 
				
			||||||
	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */
 | 
					 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1381,8 +1381,8 @@ static sxi32 PH7_CompileContinue(ph7_gen_state *pGen) {
 | 
				
			|||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		sxu32 nInstrIdx = 0;
 | 
							sxu32 nInstrIdx = 0;
 | 
				
			||||||
		if(!pLoop->bPostContinue) {
 | 
							if(!pLoop->bPostContinue) {
 | 
				
			||||||
			/* Emit the OP_JMPLFE instruction to leave the loop frame */
 | 
								/* Emit the OP_LF_STOP instruction to leave the loop frame */
 | 
				
			||||||
			PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0);
 | 
								PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_JMP, 0, pLoop->nFirstInstr, 0, &nInstrIdx);
 | 
							PH7_VmEmitInstr(pGen->pVm, 0, PH7_OP_JMP, 0, pLoop->nFirstInstr, 0, &nInstrIdx);
 | 
				
			||||||
		if(pLoop->bPostContinue) {
 | 
							if(pLoop->bPostContinue) {
 | 
				
			||||||
@@ -1421,8 +1421,8 @@ static sxi32 PH7_CompileBreak(ph7_gen_state *pGen) {
 | 
				
			|||||||
		PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "A 'break' statement may only be used within a loop or switch");
 | 
							PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine, "A 'break' statement may only be used within a loop or switch");
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		sxu32 nInstrIdx;
 | 
							sxu32 nInstrIdx;
 | 
				
			||||||
		/* Emit the OP_JMPLFE instruction to leave the loop frame */
 | 
							/* Emit the OP_LF_STOP instruction to leave the loop frame */
 | 
				
			||||||
		PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0);
 | 
							PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
 | 
				
			||||||
		rc = PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, 0, 0, &nInstrIdx);
 | 
							rc = PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, 0, 0, &nInstrIdx);
 | 
				
			||||||
		if(rc == SXRET_OK) {
 | 
							if(rc == SXRET_OK) {
 | 
				
			||||||
			/* Fix the jump later when the jump destination is resolved */
 | 
								/* Fix the jump later when the jump destination is resolved */
 | 
				
			||||||
@@ -1548,7 +1548,7 @@ static sxi32 PH7_CompileGoto(ph7_gen_state *pGen)
 | 
				
			|||||||
			sJump.pFunc = 0;
 | 
								sJump.pFunc = 0;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		/* Make sure there will not stay any loop frame opened (i.e. goto inside a loop) */
 | 
							/* Make sure there will not stay any loop frame opened (i.e. goto inside a loop) */
 | 
				
			||||||
		PH7_VmEmitInstr(pGen->pVm, sJump.nLine, PH7_OP_JMPLFE, 0, 0, 0, 0);
 | 
							PH7_VmEmitInstr(pGen->pVm, sJump.nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
 | 
				
			||||||
		/* Emit the unconditional jump */
 | 
							/* Emit the unconditional jump */
 | 
				
			||||||
		if(SXRET_OK == PH7_VmEmitInstr(pGen->pVm, sJump.nLine, PH7_OP_JMP, 0, 0, 0, &sJump.nInstrIdx)) {
 | 
							if(SXRET_OK == PH7_VmEmitInstr(pGen->pVm, sJump.nLine, PH7_OP_JMP, 0, 0, 0, &sJump.nInstrIdx)) {
 | 
				
			||||||
			SySetPut(&pGen->aGoto, (const void *)&sJump);
 | 
								SySetPut(&pGen->aGoto, (const void *)&sJump);
 | 
				
			||||||
@@ -1700,15 +1700,15 @@ static sxi32 PH7_CompileWhile(ph7_gen_state *pGen) {
 | 
				
			|||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPZ, 0, 0, 0, &nFalseJump);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPZ, 0, 0, 0, &nFalseJump);
 | 
				
			||||||
	/* Save the instruction index so we can fix it later when the jump destination is resolved */
 | 
						/* Save the instruction index so we can fix it later when the jump destination is resolved */
 | 
				
			||||||
	PH7_GenStateNewJumpFixup(pWhileBlock, PH7_OP_JMPZ, nFalseJump);
 | 
						PH7_GenStateNewJumpFixup(pWhileBlock, PH7_OP_JMPZ, nFalseJump);
 | 
				
			||||||
	/* Emit the OP_JMPLFB instruction to enter a loop frame */
 | 
						/* Emit the OP_LF_START instruction to enter a loop frame */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFB, 0, 0, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_START, 0, 0, 0, 0);
 | 
				
			||||||
	/* Compile the loop body */
 | 
						/* Compile the loop body */
 | 
				
			||||||
	rc = PH7_CompileBlock(&(*pGen));
 | 
						rc = PH7_CompileBlock(&(*pGen));
 | 
				
			||||||
	if(rc == SXERR_ABORT) {
 | 
						if(rc == SXERR_ABORT) {
 | 
				
			||||||
		return SXERR_ABORT;
 | 
							return SXERR_ABORT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Emit the OP_JMPLFE instruction to leave the loop frame */
 | 
						/* Emit the OP_LF_STOP instruction to leave the loop frame */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
 | 
				
			||||||
	/* Emit the unconditional jump to the start of the loop */
 | 
						/* Emit the unconditional jump to the start of the loop */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pWhileBlock->nFirstInstr, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pWhileBlock->nFirstInstr, 0, 0);
 | 
				
			||||||
	/* Fix all jumps now the destination is resolved */
 | 
						/* Fix all jumps now the destination is resolved */
 | 
				
			||||||
@@ -1755,8 +1755,8 @@ static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	/* Deffer 'continue;' jumps until we compile the block */
 | 
						/* Deffer 'continue;' jumps until we compile the block */
 | 
				
			||||||
	pDoBlock->bPostContinue = TRUE;
 | 
						pDoBlock->bPostContinue = TRUE;
 | 
				
			||||||
	/* Emit the OP_JMPLFB instruction to enter a loop frame */
 | 
						/* Emit the OP_LF_START instruction to enter a loop frame */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFB, 0, 0, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_START, 0, 0, 0, 0);
 | 
				
			||||||
	rc = PH7_CompileBlock(&(*pGen));
 | 
						rc = PH7_CompileBlock(&(*pGen));
 | 
				
			||||||
	if(rc == SXERR_ABORT) {
 | 
						if(rc == SXERR_ABORT) {
 | 
				
			||||||
		return SXERR_ABORT;
 | 
							return SXERR_ABORT;
 | 
				
			||||||
@@ -1814,8 +1814,8 @@ static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	pGen->pIn  = &pEnd[1];
 | 
						pGen->pIn  = &pEnd[1];
 | 
				
			||||||
	pGen->pEnd = pTmp;
 | 
						pGen->pEnd = pTmp;
 | 
				
			||||||
	/* Emit the OP_JMPLFE instruction to leave the loop frame */
 | 
						/* Emit the OP_LF_STOP instruction to leave the loop frame */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
 | 
				
			||||||
	/* Emit the true jump to the beginning of the loop */
 | 
						/* Emit the true jump to the beginning of the loop */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPNZ, 0, pDoBlock->nFirstInstr, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPNZ, 0, pDoBlock->nFirstInstr, 0, 0);
 | 
				
			||||||
	/* Fix all jumps now the destination is resolved */
 | 
						/* Fix all jumps now the destination is resolved */
 | 
				
			||||||
@@ -1918,8 +1918,8 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) {
 | 
				
			|||||||
		PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
 | 
							PH7_GenCompileError(pGen, E_ERROR, pGen->pIn->nLine,
 | 
				
			||||||
								 "for: Expected ';' after conditionals expressions");
 | 
													 "for: Expected ';' after conditionals expressions");
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Emit the OP_JMPLFB instruction to enter a loop frame */
 | 
						/* Emit the OP_LF_START instruction to enter a loop frame */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFB, 0, 0, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_START, 0, 0, 0, 0);
 | 
				
			||||||
	/* Jump the trailing ';' */
 | 
						/* Jump the trailing ';' */
 | 
				
			||||||
	pGen->pIn++;
 | 
						pGen->pIn++;
 | 
				
			||||||
	/* Save the post condition stream */
 | 
						/* Save the post condition stream */
 | 
				
			||||||
@@ -1968,8 +1968,8 @@ static sxi32 PH7_CompileFor(ph7_gen_state *pGen) {
 | 
				
			|||||||
			PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_POP, 1, 0, 0, 0);
 | 
								PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_POP, 1, 0, 0, 0);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Emit the OP_JMPLFE instruction to leave the loop frame */
 | 
						/* Emit the OP_LF_STOP instruction to leave the loop frame */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
 | 
				
			||||||
	/* Emit the unconditional jump to the start of the loop */
 | 
						/* Emit the unconditional jump to the start of the loop */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pForBlock->nFirstInstr, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pForBlock->nFirstInstr, 0, 0);
 | 
				
			||||||
	/* Fix all jumps now the destination is resolved */
 | 
						/* Fix all jumps now the destination is resolved */
 | 
				
			||||||
@@ -2158,8 +2158,8 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) {
 | 
				
			|||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_FOREACH_STEP, 0, 0, pInfo, &nFalseJump);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_FOREACH_STEP, 0, 0, pInfo, &nFalseJump);
 | 
				
			||||||
	/* Save the instruction index so we can fix it later when the jump destination is resolved */
 | 
						/* Save the instruction index so we can fix it later when the jump destination is resolved */
 | 
				
			||||||
	PH7_GenStateNewJumpFixup(pForeachBlock, PH7_OP_FOREACH_STEP, nFalseJump);
 | 
						PH7_GenStateNewJumpFixup(pForeachBlock, PH7_OP_FOREACH_STEP, nFalseJump);
 | 
				
			||||||
	/* Emit the OP_JMPLFB instruction to enter a loop frame */
 | 
						/* Emit the OP_LF_START instruction to enter a loop frame */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFB, 0, 0, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_START, 0, 0, 0, 0);
 | 
				
			||||||
	/* Compile the loop body */
 | 
						/* Compile the loop body */
 | 
				
			||||||
	pGen->pIn = &pEnd[1];
 | 
						pGen->pIn = &pEnd[1];
 | 
				
			||||||
	pGen->pEnd = pTmp;
 | 
						pGen->pEnd = pTmp;
 | 
				
			||||||
@@ -2168,8 +2168,8 @@ static sxi32 PH7_CompileForeach(ph7_gen_state *pGen) {
 | 
				
			|||||||
		/* Don't worry about freeing memory, everything will be released shortly */
 | 
							/* Don't worry about freeing memory, everything will be released shortly */
 | 
				
			||||||
		return SXERR_ABORT;
 | 
							return SXERR_ABORT;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/* Emit the OP_JMPLFE instruction to leave the loop frame */
 | 
						/* Emit the OP_LF_STOP instruction to leave the loop frame */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0);
 | 
				
			||||||
	/* Emit the unconditional jump to the start of the loop */
 | 
						/* Emit the unconditional jump to the start of the loop */
 | 
				
			||||||
	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pForeachBlock->nFirstInstr, 0, 0);
 | 
						PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pForeachBlock->nFirstInstr, 0, 0);
 | 
				
			||||||
	/* Fix all jumps now the destination is resolved */
 | 
						/* Fix all jumps now the destination is resolved */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -273,33 +273,6 @@ PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	return rc;
 | 
						return rc;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
PH7_PRIVATE sxi32 SyMemBackendMakeThreadSafe(SyMemBackend *pBackend, const SyMutexMethods *pMethods) {
 | 
					 | 
				
			||||||
	SyMutex *pMutex;
 | 
					 | 
				
			||||||
	if(SXMEM_BACKEND_CORRUPT(pBackend) || pMethods == 0 || pMethods->xNew == 0) {
 | 
					 | 
				
			||||||
		return SXERR_CORRUPT;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pMutex = pMethods->xNew(SXMUTEX_TYPE_FAST);
 | 
					 | 
				
			||||||
	if(pMutex == 0) {
 | 
					 | 
				
			||||||
		return SXERR_OS;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	/* Attach the mutex to the memory backend */
 | 
					 | 
				
			||||||
	pBackend->pMutex = pMutex;
 | 
					 | 
				
			||||||
	pBackend->pMutexMethods = pMethods;
 | 
					 | 
				
			||||||
	return SXRET_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
PH7_PRIVATE sxi32 SyMemBackendDisbaleMutexing(SyMemBackend *pBackend) {
 | 
					 | 
				
			||||||
	if(SXMEM_BACKEND_CORRUPT(pBackend)) {
 | 
					 | 
				
			||||||
		return SXERR_CORRUPT;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if(pBackend->pMutex == 0) {
 | 
					 | 
				
			||||||
		/* There is no mutex subsystem at all */
 | 
					 | 
				
			||||||
		return SXRET_OK;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	SyMutexRelease(pBackend->pMutexMethods, pBackend->pMutex);
 | 
					 | 
				
			||||||
	pBackend->pMutexMethods = 0;
 | 
					 | 
				
			||||||
	pBackend->pMutex = 0;
 | 
					 | 
				
			||||||
	return SXRET_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Memory pool allocator
 | 
					 * Memory pool allocator
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,222 +0,0 @@
 | 
				
			|||||||
/**
 | 
					 | 
				
			||||||
 * @PROJECT     PH7 Engine for the AerScript Interpreter
 | 
					 | 
				
			||||||
 * @COPYRIGHT   See COPYING in the top level directory
 | 
					 | 
				
			||||||
 * @FILE        engine/lib/mutex.c
 | 
					 | 
				
			||||||
 * @DESCRIPTION Thread safe MUTEX implementation for the PH7 Engine
 | 
					 | 
				
			||||||
 * @DEVELOPERS  Symisc Systems <devel@symisc.net>
 | 
					 | 
				
			||||||
 *              Rafal Kupiec <belliash@codingworkshop.eu.org>
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
#include "ph7int.h"
 | 
					 | 
				
			||||||
#if defined(__WINNT__)
 | 
					 | 
				
			||||||
	#include <Windows.h>
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	#include <stdlib.h>
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
#if defined(__WINNT__)
 | 
					 | 
				
			||||||
struct SyMutex {
 | 
					 | 
				
			||||||
	CRITICAL_SECTION sMutex;
 | 
					 | 
				
			||||||
	sxu32 nType; /* Mutex type,one of SXMUTEX_TYPE_* */
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
/* Preallocated static mutex */
 | 
					 | 
				
			||||||
static SyMutex aStaticMutexes[] = {
 | 
					 | 
				
			||||||
	{{0}, SXMUTEX_TYPE_STATIC_1},
 | 
					 | 
				
			||||||
	{{0}, SXMUTEX_TYPE_STATIC_2},
 | 
					 | 
				
			||||||
	{{0}, SXMUTEX_TYPE_STATIC_3},
 | 
					 | 
				
			||||||
	{{0}, SXMUTEX_TYPE_STATIC_4},
 | 
					 | 
				
			||||||
	{{0}, SXMUTEX_TYPE_STATIC_5},
 | 
					 | 
				
			||||||
	{{0}, SXMUTEX_TYPE_STATIC_6}
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
static BOOL winMutexInit = FALSE;
 | 
					 | 
				
			||||||
static LONG winMutexLock = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static sxi32 WinMutexGlobaInit(void) {
 | 
					 | 
				
			||||||
	LONG rc;
 | 
					 | 
				
			||||||
	rc = InterlockedCompareExchange(&winMutexLock, 1, 0);
 | 
					 | 
				
			||||||
	if(rc == 0) {
 | 
					 | 
				
			||||||
		sxu32 n;
 | 
					 | 
				
			||||||
		for(n = 0 ; n  < SX_ARRAYSIZE(aStaticMutexes) ; ++n) {
 | 
					 | 
				
			||||||
			InitializeCriticalSection(&aStaticMutexes[n].sMutex);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		winMutexInit = TRUE;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		/* Someone else is doing this for us */
 | 
					 | 
				
			||||||
		while(winMutexInit == FALSE) {
 | 
					 | 
				
			||||||
			Sleep(1);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return SXRET_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void WinMutexGlobalRelease(void) {
 | 
					 | 
				
			||||||
	LONG rc;
 | 
					 | 
				
			||||||
	rc = InterlockedCompareExchange(&winMutexLock, 0, 1);
 | 
					 | 
				
			||||||
	if(rc == 1) {
 | 
					 | 
				
			||||||
		/* The first to decrement to zero does the actual global release */
 | 
					 | 
				
			||||||
		if(winMutexInit == TRUE) {
 | 
					 | 
				
			||||||
			sxu32 n;
 | 
					 | 
				
			||||||
			for(n = 0 ; n < SX_ARRAYSIZE(aStaticMutexes) ; ++n) {
 | 
					 | 
				
			||||||
				DeleteCriticalSection(&aStaticMutexes[n].sMutex);
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			winMutexInit = FALSE;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static SyMutex *WinMutexNew(int nType) {
 | 
					 | 
				
			||||||
	SyMutex *pMutex = 0;
 | 
					 | 
				
			||||||
	if(nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
					 | 
				
			||||||
		/* Allocate a new mutex */
 | 
					 | 
				
			||||||
		pMutex = (SyMutex *)HeapAlloc(GetProcessHeap(), 0, sizeof(SyMutex));
 | 
					 | 
				
			||||||
		if(pMutex == 0) {
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		InitializeCriticalSection(&pMutex->sMutex);
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		/* Use a pre-allocated static mutex */
 | 
					 | 
				
			||||||
		if(nType > SXMUTEX_TYPE_STATIC_6) {
 | 
					 | 
				
			||||||
			nType = SXMUTEX_TYPE_STATIC_6;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		pMutex = &aStaticMutexes[nType - 3];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pMutex->nType = nType;
 | 
					 | 
				
			||||||
	return pMutex;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void WinMutexRelease(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
	if(pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
					 | 
				
			||||||
		DeleteCriticalSection(&pMutex->sMutex);
 | 
					 | 
				
			||||||
		HeapFree(GetProcessHeap(), 0, pMutex);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void WinMutexEnter(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
	EnterCriticalSection(&pMutex->sMutex);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static sxi32 WinMutexTryEnter(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
#ifdef _WIN32_WINNT
 | 
					 | 
				
			||||||
	BOOL rc;
 | 
					 | 
				
			||||||
	/* Only WindowsNT platforms */
 | 
					 | 
				
			||||||
	rc = TryEnterCriticalSection(&pMutex->sMutex);
 | 
					 | 
				
			||||||
	if(rc) {
 | 
					 | 
				
			||||||
		return SXRET_OK;
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		return SXERR_BUSY;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
	return SXERR_NOTIMPLEMENTED;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void WinMutexLeave(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
	LeaveCriticalSection(&pMutex->sMutex);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/* Export Windows mutex interfaces */
 | 
					 | 
				
			||||||
static const SyMutexMethods sWinMutexMethods = {
 | 
					 | 
				
			||||||
	WinMutexGlobaInit,  /* xGlobalInit() */
 | 
					 | 
				
			||||||
	WinMutexGlobalRelease, /* xGlobalRelease() */
 | 
					 | 
				
			||||||
	WinMutexNew,     /* xNew() */
 | 
					 | 
				
			||||||
	WinMutexRelease, /* xRelease() */
 | 
					 | 
				
			||||||
	WinMutexEnter,   /* xEnter() */
 | 
					 | 
				
			||||||
	WinMutexTryEnter, /* xTryEnter() */
 | 
					 | 
				
			||||||
	WinMutexLeave     /* xLeave() */
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) {
 | 
					 | 
				
			||||||
	return &sWinMutexMethods;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#elif defined(__UNIXES__)
 | 
					 | 
				
			||||||
#include <pthread.h>
 | 
					 | 
				
			||||||
struct SyMutex {
 | 
					 | 
				
			||||||
	pthread_mutex_t sMutex;
 | 
					 | 
				
			||||||
	sxu32 nType;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
static SyMutex *UnixMutexNew(int nType) {
 | 
					 | 
				
			||||||
	static SyMutex aStaticMutexes[] = {
 | 
					 | 
				
			||||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_1},
 | 
					 | 
				
			||||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_2},
 | 
					 | 
				
			||||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_3},
 | 
					 | 
				
			||||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_4},
 | 
					 | 
				
			||||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_5},
 | 
					 | 
				
			||||||
		{PTHREAD_MUTEX_INITIALIZER, SXMUTEX_TYPE_STATIC_6}
 | 
					 | 
				
			||||||
	};
 | 
					 | 
				
			||||||
	SyMutex *pMutex;
 | 
					 | 
				
			||||||
	if(nType == SXMUTEX_TYPE_FAST || nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
					 | 
				
			||||||
		pthread_mutexattr_t sRecursiveAttr;
 | 
					 | 
				
			||||||
		/* Allocate a new mutex */
 | 
					 | 
				
			||||||
		pMutex = (SyMutex *)malloc(sizeof(SyMutex));
 | 
					 | 
				
			||||||
		if(pMutex == 0) {
 | 
					 | 
				
			||||||
			return 0;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if(nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
					 | 
				
			||||||
			pthread_mutexattr_init(&sRecursiveAttr);
 | 
					 | 
				
			||||||
			pthread_mutexattr_settype(&sRecursiveAttr, PTHREAD_MUTEX_RECURSIVE);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		pthread_mutex_init(&pMutex->sMutex, nType == SXMUTEX_TYPE_RECURSIVE ? &sRecursiveAttr : 0);
 | 
					 | 
				
			||||||
		if(nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
					 | 
				
			||||||
			pthread_mutexattr_destroy(&sRecursiveAttr);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	} else {
 | 
					 | 
				
			||||||
		/* Use a pre-allocated static mutex */
 | 
					 | 
				
			||||||
		if(nType > SXMUTEX_TYPE_STATIC_6) {
 | 
					 | 
				
			||||||
			nType = SXMUTEX_TYPE_STATIC_6;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		pMutex = &aStaticMutexes[nType - 3];
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	pMutex->nType = nType;
 | 
					 | 
				
			||||||
	return pMutex;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void UnixMutexRelease(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
	if(pMutex->nType == SXMUTEX_TYPE_FAST || pMutex->nType == SXMUTEX_TYPE_RECURSIVE) {
 | 
					 | 
				
			||||||
		pthread_mutex_destroy(&pMutex->sMutex);
 | 
					 | 
				
			||||||
		free(pMutex);
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void UnixMutexEnter(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
	pthread_mutex_lock(&pMutex->sMutex);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void UnixMutexLeave(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
	pthread_mutex_unlock(&pMutex->sMutex);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/* Export pthread mutex interfaces */
 | 
					 | 
				
			||||||
static const SyMutexMethods sPthreadMutexMethods = {
 | 
					 | 
				
			||||||
	0, /* xGlobalInit() */
 | 
					 | 
				
			||||||
	0, /* xGlobalRelease() */
 | 
					 | 
				
			||||||
	UnixMutexNew,      /* xNew() */
 | 
					 | 
				
			||||||
	UnixMutexRelease,  /* xRelease() */
 | 
					 | 
				
			||||||
	UnixMutexEnter,    /* xEnter() */
 | 
					 | 
				
			||||||
	0,                 /* xTryEnter() */
 | 
					 | 
				
			||||||
	UnixMutexLeave     /* xLeave() */
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) {
 | 
					 | 
				
			||||||
	return &sPthreadMutexMethods;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#else
 | 
					 | 
				
			||||||
/* Host application must register their own mutex subsystem if the target
 | 
					 | 
				
			||||||
 * platform is not an UNIX-like or windows systems.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
struct SyMutex {
 | 
					 | 
				
			||||||
	sxu32 nType;
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
static SyMutex *DummyMutexNew(int nType) {
 | 
					 | 
				
			||||||
	static SyMutex sMutex;
 | 
					 | 
				
			||||||
	SXUNUSED(nType);
 | 
					 | 
				
			||||||
	return &sMutex;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void DummyMutexRelease(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
	SXUNUSED(pMutex);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void DummyMutexEnter(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
	SXUNUSED(pMutex);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
static void DummyMutexLeave(SyMutex *pMutex) {
 | 
					 | 
				
			||||||
	SXUNUSED(pMutex);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
/* Export the dummy mutex interfaces */
 | 
					 | 
				
			||||||
static const SyMutexMethods sDummyMutexMethods = {
 | 
					 | 
				
			||||||
	0, /* xGlobalInit() */
 | 
					 | 
				
			||||||
	0, /* xGlobalRelease() */
 | 
					 | 
				
			||||||
	DummyMutexNew,      /* xNew() */
 | 
					 | 
				
			||||||
	DummyMutexRelease,  /* xRelease() */
 | 
					 | 
				
			||||||
	DummyMutexEnter,    /* xEnter() */
 | 
					 | 
				
			||||||
	0,                  /* xTryEnter() */
 | 
					 | 
				
			||||||
	DummyMutexLeave     /* xLeave() */
 | 
					 | 
				
			||||||
};
 | 
					 | 
				
			||||||
PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void) {
 | 
					 | 
				
			||||||
	return &sDummyMutexMethods;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
#endif /* __WINNT__ */
 | 
					 | 
				
			||||||
@@ -724,6 +724,16 @@ PH7_PRIVATE sxi32 PH7_MemObjIsNull(ph7_value *pObj) {
 | 
				
			|||||||
	/* Assume empty by default */
 | 
						/* Assume empty by default */
 | 
				
			||||||
	return TRUE;
 | 
						return TRUE;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Check whether the ph7_value is an array (hashmap)
 | 
				
			||||||
 | 
					 * Returns TRUE if hashmap, FALSE otherwise.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					PH7_PRIVATE sxi32 PH7_MemObjIsHashmap(ph7_value *pObj) {
 | 
				
			||||||
 | 
						if(pObj->nType & MEMOBJ_HASHMAP) {
 | 
				
			||||||
 | 
							return TRUE;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return FALSE;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Check whether the ph7_value is numeric [i.e: int/float/bool] or looks
 | 
					 * Check whether the ph7_value is numeric [i.e: int/float/bool] or looks
 | 
				
			||||||
 * like a numeric number [i.e: if the ph7_value is of type string.].
 | 
					 * like a numeric number [i.e: if the ph7_value is of type string.].
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										56
									
								
								engine/vm.c
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								engine/vm.c
									
									
									
									
									
								
							@@ -2120,11 +2120,11 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
				}
 | 
									}
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
			 * JMPLFB: * * *
 | 
								 * LF_START: * * *
 | 
				
			||||||
			 *
 | 
								 *
 | 
				
			||||||
			 * Creates and enters the jump loop frame on the beginning of each iteration.
 | 
								 * Creates and enters the jump loop frame on the beginning of each iteration.
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			case PH7_OP_JMPLFB: {
 | 
								case PH7_OP_LF_START: {
 | 
				
			||||||
					VmFrame *pFrame = 0;
 | 
										VmFrame *pFrame = 0;
 | 
				
			||||||
					/* Enter the jump loop frame */
 | 
										/* Enter the jump loop frame */
 | 
				
			||||||
					rc = VmEnterFrame(&(*pVm), pVm->pFrame->pUserData, pVm->pFrame->pThis, &pFrame);
 | 
										rc = VmEnterFrame(&(*pVm), pVm->pFrame->pUserData, pVm->pFrame->pThis, &pFrame);
 | 
				
			||||||
@@ -2135,10 +2135,12 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
 | 
								 * LF_STOP: * * *
 | 
				
			||||||
 | 
								 *
 | 
				
			||||||
			 * Leaves and destroys the jump loop frame at the end of each iteration
 | 
								 * Leaves and destroys the jump loop frame at the end of each iteration
 | 
				
			||||||
			 * as well as on 'break' and 'continue' instructions.
 | 
								 * as well as on 'break' and 'continue' instructions.
 | 
				
			||||||
			 */
 | 
								 */
 | 
				
			||||||
			case PH7_OP_JMPLFE: {
 | 
								case PH7_OP_LF_STOP: {
 | 
				
			||||||
					/* Leave the jump loop frame */
 | 
										/* Leave the jump loop frame */
 | 
				
			||||||
					if(pVm->pFrame->iFlags & VM_FRAME_LOOP) {
 | 
										if(pVm->pFrame->iFlags & VM_FRAME_LOOP) {
 | 
				
			||||||
						VmLeaveFrame(&(*pVm));
 | 
											VmLeaveFrame(&(*pVm));
 | 
				
			||||||
@@ -2553,13 +2555,13 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
						if(pIdx) {
 | 
											if(pIdx) {
 | 
				
			||||||
							sxu32 nOfft;
 | 
												sxu32 nOfft;
 | 
				
			||||||
							if((pIdx->nType & MEMOBJ_INT) == 0) {
 | 
												if((pIdx->nType & MEMOBJ_INT) == 0) {
 | 
				
			||||||
								/* Force an int cast */
 | 
													/* No available index */
 | 
				
			||||||
								PH7_MemObjToInteger(pIdx);
 | 
													PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Index was outside the bounds of the array");
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
							nOfft = (sxu32)pIdx->x.iVal;
 | 
												nOfft = (sxu32)pIdx->x.iVal;
 | 
				
			||||||
							if(nOfft >= SyBlobLength(&pTos->sBlob)) {
 | 
												if(nOfft >= SyBlobLength(&pTos->sBlob)) {
 | 
				
			||||||
								/* Invalid offset,load null */
 | 
													/* No available index */
 | 
				
			||||||
								PH7_MemObjRelease(pTos);
 | 
													PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Index was outside the bounds of the array");
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								const char *zData = (const char *)SyBlobData(&pTos->sBlob);
 | 
													const char *zData = (const char *)SyBlobData(&pTos->sBlob);
 | 
				
			||||||
								int c = zData[nOfft];
 | 
													int c = zData[nOfft];
 | 
				
			||||||
@@ -2567,9 +2569,6 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
								MemObjSetType(pTos, MEMOBJ_STRING);
 | 
													MemObjSetType(pTos, MEMOBJ_STRING);
 | 
				
			||||||
								SyBlobAppend(&pTos->sBlob, (const void *)&c, sizeof(char));
 | 
													SyBlobAppend(&pTos->sBlob, (const void *)&c, sizeof(char));
 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
						} else {
 | 
					 | 
				
			||||||
							/* No available index,load NULL */
 | 
					 | 
				
			||||||
							MemObjSetType(pTos, MEMOBJ_NULL);
 | 
					 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
						break;
 | 
											break;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
@@ -2599,8 +2598,8 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
					if(rc == SXRET_OK) {
 | 
										if(rc == SXRET_OK) {
 | 
				
			||||||
						/* Load entry contents */
 | 
											/* Load entry contents */
 | 
				
			||||||
						if(pMap->iRef < 2) {
 | 
											if(pMap->iRef < 2) {
 | 
				
			||||||
							/* TICKET 1433-42: Array will be deleted shortly,so we will make a copy
 | 
												/* TICKET 1433-42: Array will be deleted shortly, so we will make a copy
 | 
				
			||||||
							 * of the entry value,rather than pointing to it.
 | 
												 * of the entry value, rather than pointing to it.
 | 
				
			||||||
							 */
 | 
												 */
 | 
				
			||||||
							pTos->nIdx = SXU32_HIGH;
 | 
												pTos->nIdx = SXU32_HIGH;
 | 
				
			||||||
							PH7_HashmapExtractNodeValue(pNode, pTos, TRUE);
 | 
												PH7_HashmapExtractNodeValue(pNode, pTos, TRUE);
 | 
				
			||||||
@@ -2610,9 +2609,8 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
							PH7_HashmapUnref(pMap);
 | 
												PH7_HashmapUnref(pMap);
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						/* No such entry, load NULL */
 | 
											/* No available index */
 | 
				
			||||||
						PH7_MemObjRelease(pTos);
 | 
											PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Index was outside the bounds of the array");
 | 
				
			||||||
						pTos->nIdx = SXU32_HIGH;
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					break;
 | 
										break;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
@@ -2856,17 +2854,14 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
				if(pTos < pStack) {
 | 
									if(pTos < pStack) {
 | 
				
			||||||
					goto Abort;
 | 
										goto Abort;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if((pTos->nType & (MEMOBJ_HASHMAP | MEMOBJ_OBJ | MEMOBJ_RES)) == 0) {
 | 
									if(PH7_MemObjIsNumeric(pTos) && !PH7_MemObjIsHashmap(pTos)) {
 | 
				
			||||||
					if(pTos->nIdx != SXU32_HIGH) {
 | 
										if(pTos->nIdx != SXU32_HIGH) {
 | 
				
			||||||
						ph7_value *pObj;
 | 
											ph7_value *pObj;
 | 
				
			||||||
						if((pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pTos->nIdx)) != 0) {
 | 
											if((pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pTos->nIdx)) != 0) {
 | 
				
			||||||
							/* Force a numeric cast */
 | 
					 | 
				
			||||||
							PH7_MemObjToNumeric(pObj);
 | 
					 | 
				
			||||||
							if(pObj->nType & MEMOBJ_REAL) {
 | 
												if(pObj->nType & MEMOBJ_REAL) {
 | 
				
			||||||
								pObj->x.rVal++;
 | 
													pObj->x.rVal++;
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								pObj->x.iVal++;
 | 
													pObj->x.iVal++;
 | 
				
			||||||
								MemObjSetType(pTos, MEMOBJ_INT);
 | 
					 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
							if(pInstr->iP1) {
 | 
												if(pInstr->iP1) {
 | 
				
			||||||
								/* Pre-increment */
 | 
													/* Pre-increment */
 | 
				
			||||||
@@ -2875,8 +2870,6 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
					} else {
 | 
										} else {
 | 
				
			||||||
						if(pInstr->iP1) {
 | 
											if(pInstr->iP1) {
 | 
				
			||||||
							/* Force a numeric cast */
 | 
					 | 
				
			||||||
							PH7_MemObjToNumeric(pTos);
 | 
					 | 
				
			||||||
							/* Pre-increment */
 | 
												/* Pre-increment */
 | 
				
			||||||
							if(pTos->nType & MEMOBJ_REAL) {
 | 
												if(pTos->nType & MEMOBJ_REAL) {
 | 
				
			||||||
								pTos->x.rVal++;
 | 
													pTos->x.rVal++;
 | 
				
			||||||
@@ -2886,6 +2879,9 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
 | 
				
			||||||
 | 
														"Increment operator cannot be applied to a non-numeric operand");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
@@ -2899,19 +2895,14 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
				if(pTos < pStack) {
 | 
									if(pTos < pStack) {
 | 
				
			||||||
					goto Abort;
 | 
										goto Abort;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if((pTos->nType & (MEMOBJ_HASHMAP | MEMOBJ_OBJ | MEMOBJ_RES | MEMOBJ_NULL)) == 0) {
 | 
									if(PH7_MemObjIsNumeric(pTos) & !PH7_MemObjIsHashmap(pTos)) {
 | 
				
			||||||
					/* Force a numeric cast */
 | 
					 | 
				
			||||||
					PH7_MemObjToNumeric(pTos);
 | 
					 | 
				
			||||||
					if(pTos->nIdx != SXU32_HIGH) {
 | 
										if(pTos->nIdx != SXU32_HIGH) {
 | 
				
			||||||
						ph7_value *pObj;
 | 
											ph7_value *pObj;
 | 
				
			||||||
						if((pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pTos->nIdx)) != 0) {
 | 
											if((pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pTos->nIdx)) != 0) {
 | 
				
			||||||
							/* Force a numeric cast */
 | 
					 | 
				
			||||||
							PH7_MemObjToNumeric(pObj);
 | 
					 | 
				
			||||||
							if(pObj->nType & MEMOBJ_REAL) {
 | 
												if(pObj->nType & MEMOBJ_REAL) {
 | 
				
			||||||
								pObj->x.rVal--;
 | 
													pObj->x.rVal--;
 | 
				
			||||||
							} else {
 | 
												} else {
 | 
				
			||||||
								pObj->x.iVal--;
 | 
													pObj->x.iVal--;
 | 
				
			||||||
								MemObjSetType(pTos, MEMOBJ_INT);
 | 
					 | 
				
			||||||
							}
 | 
												}
 | 
				
			||||||
							if(pInstr->iP1) {
 | 
												if(pInstr->iP1) {
 | 
				
			||||||
								/* Pre-decrement */
 | 
													/* Pre-decrement */
 | 
				
			||||||
@@ -2929,6 +2920,9 @@ static sxi32 VmByteCodeExec(
 | 
				
			|||||||
							}
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										PH7_VmThrowError(&(*pVm), PH7_CTX_ERR,
 | 
				
			||||||
 | 
														"Decrement operator cannot be applied to a non-numeric operand");
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				break;
 | 
									break;
 | 
				
			||||||
			/*
 | 
								/*
 | 
				
			||||||
@@ -5223,11 +5217,11 @@ static const char *VmInstrToString(sxi32 nOp) {
 | 
				
			|||||||
		case PH7_OP_JMPNZ:
 | 
							case PH7_OP_JMPNZ:
 | 
				
			||||||
			zOp = "JMPNZ";
 | 
								zOp = "JMPNZ";
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case PH7_OP_JMPLFB:
 | 
							case PH7_OP_LF_START:
 | 
				
			||||||
			zOp = "JMPLFB";
 | 
								zOp = "LF_START";
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case PH7_OP_JMPLFE:
 | 
							case PH7_OP_LF_STOP:
 | 
				
			||||||
			zOp = "JMPLFE";
 | 
								zOp = "LF_STOP";
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		case PH7_OP_POP:
 | 
							case PH7_OP_POP:
 | 
				
			||||||
			zOp = "POP";
 | 
								zOp = "POP";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -806,8 +806,6 @@ struct ph7 {
 | 
				
			|||||||
	SyMemBackend sAllocator;     /* Low level memory allocation subsystem */
 | 
						SyMemBackend sAllocator;     /* Low level memory allocation subsystem */
 | 
				
			||||||
	const ph7_vfs *pVfs;         /* Underlying Virtual File System */
 | 
						const ph7_vfs *pVfs;         /* Underlying Virtual File System */
 | 
				
			||||||
	ph7_conf xConf;              /* Configuration */
 | 
						ph7_conf xConf;              /* Configuration */
 | 
				
			||||||
	const SyMutexMethods *pMethods;  /* Mutex methods */
 | 
					 | 
				
			||||||
	SyMutex *pMutex;                 /* Per-engine mutex */
 | 
					 | 
				
			||||||
	ph7_vm *pVms;      /* List of active VM */
 | 
						ph7_vm *pVms;      /* List of active VM */
 | 
				
			||||||
	sxi32 iVm;         /* Total number of active VM */
 | 
						sxi32 iVm;         /* Total number of active VM */
 | 
				
			||||||
	ph7 *pNext, *pPrev; /* List of active engines */
 | 
						ph7 *pNext, *pPrev; /* List of active engines */
 | 
				
			||||||
@@ -1183,7 +1181,6 @@ struct ph7_switch {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
struct ph7_vm {
 | 
					struct ph7_vm {
 | 
				
			||||||
	SyMemBackend sAllocator;	/* Memory backend */
 | 
						SyMemBackend sAllocator;	/* Memory backend */
 | 
				
			||||||
	SyMutex *pMutex;            /* Recursive mutex associated with VM */
 | 
					 | 
				
			||||||
	ph7 *pEngine;               /* Interpreter that own this VM */
 | 
						ph7 *pEngine;               /* Interpreter that own this VM */
 | 
				
			||||||
	SySet aInstrSet;            /* Instructions debugging container */
 | 
						SySet aInstrSet;            /* Instructions debugging container */
 | 
				
			||||||
	SySet aByteCode;            /* Default bytecode container */
 | 
						SySet aByteCode;            /* Default bytecode container */
 | 
				
			||||||
@@ -1389,8 +1386,8 @@ enum ph7_vm_op {
 | 
				
			|||||||
	PH7_OP_JMP,          /* Unconditional jump */
 | 
						PH7_OP_JMP,          /* Unconditional jump */
 | 
				
			||||||
	PH7_OP_JMPZ,         /* Jump on zero (FALSE jump) */
 | 
						PH7_OP_JMPZ,         /* Jump on zero (FALSE jump) */
 | 
				
			||||||
	PH7_OP_JMPNZ,        /* Jump on non-zero (TRUE jump) */
 | 
						PH7_OP_JMPNZ,        /* Jump on non-zero (TRUE jump) */
 | 
				
			||||||
	PH7_OP_JMPLFB,       /* Jump loop frame begin */
 | 
						PH7_OP_LF_START,     /* Loop frame start */
 | 
				
			||||||
	PH7_OP_JMPLFE,       /* Jump loop frame end */
 | 
						PH7_OP_LF_STOP,      /* Loop frame stop */
 | 
				
			||||||
	PH7_OP_POP,          /* Stack POP */
 | 
						PH7_OP_POP,          /* Stack POP */
 | 
				
			||||||
	PH7_OP_CVT_INT,      /* Integer cast */
 | 
						PH7_OP_CVT_INT,      /* Integer cast */
 | 
				
			||||||
	PH7_OP_CVT_STR,      /* String cast */
 | 
						PH7_OP_CVT_STR,      /* String cast */
 | 
				
			||||||
@@ -1630,6 +1627,7 @@ PH7_PRIVATE sxi32 PH7_MemObjRelease(ph7_value *pObj);
 | 
				
			|||||||
PH7_PRIVATE sxi32 PH7_MemObjToNumeric(ph7_value *pObj);
 | 
					PH7_PRIVATE sxi32 PH7_MemObjToNumeric(ph7_value *pObj);
 | 
				
			||||||
PH7_PRIVATE ProcMemObjCast PH7_MemObjCastMethod(sxi32 iFlags);
 | 
					PH7_PRIVATE ProcMemObjCast PH7_MemObjCastMethod(sxi32 iFlags);
 | 
				
			||||||
PH7_PRIVATE sxi32 PH7_MemObjIsNull(ph7_value *pObj);
 | 
					PH7_PRIVATE sxi32 PH7_MemObjIsNull(ph7_value *pObj);
 | 
				
			||||||
 | 
					PH7_PRIVATE sxi32 PH7_MemObjIsHashmap(ph7_value *pObj);
 | 
				
			||||||
PH7_PRIVATE sxi32 PH7_MemObjIsNumeric(ph7_value *pObj);
 | 
					PH7_PRIVATE sxi32 PH7_MemObjIsNumeric(ph7_value *pObj);
 | 
				
			||||||
PH7_PRIVATE sxi32 PH7_MemObjIsEmpty(ph7_value *pObj);
 | 
					PH7_PRIVATE sxi32 PH7_MemObjIsEmpty(ph7_value *pObj);
 | 
				
			||||||
PH7_PRIVATE sxi32 PH7_MemObjToHashmap(ph7_value *pObj);
 | 
					PH7_PRIVATE sxi32 PH7_MemObjToHashmap(ph7_value *pObj);
 | 
				
			||||||
@@ -1871,8 +1869,6 @@ PH7_PRIVATE void *SyMemBackendPoolAlloc(SyMemBackend *pBackend, sxu32 nBytes);
 | 
				
			|||||||
PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk);
 | 
					PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk);
 | 
				
			||||||
PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes);
 | 
					PH7_PRIVATE void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, sxu32 nBytes);
 | 
				
			||||||
PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes);
 | 
					PH7_PRIVATE void *SyMemBackendAlloc(SyMemBackend *pBackend, sxu32 nBytes);
 | 
				
			||||||
	PH7_PRIVATE sxi32 SyMemBackendMakeThreadSafe(SyMemBackend *pBackend, const SyMutexMethods *pMethods);
 | 
					 | 
				
			||||||
	PH7_PRIVATE sxi32 SyMemBackendDisbaleMutexing(SyMemBackend *pBackend);
 | 
					 | 
				
			||||||
PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen);
 | 
					PH7_PRIVATE sxu32 SyMemcpy(const void *pSrc, void *pDest, sxu32 nLen);
 | 
				
			||||||
PH7_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize);
 | 
					PH7_PRIVATE sxi32 SyMemcmp(const void *pB1, const void *pB2, sxu32 nSize);
 | 
				
			||||||
PH7_PRIVATE void SyZero(void *pSrc, sxu32 nSize);
 | 
					PH7_PRIVATE void SyZero(void *pSrc, sxu32 nSize);
 | 
				
			||||||
@@ -1886,7 +1882,4 @@ PH7_PRIVATE sxu32 SyStrlen(const char *zSrc);
 | 
				
			|||||||
PH7_PRIVATE sxu32 Systrcpy(char *zDest, sxu32 nDestLen, const char *zSrc, sxu32 nLen);
 | 
					PH7_PRIVATE sxu32 Systrcpy(char *zDest, sxu32 nDestLen, const char *zSrc, sxu32 nLen);
 | 
				
			||||||
PH7_PRIVATE char *SyStrtok(char *str, const char *sep);
 | 
					PH7_PRIVATE char *SyStrtok(char *str, const char *sep);
 | 
				
			||||||
PH7_PRIVATE sxi32 SyAsciiToHex(sxi32 c);
 | 
					PH7_PRIVATE sxi32 SyAsciiToHex(sxi32 c);
 | 
				
			||||||
	PH7_PRIVATE const SyMutexMethods *SyMutexExportMethods(void);
 | 
					 | 
				
			||||||
	PH7_PRIVATE sxi32 SyMemBackendMakeThreadSafe(SyMemBackend *pBackend, const SyMutexMethods *pMethods);
 | 
					 | 
				
			||||||
	PH7_PRIVATE sxi32 SyMemBackendDisbaleMutexing(SyMemBackend *pBackend);
 | 
					 | 
				
			||||||
#endif /* __PH7INT_H__ */
 | 
					#endif /* __PH7INT_H__ */
 | 
				
			||||||
@@ -55,8 +55,10 @@ class Base32 {
 | 
				
			|||||||
			if(!in_array($input[$i], Base32::$map))
 | 
								if(!in_array($input[$i], Base32::$map))
 | 
				
			||||||
				return '';
 | 
									return '';
 | 
				
			||||||
			for(int $j = 0; $j < 8; $j++) {
 | 
								for(int $j = 0; $j < 8; $j++) {
 | 
				
			||||||
				if(array_key_exists($input[$i + $j], Base32::$flippedMap)) {
 | 
									if($i + $j < strlen($input)) {
 | 
				
			||||||
					$x += str_pad(base_convert(Base32::$flippedMap[$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
 | 
										if(array_key_exists($input[$i + $j], Base32::$flippedMap)) {
 | 
				
			||||||
 | 
											$x += str_pad(base_convert(Base32::$flippedMap[$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			string[] $eightBits = str_split($x, 8);
 | 
								string[] $eightBits = str_split($x, 8);
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user