⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 scriptengine.cpp

📁 php-4.4.7学习linux时下载的源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
		if (excepinfo) {			memset(excepinfo, 0, sizeof(EXCEPINFO));			excepinfo->wCode = 1000;			excepinfo->bstrSource = TWideString::bstr_from_ansi("fragment");			excepinfo->bstrDescription = TWideString::bstr_from_ansi("Problem while parsing/compiling");		}				return NULL;	}		return frag;}static void free_code_fragment(code_frag *frag){	switch(frag->fragtype) {		case FRAG_PROCEDURE:			if (frag->ptr) {				ScriptProcedureDispatch *disp = (ScriptProcedureDispatch*)frag->ptr;				disp->Release();				GIT_revoke(disp->m_gitcookie, (IDispatch*)disp);				frag->ptr = NULL;			}			break;	}		if (frag->opcodes)		destroy_op_array(frag->opcodes);	if (frag->functionname)		CoTaskMemFree(frag->functionname);	CoTaskMemFree(frag->code);	CoTaskMemFree(frag);}static code_frag *clone_code_fragment(code_frag *frag, TPHPScriptingEngine *engine TSRMLS_DC){	zval pv;	code_frag *newfrag = (code_frag*)CoTaskMemAlloc(sizeof(code_frag));	memset(newfrag, 0, sizeof(code_frag));	newfrag->engine = engine;trace("%08x: CLONED FRAG\n", newfrag);	newfrag->persistent = frag->persistent;	newfrag->codelen = frag->codelen;	newfrag->code = (char*)CoTaskMemAlloc(sizeof(char) * frag->codelen + 1);	memcpy(newfrag->code, frag->code, frag->codelen + 1);	if (frag->functionname) {		int namelen = strlen(frag->functionname);		newfrag->functionname = (char*)CoTaskMemAlloc(sizeof(char) * (namelen + 1));		memcpy(newfrag->functionname, frag->functionname, namelen+1);	} else {		newfrag->functionname = NULL;	}		newfrag->fragtype = frag->fragtype;	newfrag->starting_line = frag->starting_line;		pv.type = IS_STRING;	pv.value.str.val = newfrag->code;	pv.value.str.len = newfrag->codelen;	newfrag->opcodes = compile_string(&pv, "fragment" TSRMLS_CC);	if (newfrag->opcodes == NULL) {		free_code_fragment(newfrag);/*		if (excepinfo) {			memset(excepinfo, 0, sizeof(EXCEPINFO));			excepinfo->wCode = 1000;			excepinfo->bstrSource = TWideString::bstr_from_ansi("fragment");			excepinfo->bstrDescription = TWideString::bstr_from_ansi("Problem while parsing/compiling");		}*/				return NULL;	}		return newfrag;}static int execute_code_fragment(code_frag *frag,		VARIANT *varResult,		EXCEPINFO *excepinfo		TSRMLS_DC){	zval *retval_ptr = NULL;	jmp_buf	*orig_jmpbuf;	jmp_buf err_trap;	if (frag->fragtype == FRAG_MAIN && frag->executed)		return 1;		orig_jmpbuf = frag->engine->m_err_trap;	frag->engine->m_err_trap = &err_trap;	if (setjmp(err_trap) == 0) {		trace("*** Executing code in thread %08x\n", tsrm_thread_id());		if (frag->functionname) {			zval fname;			fname.type = IS_STRING;			fname.value.str.val = frag->functionname;			fname.value.str.len = strlen(frag->functionname);			call_user_function_ex(CG(function_table), NULL, &fname, &retval_ptr, 0, NULL, 1, NULL TSRMLS_CC);		} else {			zend_op_array 		*active_op_array		= EG(active_op_array);			zend_function_state	*function_state_ptr		= EG(function_state_ptr);			zval				**return_value_ptr_ptr	= EG(return_value_ptr_ptr);			zend_op				**opline_ptr			= EG(opline_ptr);			EG(return_value_ptr_ptr)	= &retval_ptr;			EG(active_op_array)			= frag->opcodes;			EG(no_extensions)			= 1;			zend_execute(frag->opcodes TSRMLS_CC);			EG(no_extensions)			= 0;			EG(opline_ptr)				= opline_ptr;			EG(active_op_array)			= active_op_array;			EG(function_state_ptr)		= function_state_ptr;			EG(return_value_ptr_ptr)	= return_value_ptr_ptr;		}	} else {		trace("*** --> caught error while executing\n");		if (frag->engine->m_in_main)			frag->engine->m_stop_main = 1;	}	frag->engine->m_err_trap = orig_jmpbuf;	if (frag->fragtype == FRAG_MAIN)		frag->executed = 1;	if (varResult)		VariantInit(varResult);		if (retval_ptr) {		if (varResult)			php_pval_to_variant(retval_ptr, varResult, CP_ACP TSRMLS_CC);		zval_ptr_dtor(&retval_ptr);	}	return 1;}static void frag_dtor(void *pDest){	code_frag *frag = *(code_frag**)pDest;	free_code_fragment(frag);}/* }}} *//* glue for getting back into the OO land */static DWORD WINAPI begin_engine_thread(LPVOID param){	TPHPScriptingEngine *engine = (TPHPScriptingEngine*)param;	engine->engine_thread_func();	trace("engine thread has really gone away!\n");	return 0;}TPHPScriptingEngine::TPHPScriptingEngine(){	m_scriptstate = SCRIPTSTATE_UNINITIALIZED;	m_pass = NULL;	m_in_main = 0;	m_stop_main = 0;	m_err_trap = NULL;	m_lambda_count = 0;	m_pass_eng = NULL;	m_refcount = 1;	m_basethread = tsrm_thread_id();	m_mutex = tsrm_mutex_alloc();	m_sync_thread_msg = CreateEvent(NULL, TRUE, FALSE, NULL);	TPHPClassFactory::AddToObjectCount();		m_engine_thread_handle = CreateThread(NULL, 0, begin_engine_thread, this, 0, &m_enginethread);	CloseHandle(m_engine_thread_handle);}void activescript_run_ticks(int count){	MSG msg;	TSRMLS_FETCH();	TPHPScriptingEngine *engine;		trace("ticking %d\n", count);		engine = (TPHPScriptingEngine*)SG(server_context);/*	PostThreadMessage(engine->m_enginethread, PHPSE_DUMMY_TICK, 0, 0); */		while(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {		if (msg.hwnd) {			PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);			TranslateMessage(&msg);			DispatchMessage(&msg);		} else {			break;		}	}}/* Synchronize with the engine thread */HRESULT TPHPScriptingEngine::SendThreadMessage(LONG msg, WPARAM wparam, LPARAM lparam){	HRESULT ret;	if (m_enginethread == 0)		return E_UNEXPECTED;	trace("I'm waiting for a mutex in SendThreadMessage\n   this=%08x ethread=%08x msg=%08x\n",			this, m_enginethread, msg);		tsrm_mutex_lock(m_mutex);	ResetEvent(m_sync_thread_msg);	/* If we call PostThreadMessage before the thread has created the queue, the message	 * posting fails.  MSDN docs recommend the following course of action */	while (!PostThreadMessage(m_enginethread, msg, wparam, lparam)) {		Sleep(50);		if (m_enginethread == 0) {			tsrm_mutex_unlock(m_mutex);			trace("breaking out of dodgy busy wait\n");			return E_UNEXPECTED;		}	}	/* Wait for the event object to be signalled.	 * This is a nice "blocking without blocking" wait; window messages are dispatched	 * and everything works out quite nicely */	while(1) {		DWORD result = MsgWaitForMultipleObjects(1, &m_sync_thread_msg, FALSE, 4000, QS_ALLINPUT);		if (result == WAIT_OBJECT_0 + 1) {			/* Dispatch some messages */			MSG msg;			while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {				//trace("dispatching message while waiting\n"); 				TranslateMessage(&msg);				DispatchMessage(&msg);			}		} else if (result == WAIT_TIMEOUT) {			trace("timeout while waiting for thread reply\n");		} else {			/* the event was signalled */			break;		}	}	ret = m_sync_thread_ret;	ResetEvent(m_sync_thread_msg);	tsrm_mutex_unlock(m_mutex);	return ret;}TPHPScriptingEngine::~TPHPScriptingEngine(){	trace("\n\n *** Engine Destructor Called\n\n");	if (m_scriptstate != SCRIPTSTATE_UNINITIALIZED && m_scriptstate != SCRIPTSTATE_CLOSED && m_enginethread)		Close();	PostThreadMessage(m_enginethread, WM_QUIT, 0, 0);	TPHPClassFactory::RemoveFromObjectCount();	tsrm_mutex_free(m_mutex);}/* Set some executor globals and execute a zend_op_array. * The declaration looks wierd because this can be invoked from * zend_hash_apply_with_argument */static int execute_main(void *pDest, void *arg TSRMLS_DC){	code_frag *frag = *(code_frag**)pDest;	if (frag->fragtype == FRAG_MAIN && !(frag->engine->m_in_main && frag->engine->m_stop_main))		execute_code_fragment(frag, NULL, NULL TSRMLS_CC);	return ZEND_HASH_APPLY_KEEP;}static int clone_frags(void *pDest, void *arg TSRMLS_DC){	code_frag *frag, *src = *(code_frag**)pDest;	TPHPScriptingEngine *engine = (TPHPScriptingEngine*)arg;	if (src->persistent) {		frag = clone_code_fragment(src, engine TSRMLS_CC);		if (frag)			zend_hash_next_index_insert(&engine->m_frags, &frag, sizeof(code_frag*), NULL);		else			trace("WARNING: clone failed!\n");	}	return ZEND_HASH_APPLY_KEEP;}	HRESULT TPHPScriptingEngine::engine_thread_handler(LONG msg, WPARAM wparam, LPARAM lParam, int *handled TSRMLS_DC){	HRESULT ret = S_OK;	trace("engine_thread_handler: running in thread %08x, should be %08x msg=%08x this=%08x\n",			tsrm_thread_id(), m_enginethread, msg, this);	if (handled)		*handled = 1;		if (m_enginethread == 0)		return E_UNEXPECTED;		switch(msg) {		case PHPSE_ADD_TYPELIB:			{				struct php_active_script_add_tlb_info *info = (struct php_active_script_add_tlb_info*)lParam;				ITypeLib *TypeLib;				if (SUCCEEDED(LoadRegTypeLib(*info->rguidTypeLib, (USHORT)info->dwMajor,								(USHORT)info->dwMinor, LANG_NEUTRAL, &TypeLib))) {					php_COM_load_typelib(TypeLib, CONST_CS TSRMLS_CC);					TypeLib->Release();				}			}			break;		case PHPSE_STATE_CHANGE:			{				/* handle the state change here */				SCRIPTSTATE ss = (SCRIPTSTATE)lParam;				int start_running = 0;				trace("%08x: DoSetScriptState(current=%s, new=%s)\n",						this,						scriptstate_to_string(m_scriptstate),						scriptstate_to_string(ss));				if (m_scriptstate == SCRIPTSTATE_INITIALIZED && (ss == SCRIPTSTATE_STARTED || ss == SCRIPTSTATE_CONNECTED))					start_running = 1;				m_scriptstate = ss;				/* inform host/site of the change */				if (m_pass_eng)					m_pass_eng->OnStateChange(m_scriptstate);				if (start_running) {					/* run "main()", as described in the docs */						if (m_pass_eng)						m_pass_eng->OnEnterScript();					trace("%08x: apply execute main to m_frags\n", this);					m_in_main = 1;					m_stop_main = 0;					zend_hash_apply_with_argument(&m_frags, execute_main, this TSRMLS_CC);					m_in_main = 0;					trace("%08x: --- done execute main\n", this);					if (m_pass_eng)						m_pass_eng->OnLeaveScript();					/* docs are a bit ambiguous here, but it appears that we should					 * inform the host that the main script execution has completed,					 * and also what the return value is */					VARIANT varRes;					VariantInit(&varRes);					if (m_pass_eng)						m_pass_eng->OnScriptTerminate(&varRes, NULL);					/*					   m_scriptstate = SCRIPTSTATE_INITIALIZED;					   if (m_pass_eng)					   m_pass_eng->OnStateChange(m_scriptstate);					   */				}			}			break;		case PHPSE_INIT_NEW:			{				/* Prepare PHP/ZE for use */				trace("%08x: m_frags : INIT NEW\n", this);				zend_hash_init(&m_frags, 0, NULL, frag_dtor, TRUE);				SG(options) |= SAPI_OPTION_NO_CHDIR;				SG(server_context) = this;				/* override the default PHP error callback */				zend_error_cb = activescript_error_handler;				zend_alter_ini_entry("register_argc_argv", 19, "1", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);				zend_alter_ini_entry("html_errors", 12, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);				zend_alter_ini_entry("implicit_flush", 15, "1", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);				zend_alter_ini_entry("max_execution_time", 19, "0", 1, PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE);				php_request_startup(TSRMLS_C);				PG(during_request_startup) = 0;				trace("\n\n     *** ticks func at %08x %08x ***\n\n\n", activescript_run_ticks, &activescript_run_ticks);//				php_add_tick_function(activescript_run_ticks);			}			break;		case PHPSE_CLOSE:			{				/* Close things down */				trace("%08x: m_frags : CLOSE/DESTROY\n", this);				m_scriptstate = SCRIPTSTATE_CLOSED;				if (m_pass_eng) {					m_pass_eng->OnStateChange(m_scriptstate);					trace("%08x: release site from this side\n", this);					m_pass_eng->Release();					m_pass_eng = NULL;				}				zend_hash_destroy(&m_frags);				php_request_shutdown(NULL);				break;			}			break;		case PHPSE_CLONE:			{				/* Clone the engine state.  This is semantically equal to serializing all				 * the parsed code from the source and unserializing it in the dest (this).				 * IE doesn't appear to use it, but Windows Script Host does. I'd expect				 * ASP/ASP.NET to do so also.				 *				 * FIXME: Probably won't work with IActiveScriptParseProcedure scriplets				 * */				TPHPScriptingEngine *src = (TPHPScriptingEngine*)lParam;				trace("%08x: m_frags : CLONE\n", this);				zend_hash_apply_with_argument(&src->m_frags, clone_frags, this TSRMLS_CC); 			}			break;		case PHPSE_ADD_SCRIPTLET:			{				/* Parse/compile a chunk of script that will act as an event handler.				 * If the host supports IActiveScriptParseProcedure, this code will				 * not be called.				 * The docs are (typically) vague: AFAICT, once the code has been				 * compiled, we are supposed to arrange for an IConnectionPoint				 * advisory connection to the item/subitem, once the script				 * moves into SCRIPTSTATE_CONNECTED.				 * That's a lot of work!				 *				 * FIXME: this is currently almost useless				 * */				struct php_active_script_add_scriptlet_info *info = (struct php_active_script_add_scriptlet_info*)lParam;				TWideString					default_name(info->pstrDefaultName),				code(info->pstrCode),				item_name(info->pstrItemName),				sub_item_name(info->pstrSubItemName),				event_name(info->pstrEventName),				delimiter(info->pstrDelimiter);				/* lets invent a function name for the scriptlet */				char sname[256];				/* should check if the name is already used! */				if (info->pstrDefaultName) 					strcpy(sname, default_name.ansi_string());				else {					sname[0] = 0;					strcat(sname, "__");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -