📄 vxi.cpp
字号:
vxistring defaultsUri; GetRuntimeProperty(VXI::PlatDefaultsURI, defaultsUri); // (1.2) Load platform defaults. try { VXIMapHolder domDefaultProp; AttemptDocumentLoad(defaultsUri, VXIMapHolder(NULL), domDefaultDoc, domDefaultProp, true); } catch (const VXIException::InterpreterEvent & e) { log->LogError(221, SimpleLogger::EXCEPTION, e.GetValue().c_str()); return 3; } // (2) Create a new execution context and initialize the defaults. // (2.1) Create new execution context. if (!PushExecutionContext(args)) return -1; // (2.1) Find generic language properties. VXMLElement defaultsRoot = domDefaultDoc.GetRoot(); for (VXMLNodeIterator it(defaultsRoot); it; ++it) { VXMLNode child = *it; if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & elem = reinterpret_cast<const VXMLElement &>(child); if (elem.GetName() != DEFAULTS_LANGUAGE) continue; vxistring id; elem.GetAttribute(ATTRIBUTE_ID, id); if (id != GENERIC_DEFAULTS) continue; exe->platDefaults = elem; break; } if (exe->platDefaults == 0) { log->LogError(221, SimpleLogger::EXCEPTION, L"error.semantic.missing_generic_defaults"); PopExecutionContext(); return 3; } // (2.2) Install defaults. We only need to worry about the properties (for // document load) and the ECMA variables and scripts (for catch handlers on // load failure). The grammars & prompts may be safely ignored. exe->properties.SetProperties(exe->platDefaults, DEFAULTS_PROP, VXIMapHolder()); exe->script.PushScope(SCOPE_Application); exe->script.PushScope(SCOPE_Defaults); ProcessRootScripts(exe->platDefaults); bool firstTime = true; int loopCount = 0; // (3) Start the loops through contexts and documents. int result; while (1) { // (3.1) Check loop count. Exit if exceeded if (++loopCount > MAX_DOCUMENTS) { log->LogError(210); result = 1; break; } try { if (firstTime) { firstTime = false; // (3) Jump to the initial document. Any events which occur while // loading the initial document are handled by the defaults. log->LogDiagnostic(2,L"VXI::RunOuterLoop - loading initial document."); try { DoOuterJump(exe->platDefaults, initialDocument); } catch (const VXIException::InterpreterEvent & e) { DoEvent(exe->platDefaults, e); PopExecutionContext(); throw VXIException::Exit(NULL); } } log->LogDiagnostic(2, L"VXI::RunOuterLoop - new document"); RunInnerLoop(); break; } catch (JumpDoc & e) { if (e.isSubdialog) if (!PushExecutionContext(args)) return -1; InstallDocument(e); } catch (JumpReturn &) { PopExecutionContext(); } catch (const VXIException::Exit & e) { // This handles <exit>. if (resultValue != NULL) *resultValue = e.exprResult; break; } } PopExecutionContext(); return 0;}void VXI::InstallDocument(JumpDoc & e){ // (1) Check to see what needs to be initialized. bool reinitApplication = e.isSubdialog || (e.applicationURI != exe->applicationURI); bool reinitDefaults = reinitApplication || (e.defaults != exe->platDefaults); // (2) Set the easy stuff. exe->platDefaults = e.defaults; exe->application = e.application; exe->applicationURI = e.applicationURI; exe->document = e.document; exe->currentDialog = e.documentDialog; exe->eventSource = VXMLElement(); exe->properties = e.properties; exe->gm.ReleaseGrammars(); VXMLElement documentRoot = exe->document.GetRoot(); VXMLElement applicationRoot = exe->application.GetRoot(); // (3) Load grammars. The grammars are reloaded using the current // understanding of the properties. During activation, the actual // proerties may differ slightly. try { exe->documentName = L""; exe->gm.LoadGrammars(documentRoot, exe->documentName, exe->properties); } catch (const VXIException::InterpreterEvent & e) { DoEvent(documentRoot, e); throw VXIException::Exit(NULL); } try { vxistring temp; exe->gm.LoadGrammars(exe->platDefaults, temp, exe->properties); } catch (const VXIException::InterpreterEvent & e) { DoEvent(exe->platDefaults, e); throw VXIException::Exit(NULL); } try { vxistring temp; exe->gm.LoadGrammars(applicationRoot, temp, exe->properties); } catch (const VXIException::InterpreterEvent & e) { DoEvent(applicationRoot, e); throw VXIException::Exit(NULL); } // (4) Clear existing ECMA script scopes. Scripter & script = exe->script; if (script.CurrentScope(SCOPE_Anonymous)) script.PopScope(); if (script.CurrentScope(SCOPE_Local)) script.PopScope(); if (script.CurrentScope(SCOPE_Dialog)) script.PopScope(); if (script.CurrentScope(SCOPE_Document)) script.PopScope(); if (script.CurrentScope(SCOPE_Defaults) && reinitDefaults) script.PopScope(); if (script.CurrentScope(SCOPE_Application) && reinitApplication) script.PopScope(); if (reinitApplication && !script.CurrentScope(SCOPE_Session)) { log->LogError(999,SimpleLogger::MESSAGE,L"ECMA Script scope inconsistent"); throw VXIException::Fatal(); } // (5) And set the new ones. try { if (script.CurrentScope(SCOPE_Session)) { script.PushScope(SCOPE_Application); ProcessRootScripts(applicationRoot); } } catch (const VXIException::InterpreterEvent & e) { DoEvent(applicationRoot, e); throw VXIException::Exit(NULL); } try { if (script.CurrentScope(SCOPE_Application)) { script.PushScope(SCOPE_Defaults); ProcessRootScripts(exe->platDefaults); } } catch (const VXIException::InterpreterEvent & e) { DoEvent(exe->platDefaults, e); throw VXIException::Exit(NULL); } try { script.PushScope(SCOPE_Document); ProcessRootScripts(documentRoot); } catch (const VXIException::InterpreterEvent & e) { DoEvent(documentRoot, e); throw VXIException::Exit(NULL); }}void VXI::DoOuterJump(const VXMLElement & elem, const vxistring & rawURI, VXIMap * rawSubmitData, bool isSubdialog){ if (log->IsLogging(2)) { log->StartDiagnostic(2) << L"VXI::DoOuterJump(" << rawURI << L")"; log->EndDiagnostic(); } VXIMapHolder submitData(rawSubmitData); // (1) Determine fetch properties for document load. // (1.1) Create empty fetch object. Now we need to fill this in. VXIMapHolder fetchobj; if (fetchobj.GetValue() == NULL) throw VXIException::OutOfMemory(); // (1.2) Set URIs for the Jump. vxistring uri(rawURI); vxistring fragment; // (1.2.1) Divide raw URI into uri + fragment. exe->properties.GetFetchobjURIs(elem, fetchobj, uri, fragment); // (1.2.2) Handle the (rare) degerate case. if (uri.empty() && fragment.empty()) { log->StartDiagnostic(0) << L"VXI::DoOuterJump - invalid URI, \"" << rawURI << L"\""; log->EndDiagnostic(); throw VXIException::InterpreterEvent(EV_ERROR_BADURI); } // (1.2.3) In the fragment only case, just go to the indicated item. if (uri.empty()) { VXMLElement targetElement = FindDialog(elem, fragment); if (targetElement == 0) { log->StartDiagnostic(0) << L"VXI::DoOuterJump - non-existent dialog, \"" << rawURI << L"\""; log->EndDiagnostic(); throw VXIException::InterpreterEvent(EV_ERROR_BADDIALOG); } if (!isSubdialog) throw JumpDialog(targetElement); else throw JumpDoc(exe->platDefaults, exe->application, exe->applicationURI, exe->document, targetElement, isSubdialog, exe->properties); } // TBD #pragma message ("VXI::DoOuterJump - ignoring fetchhint") // (1.3) Get remaining fetch properties. exe->properties.GetFetchobjCacheAttrs(elem, PropertyList::Document,fetchobj); if (submitData.GetValue() != NULL) { if (!exe->properties.GetFetchobjSubmitAttributes(elem, submitData, fetchobj)) { // This should never occur. log->StartDiagnostic(0) << L"VXI::DoOuterJump - couldn't set the submit " L"attributes."; log->EndDiagnostic(); throw VXIException::InterpreterEvent(EV_ERROR_BADURI); } submitData.Release(); // This map is now owned by fetchobj. } // (2) Load Document. // (2.1) Start fetch audio. vxistring fetchaudio; if (!elem.GetAttribute(ATTRIBUTE_FETCHAUDIO, fetchaudio)) fetchaudio = toString(exe->properties.GetProperty(L"fetchaudio")); if (!fetchaudio.empty()) pm->PlayFiller(fetchaudio); // (2.2) Do real work VXMLDocument document; VXMLElement documentDialog; VXIMapHolder documentFetchProps; AttemptDocumentLoad(uri, fetchobj, document, documentFetchProps); VXMLElement documentRoot = document.GetRoot(); documentDialog = FindDialog(documentRoot, fragment); if (documentDialog == 0) { if (fragment.empty()) log->StartDiagnostic(0) << L"VXI::DoOuterJump - no dialog element found " L"in \"" << uri << L"\""; else log->StartDiagnostic(0) << L"VXI::DoOuterJump - named dialog, " << fragment << L" not found in \"" << uri<<L"\""; log->EndDiagnostic(); throw VXIException::InterpreterEvent(EV_ERROR_BADDIALOG); } // (3) Get Document language & find associated defaults. // (3.1) Create a new property list containing the document properties. PropertyList newProperties(*log); // (3.2) Extract the language setting. const VXIchar * language = newProperties.GetProperty(PropertyList::Language); if (language == NULL) language = GENERIC_DEFAULTS; // (3.3) Find the language defaults. VXMLElement defaults; VXMLElement defaultsRoot = domDefaultDoc.GetRoot(); for (VXMLNodeIterator it(defaultsRoot); it; ++it) { VXMLNode child = *it; // Look for a language node. if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & elem = reinterpret_cast<const VXMLElement &>(child); if (elem.GetName() != DEFAULTS_LANGUAGE) continue; vxistring id; elem.GetAttribute(ATTRIBUTE_ID, id); if (id == language || (id == GENERIC_DEFAULTS && defaults == 0)) defaults = elem; } if (defaults != 0) newProperties.SetProperties(defaults, DEFAULTS_PROP, VXIMapHolder(NULL)); newProperties.SetProperties(documentRoot, DOC_PROP, documentFetchProps); // (4) Load the application. VXMLDocument application; VXIMapHolder appProperties; // (4.1) Get the application URI. vxistring appuri; documentRoot.GetAttribute(ATTRIBUTE_APPLICATION, appuri); if (!appuri.empty()) { // (4.2) Initialize application fetch parameters. VXIMapHolder appFetchobj; if (appFetchobj.GetValue() == NULL) throw VXIException::OutOfMemory(); vxistring appFragment; newProperties.GetFetchobjURIs(documentRoot, appFetchobj, appuri, appFragment); if (appuri.empty() || !appFragment.empty()) { log->LogError(214); throw VXIException::InterpreterEvent(EV_ERROR_APP_BADURI); } newProperties.GetFetchobjCacheAttrs(documentRoot, PropertyList::Document, appFetchobj); // (4.3) Load the application and its properties (we must then restore the // document properties. AttemptDocumentLoad(appuri, appFetchobj, application, appProperties); newProperties.SetProperties(application.GetRoot(), APP_PROP,appProperties); newProperties.SetProperties(documentRoot, DOC_PROP, documentFetchProps); // (4.4) Update appuri to absolute URI. const VXIValue* absuri = VXIMapGetProperty(appProperties.GetValue(), PropertyList::AbsoluteURI); if (VXIValueGetType(absuri) == VALUE_STRING) appuri = toString(reinterpret_cast<const VXIString *>(absuri)); } // (5) Generate the final event. throw JumpDoc(defaults, application, appuri, document, documentDialog, isSubdialog, newProperties);}// Finds the named dialog in the document. If the name is empty, the first// item is returned.//VXMLElement VXI::FindDialog(const VXMLElement & start, const vxistring & name){ if (log->IsLogging(2)) { log->StartDiagnostic(2) << L"VXI::FindDialog(" << name << L")"; log->EndDiagnostic(); } // (0) find the root node. VXMLElement doc; for (doc = start; doc != 0 && doc.GetName() != NODE_VXML; doc = doc.GetParent()); if (doc == 0) return VXMLElement(); // (1) Walk through all elements at this level and find match. for (VXMLNodeIterator it(doc); it; ++it) { VXMLNode child = *it; // (1.1) Only <form> & <menu> elements are considered. if (child.GetType() != VXMLNode::Type_VXMLElement) continue; const VXMLElement & elem = reinterpret_cast<const VXMLElement &>(child); VXMLElementType nodeName = elem.GetName(); if (nodeName != NODE_FORM && nodeName != NODE_MENU) continue; // (1.2) If no dialog was specified, return the first one. if (name.empty()) return elem; // (1.3) Otherwise, look for an exact match. vxistring id; if (!elem.GetAttribute(ATTRIBUTE__ITEMNAME, id)) continue; if (name == id) return elem; } // (2) User attempted to GOTO to non-existant dialog or have an empty doc! log->LogDiagnostic(2, L"VXI::FindDialog - no match found."); return VXMLElement();}//#############################################################################// Document Loop//#############################################################################// return success/failure (can't throw error here as caller needs// a chance to clean up// Also initialize new context (session scope)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -