Fixes for 0.1.1 #56
							
								
								
									
										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 { | ||||
| 	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 */ | ||||
| 	sxi32 nEngine;                          /* Total number of active engines */ | ||||
| 	ph7 *pEngines;                          /* List of active engine */ | ||||
| @@ -44,23 +36,9 @@ static struct Global_Data { | ||||
| 	0, | ||||
| 	0, | ||||
| 	0, | ||||
| 	0, | ||||
| 	0, | ||||
| 	0, | ||||
| 	0 | ||||
| }; | ||||
| #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. | ||||
|  * return PH7_OK on success.Any other return | ||||
| @@ -186,63 +164,6 @@ static sxi32 PH7CoreConfigure(sxi32 nOp, va_list ap) { | ||||
| 				sMPGlobal.sAllocator.pUserData = pUserData; | ||||
| 				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: | ||||
| 			/* Unknown configuration option */ | ||||
| 			rc = PH7_CORRUPT; | ||||
| @@ -278,8 +199,6 @@ int ph7_lib_config(int nConfigOp, ...) { | ||||
|  */ | ||||
| static sxi32 PH7CoreInitialize(void) { | ||||
| 	const ph7_vfs *pVfs; /* Built-in vfs */ | ||||
| 	const SyMutexMethods *pMutexMethods = 0; | ||||
| 	SyMutex *pMaster = 0; | ||||
| 	int rc; | ||||
| 	/* | ||||
| 	 * If the library is already initialized,then a call to this routine | ||||
| @@ -292,30 +211,6 @@ static sxi32 PH7CoreInitialize(void) { | ||||
| 	pVfs = PH7_ExportBuiltinVfs(); | ||||
| 	/* Install it */ | ||||
| 	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) { | ||||
| 			/* Install a memory subsystem */ | ||||
| 			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; | ||||
| 			} | ||||
| 		} | ||||
| 		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 */ | ||||
| 		sMPGlobal.nMagic = PH7_LIB_MAGIC; | ||||
| 		rc = PH7_OK; | ||||
| 	} /* sMPGlobal.nMagic != PH7_LIB_MAGIC */ | ||||
| End: | ||||
| 	/* Unlock the master mutex */ | ||||
| 	SyMutexLeave(pMutexMethods, pMaster); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */ | ||||
| 	return rc; | ||||
| } | ||||
| /* | ||||
| @@ -391,18 +276,6 @@ static void PH7CoreShutdown(void) { | ||||
| 		pEngine = pNext; | ||||
| 		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) { | ||||
| 		/* Release the memory backend */ | ||||
| 		SyMemBackendRelease(&sMPGlobal.sAllocator); | ||||
| @@ -429,13 +302,7 @@ int ph7_lib_is_threadsafe(void) { | ||||
| 	if(sMPGlobal.nMagic != PH7_LIB_MAGIC) { | ||||
| 		return 0; | ||||
| 	} | ||||
| 	if(sMPGlobal.nThreadingLevel > PH7_THREAD_LEVEL_SINGLE) { | ||||
| 		/* Muli-threading support is enabled */ | ||||
| 		return 1; | ||||
| 	} else { | ||||
| 		/* Single-threading */ | ||||
| 		return 0; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| /* | ||||
|  * [CAPIREF: ph7_lib_version()] | ||||
| @@ -468,17 +335,9 @@ int ph7_config(ph7 *pEngine, int nConfigOp, ...) { | ||||
| 	if(PH7_ENGINE_MISUSE(pEngine)) { | ||||
| 		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); | ||||
| 	rc = EngineConfig(&(*pEngine), nConfigOp, ap); | ||||
| 	va_end(ap); | ||||
| 	/* Leave engine mutex */ | ||||
| 	SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ | ||||
| 	return rc; | ||||
| } | ||||
| /* | ||||
| @@ -510,28 +369,15 @@ int ph7_init(ph7 **ppEngine) { | ||||
| 	if(rc != PH7_OK) { | ||||
| 		goto Release; | ||||
| 	} | ||||
| 	SyMemBackendDisbaleMutexing(&pEngine->sAllocator); | ||||
| 	/* Default configuration */ | ||||
| 	SyBlobInit(&pEngine->xConf.sErrConsumer, &pEngine->sAllocator); | ||||
| 	/* Install a default compile-time error consumer routine */ | ||||
| 	ph7_config(pEngine, PH7_CONFIG_ERR_OUTPUT, PH7_VmBlobConsumer, &pEngine->xConf.sErrConsumer); | ||||
| 	/* Built-in vfs */ | ||||
| 	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 */ | ||||
| 	/* Enter the global mutex */ | ||||
| 	SyMutexEnter(sMPGlobal.pMutexMethods, sMPGlobal.pMutex); /* NO-OP if sMPGlobal.nThreadingLevel == PH7_THREAD_LEVEL_SINGLE */ | ||||
| 	MACRO_LD_PUSH(sMPGlobal.pEngines, pEngine); | ||||
| 	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 */ | ||||
| 	*ppEngine = pEngine; | ||||
| 	return PH7_OK; | ||||
| @@ -549,25 +395,11 @@ int ph7_release(ph7 *pEngine) { | ||||
| 	if(PH7_ENGINE_MISUSE(pEngine)) { | ||||
| 		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 */ | ||||
| 	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 */ | ||||
| 	MACRO_LD_REMOVE(sMPGlobal.pEngines, pEngine); | ||||
| 	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 */ | ||||
| 	SyMemBackendPoolFree(&sMPGlobal.sAllocator, pEngine); | ||||
| 	return rc; | ||||
| @@ -664,13 +496,6 @@ static sxi32 ProcessSourceFile( | ||||
| 	if(rc != PH7_OK) { | ||||
| 		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 */ | ||||
| 	MACRO_LD_PUSH(pEngine->pVms, pVm); | ||||
| 	pEngine->iVm++; | ||||
| @@ -697,16 +522,8 @@ int ph7_compile_code(ph7 *pEngine, const char *zSource, int nLen, ph7_vm **ppOut | ||||
| 		nLen = (int)SyStrlen(zSource); | ||||
| 	} | ||||
| 	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 */ | ||||
| 	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 */ | ||||
| 	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)) { | ||||
| 		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 | ||||
| 	 * [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 */ | ||||
| 	return rc; | ||||
| } | ||||
| @@ -787,18 +596,10 @@ int ph7_vm_config(ph7_vm *pVm, int iConfigOp, ...) { | ||||
| 	if(PH7_VM_MISUSE(pVm)) { | ||||
| 		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 */ | ||||
| 	va_start(ap, iConfigOp); | ||||
| 	rc = PH7_VmConfigure(&(*pVm), iConfigOp, ap); | ||||
| 	va_end(ap); | ||||
| 	/* Leave VM mutex */ | ||||
| 	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ | ||||
| 	return rc; | ||||
| } | ||||
| /* | ||||
| @@ -811,20 +612,12 @@ int ph7_vm_exec(ph7_vm *pVm, int *pExitStatus) { | ||||
| 	if(PH7_VM_MISUSE(pVm)) { | ||||
| 		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 */ | ||||
| 	rc = PH7_VmByteCodeExec(&(*pVm)); | ||||
| 	if(pExitStatus) { | ||||
| 		/* Exit status */ | ||||
| 		*pExitStatus = pVm->iExitStatus; | ||||
| 	} | ||||
| 	/* Leave VM mutex */ | ||||
| 	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ | ||||
| 	/* Execution result */ | ||||
| 	return rc; | ||||
| } | ||||
| @@ -838,15 +631,7 @@ int ph7_vm_reset(ph7_vm *pVm) { | ||||
| 	if(PH7_VM_MISUSE(pVm)) { | ||||
| 		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)); | ||||
| 	/* Leave VM mutex */ | ||||
| 	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ | ||||
| 	return rc; | ||||
| } | ||||
| /* | ||||
| @@ -860,32 +645,14 @@ int ph7_vm_release(ph7_vm *pVm) { | ||||
| 	if(PH7_VM_MISUSE(pVm)) { | ||||
| 		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; | ||||
| 	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) { | ||||
| 		/* 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); | ||||
| 		pEngine->iVm--; | ||||
| 		/* Release the memory chunk allocated to this VM */ | ||||
| 		SyMemBackendPoolFree(&pEngine->sAllocator, pVm); | ||||
| 		/* Leave engine mutex */ | ||||
| 		SyMutexLeave(sMPGlobal.pMutexMethods, pEngine->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ | ||||
| 	} | ||||
| 	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) { | ||||
| 		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 */ | ||||
| 	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; | ||||
| } | ||||
| /* | ||||
| @@ -930,12 +689,6 @@ int ph7_delete_function(ph7_vm *pVm, const char *zName) { | ||||
| 	if(PH7_VM_MISUSE(pVm)) { | ||||
| 		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 */ | ||||
| 	rc = SyHashDeleteEntry(&pVm->hHostFunction, (const void *)zName, SyStrlen(zName), (void **)&pFunc); | ||||
| 	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)); | ||||
| 		SyMemBackendPoolFree(&pVm->sAllocator, pFunc); | ||||
| 	} | ||||
| 	/* Leave VM mutex */ | ||||
| 	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ | ||||
| 	return rc; | ||||
| } | ||||
| /* | ||||
| @@ -970,16 +721,8 @@ int ph7_create_constant(ph7_vm *pVm, const char *zName, void (*xExpand)(ph7_valu | ||||
| 	if(xExpand == 0) { | ||||
| 		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 */ | ||||
| 	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; | ||||
| } | ||||
| /* | ||||
| @@ -993,12 +736,6 @@ int ph7_delete_constant(ph7_vm *pVm, const char *zName) { | ||||
| 	if(PH7_VM_MISUSE(pVm)) { | ||||
| 		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 */ | ||||
| 	rc = SyHashDeleteEntry(&pVm->hConstant, (const void *)zName, SyStrlen(zName), (void **)&pCons); | ||||
| 	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)); | ||||
| 		SyMemBackendPoolFree(&pVm->sAllocator, pCons); | ||||
| 	} | ||||
| 	/* Leave VM mutex */ | ||||
| 	SyMutexLeave(sMPGlobal.pMutexMethods, pVm->pMutex); /* NO-OP if sMPGlobal.nThreadingLevel != PH7_THREAD_LEVEL_MULTI */ | ||||
| 	return rc; | ||||
| } | ||||
| /* | ||||
|   | ||||
| @@ -1381,8 +1381,8 @@ static sxi32 PH7_CompileContinue(ph7_gen_state *pGen) { | ||||
| 	} else { | ||||
| 		sxu32 nInstrIdx = 0; | ||||
| 		if(!pLoop->bPostContinue) { | ||||
| 			/* Emit the OP_JMPLFE instruction to leave the loop frame */ | ||||
| 			PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0); | ||||
| 			/* Emit the OP_LF_STOP instruction to leave the loop frame */ | ||||
| 			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); | ||||
| 		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"); | ||||
| 	} else { | ||||
| 		sxu32 nInstrIdx; | ||||
| 		/* Emit the OP_JMPLFE instruction to leave the loop frame */ | ||||
| 		PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0); | ||||
| 		/* Emit the OP_LF_STOP instruction to leave the loop frame */ | ||||
| 		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); | ||||
| 		if(rc == SXRET_OK) { | ||||
| 			/* 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; | ||||
| 		} | ||||
| 		/* 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 */ | ||||
| 		if(SXRET_OK == PH7_VmEmitInstr(pGen->pVm, sJump.nLine, PH7_OP_JMP, 0, 0, 0, &sJump.nInstrIdx)) { | ||||
| 			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); | ||||
| 	/* Save the instruction index so we can fix it later when the jump destination is resolved */ | ||||
| 	PH7_GenStateNewJumpFixup(pWhileBlock, PH7_OP_JMPZ, nFalseJump); | ||||
| 	/* Emit the OP_JMPLFB instruction to enter a loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFB, 0, 0, 0, 0); | ||||
| 	/* Emit the OP_LF_START instruction to enter a loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_START, 0, 0, 0, 0); | ||||
| 	/* Compile the loop body */ | ||||
| 	rc = PH7_CompileBlock(&(*pGen)); | ||||
| 	if(rc == SXERR_ABORT) { | ||||
| 		return SXERR_ABORT; | ||||
| 	} | ||||
| 	/* Emit the OP_JMPLFE instruction to leave the loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0); | ||||
| 	/* Emit the OP_LF_STOP instruction to leave the loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0); | ||||
| 	/* Emit the unconditional jump to the start of the loop */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pWhileBlock->nFirstInstr, 0, 0); | ||||
| 	/* 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 */ | ||||
| 	pDoBlock->bPostContinue = TRUE; | ||||
| 	/* Emit the OP_JMPLFB instruction to enter a loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFB, 0, 0, 0, 0); | ||||
| 	/* Emit the OP_LF_START instruction to enter a loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_START, 0, 0, 0, 0); | ||||
| 	rc = PH7_CompileBlock(&(*pGen)); | ||||
| 	if(rc == SXERR_ABORT) { | ||||
| 		return SXERR_ABORT; | ||||
| @@ -1814,8 +1814,8 @@ static sxi32 PH7_CompileDoWhile(ph7_gen_state *pGen) { | ||||
| 	} | ||||
| 	pGen->pIn  = &pEnd[1]; | ||||
| 	pGen->pEnd = pTmp; | ||||
| 	/* Emit the OP_JMPLFE instruction to leave the loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0); | ||||
| 	/* Emit the OP_LF_STOP instruction to leave the loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0); | ||||
| 	/* Emit the true jump to the beginning of the loop */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPNZ, 0, pDoBlock->nFirstInstr, 0, 0); | ||||
| 	/* 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, | ||||
| 								 "for: Expected ';' after conditionals expressions"); | ||||
| 	} | ||||
| 	/* Emit the OP_JMPLFB instruction to enter a loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFB, 0, 0, 0, 0); | ||||
| 	/* Emit the OP_LF_START instruction to enter a loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_START, 0, 0, 0, 0); | ||||
| 	/* Jump the trailing ';' */ | ||||
| 	pGen->pIn++; | ||||
| 	/* 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); | ||||
| 		} | ||||
| 	} | ||||
| 	/* Emit the OP_JMPLFE instruction to leave the loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0); | ||||
| 	/* Emit the OP_LF_STOP instruction to leave the loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0); | ||||
| 	/* Emit the unconditional jump to the start of the loop */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pForBlock->nFirstInstr, 0, 0); | ||||
| 	/* 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); | ||||
| 	/* Save the instruction index so we can fix it later when the jump destination is resolved */ | ||||
| 	PH7_GenStateNewJumpFixup(pForeachBlock, PH7_OP_FOREACH_STEP, nFalseJump); | ||||
| 	/* Emit the OP_JMPLFB instruction to enter a loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFB, 0, 0, 0, 0); | ||||
| 	/* Emit the OP_LF_START instruction to enter a loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_START, 0, 0, 0, 0); | ||||
| 	/* Compile the loop body */ | ||||
| 	pGen->pIn = &pEnd[1]; | ||||
| 	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 */ | ||||
| 		return SXERR_ABORT; | ||||
| 	} | ||||
| 	/* Emit the OP_JMPLFE instruction to leave the loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMPLFE, 0, 0, 0, 0); | ||||
| 	/* Emit the OP_LF_STOP instruction to leave the loop frame */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_LF_STOP, 0, 0, 0, 0); | ||||
| 	/* Emit the unconditional jump to the start of the loop */ | ||||
| 	PH7_VmEmitInstr(pGen->pVm, nLine, PH7_OP_JMP, 0, pForeachBlock->nFirstInstr, 0, 0); | ||||
| 	/* Fix all jumps now the destination is resolved */ | ||||
|   | ||||
| @@ -273,33 +273,6 @@ PH7_PRIVATE sxi32 SyMemBackendFree(SyMemBackend *pBackend, void *pChunk) { | ||||
| 	} | ||||
| 	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 | ||||
|  */ | ||||
|   | ||||
| @@ -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 */ | ||||
| 	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 | ||||
|  * 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; | ||||
| 			/* | ||||
| 			 * JMPLFB: * * * | ||||
| 			 * LF_START: * * * | ||||
| 			 * | ||||
| 			 * 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; | ||||
| 					/* Enter the jump loop frame */ | ||||
| 					rc = VmEnterFrame(&(*pVm), pVm->pFrame->pUserData, pVm->pFrame->pThis, &pFrame); | ||||
| @@ -2135,10 +2135,12 @@ static sxi32 VmByteCodeExec( | ||||
| 					break; | ||||
| 				} | ||||
| 			/* | ||||
| 			 * LF_STOP: * * * | ||||
| 			 * | ||||
| 			 * Leaves and destroys the jump loop frame at the end of each iteration | ||||
| 			 * as well as on 'break' and 'continue' instructions. | ||||
| 			 */ | ||||
| 			case PH7_OP_JMPLFE: { | ||||
| 			case PH7_OP_LF_STOP: { | ||||
| 					/* Leave the jump loop frame */ | ||||
| 					if(pVm->pFrame->iFlags & VM_FRAME_LOOP) { | ||||
| 						VmLeaveFrame(&(*pVm)); | ||||
| @@ -2553,13 +2555,13 @@ static sxi32 VmByteCodeExec( | ||||
| 						if(pIdx) { | ||||
| 							sxu32 nOfft; | ||||
| 							if((pIdx->nType & MEMOBJ_INT) == 0) { | ||||
| 								/* Force an int cast */ | ||||
| 								PH7_MemObjToInteger(pIdx); | ||||
| 								/* No available index */ | ||||
| 								PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Index was outside the bounds of the array"); | ||||
| 							} | ||||
| 							nOfft = (sxu32)pIdx->x.iVal; | ||||
| 							if(nOfft >= SyBlobLength(&pTos->sBlob)) { | ||||
| 								/* Invalid offset,load null */ | ||||
| 								PH7_MemObjRelease(pTos); | ||||
| 								/* No available index */ | ||||
| 								PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Index was outside the bounds of the array"); | ||||
| 							} else { | ||||
| 								const char *zData = (const char *)SyBlobData(&pTos->sBlob); | ||||
| 								int c = zData[nOfft]; | ||||
| @@ -2567,9 +2569,6 @@ static sxi32 VmByteCodeExec( | ||||
| 								MemObjSetType(pTos, MEMOBJ_STRING); | ||||
| 								SyBlobAppend(&pTos->sBlob, (const void *)&c, sizeof(char)); | ||||
| 							} | ||||
| 						} else { | ||||
| 							/* No available index,load NULL */ | ||||
| 							MemObjSetType(pTos, MEMOBJ_NULL); | ||||
| 						} | ||||
| 						break; | ||||
| 					} | ||||
| @@ -2599,8 +2598,8 @@ static sxi32 VmByteCodeExec( | ||||
| 					if(rc == SXRET_OK) { | ||||
| 						/* Load entry contents */ | ||||
| 						if(pMap->iRef < 2) { | ||||
| 							/* TICKET 1433-42: Array will be deleted shortly,so we will make a copy | ||||
| 							 * of the entry value,rather than pointing to it. | ||||
| 							/* TICKET 1433-42: Array will be deleted shortly, so we will make a copy | ||||
| 							 * of the entry value, rather than pointing to it. | ||||
| 							 */ | ||||
| 							pTos->nIdx = SXU32_HIGH; | ||||
| 							PH7_HashmapExtractNodeValue(pNode, pTos, TRUE); | ||||
| @@ -2610,9 +2609,8 @@ static sxi32 VmByteCodeExec( | ||||
| 							PH7_HashmapUnref(pMap); | ||||
| 						} | ||||
| 					} else { | ||||
| 						/* No such entry, load NULL */ | ||||
| 						PH7_MemObjRelease(pTos); | ||||
| 						pTos->nIdx = SXU32_HIGH; | ||||
| 						/* No available index */ | ||||
| 						PH7_VmThrowError(&(*pVm), PH7_CTX_ERR, "Index was outside the bounds of the array"); | ||||
| 					} | ||||
| 					break; | ||||
| 				} | ||||
| @@ -2856,17 +2854,14 @@ static sxi32 VmByteCodeExec( | ||||
| 				if(pTos < pStack) { | ||||
| 					goto Abort; | ||||
| 				} | ||||
| 				if((pTos->nType & (MEMOBJ_HASHMAP | MEMOBJ_OBJ | MEMOBJ_RES)) == 0) { | ||||
| 				if(PH7_MemObjIsNumeric(pTos) && !PH7_MemObjIsHashmap(pTos)) { | ||||
| 					if(pTos->nIdx != SXU32_HIGH) { | ||||
| 						ph7_value *pObj; | ||||
| 						if((pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pTos->nIdx)) != 0) { | ||||
| 							/* Force a numeric cast */ | ||||
| 							PH7_MemObjToNumeric(pObj); | ||||
| 							if(pObj->nType & MEMOBJ_REAL) { | ||||
| 								pObj->x.rVal++; | ||||
| 							} else { | ||||
| 								pObj->x.iVal++; | ||||
| 								MemObjSetType(pTos, MEMOBJ_INT); | ||||
| 							} | ||||
| 							if(pInstr->iP1) { | ||||
| 								/* Pre-increment */ | ||||
| @@ -2875,8 +2870,6 @@ static sxi32 VmByteCodeExec( | ||||
| 						} | ||||
| 					} else { | ||||
| 						if(pInstr->iP1) { | ||||
| 							/* Force a numeric cast */ | ||||
| 							PH7_MemObjToNumeric(pTos); | ||||
| 							/* Pre-increment */ | ||||
| 							if(pTos->nType & MEMOBJ_REAL) { | ||||
| 								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; | ||||
| 			/* | ||||
| @@ -2899,19 +2895,14 @@ static sxi32 VmByteCodeExec( | ||||
| 				if(pTos < pStack) { | ||||
| 					goto Abort; | ||||
| 				} | ||||
| 				if((pTos->nType & (MEMOBJ_HASHMAP | MEMOBJ_OBJ | MEMOBJ_RES | MEMOBJ_NULL)) == 0) { | ||||
| 					/* Force a numeric cast */ | ||||
| 					PH7_MemObjToNumeric(pTos); | ||||
| 				if(PH7_MemObjIsNumeric(pTos) & !PH7_MemObjIsHashmap(pTos)) { | ||||
| 					if(pTos->nIdx != SXU32_HIGH) { | ||||
| 						ph7_value *pObj; | ||||
| 						if((pObj = (ph7_value *)SySetAt(&pVm->aMemObj, pTos->nIdx)) != 0) { | ||||
| 							/* Force a numeric cast */ | ||||
| 							PH7_MemObjToNumeric(pObj); | ||||
| 							if(pObj->nType & MEMOBJ_REAL) { | ||||
| 								pObj->x.rVal--; | ||||
| 							} else { | ||||
| 								pObj->x.iVal--; | ||||
| 								MemObjSetType(pTos, MEMOBJ_INT); | ||||
| 							} | ||||
| 							if(pInstr->iP1) { | ||||
| 								/* 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; | ||||
| 			/* | ||||
| @@ -5223,11 +5217,11 @@ static const char *VmInstrToString(sxi32 nOp) { | ||||
| 		case PH7_OP_JMPNZ: | ||||
| 			zOp = "JMPNZ"; | ||||
| 			break; | ||||
| 		case PH7_OP_JMPLFB: | ||||
| 			zOp = "JMPLFB"; | ||||
| 		case PH7_OP_LF_START: | ||||
| 			zOp = "LF_START"; | ||||
| 			break; | ||||
| 		case PH7_OP_JMPLFE: | ||||
| 			zOp = "JMPLFE"; | ||||
| 		case PH7_OP_LF_STOP: | ||||
| 			zOp = "LF_STOP"; | ||||
| 			break; | ||||
| 		case PH7_OP_POP: | ||||
| 			zOp = "POP"; | ||||
|   | ||||
| @@ -806,8 +806,6 @@ struct ph7 { | ||||
| 	SyMemBackend sAllocator;     /* Low level memory allocation subsystem */ | ||||
| 	const ph7_vfs *pVfs;         /* Underlying Virtual File System */ | ||||
| 	ph7_conf xConf;              /* Configuration */ | ||||
| 	const SyMutexMethods *pMethods;  /* Mutex methods */ | ||||
| 	SyMutex *pMutex;                 /* Per-engine mutex */ | ||||
| 	ph7_vm *pVms;      /* List of active VM */ | ||||
| 	sxi32 iVm;         /* Total number of active VM */ | ||||
| 	ph7 *pNext, *pPrev; /* List of active engines */ | ||||
| @@ -1183,7 +1181,6 @@ struct ph7_switch { | ||||
|  */ | ||||
| struct ph7_vm { | ||||
| 	SyMemBackend sAllocator;	/* Memory backend */ | ||||
| 	SyMutex *pMutex;            /* Recursive mutex associated with VM */ | ||||
| 	ph7 *pEngine;               /* Interpreter that own this VM */ | ||||
| 	SySet aInstrSet;            /* Instructions debugging container */ | ||||
| 	SySet aByteCode;            /* Default bytecode container */ | ||||
| @@ -1389,8 +1386,8 @@ enum ph7_vm_op { | ||||
| 	PH7_OP_JMP,          /* Unconditional jump */ | ||||
| 	PH7_OP_JMPZ,         /* Jump on zero (FALSE jump) */ | ||||
| 	PH7_OP_JMPNZ,        /* Jump on non-zero (TRUE jump) */ | ||||
| 	PH7_OP_JMPLFB,       /* Jump loop frame begin */ | ||||
| 	PH7_OP_JMPLFE,       /* Jump loop frame end */ | ||||
| 	PH7_OP_LF_START,     /* Loop frame start */ | ||||
| 	PH7_OP_LF_STOP,      /* Loop frame stop */ | ||||
| 	PH7_OP_POP,          /* Stack POP */ | ||||
| 	PH7_OP_CVT_INT,      /* Integer 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 ProcMemObjCast PH7_MemObjCastMethod(sxi32 iFlags); | ||||
| 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_MemObjIsEmpty(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 void *SyMemBackendRealloc(SyMemBackend *pBackend, void *pOld, 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 sxi32 SyMemcmp(const void *pB1, const void *pB2, 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 char *SyStrtok(char *str, const char *sep); | ||||
| 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)) | ||||
| 				return ''; | ||||
| 			for(int $j = 0; $j < 8; $j++) { | ||||
| 				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); | ||||
| 				if($i + $j < strlen($input)) { | ||||
| 					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); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user