📄 vxi.cpp
字号:
switch (id) {
case VXI::BeepURI: value = uriBeep; break;
case VXI::PlatDefaultsURI: value = uriPlatDefaults; break;
default: value.erase();
}
mutex.Unlock();
}
void VXI::DeclareStopRequest(bool doStop)
{
mutex.Lock();
stopRequested = doStop;
mutex.Unlock();
}
int VXI::DeclareExternalEvent(const VXIchar * event, const VXIchar * message)
{
// Check event
if (event == NULL || *event == L'\0' || *event == L'.') return 1;
bool lastWasPeriod = false;
// This could be stricter
for (const VXIchar * i = event; i != L'\0'; ++i) {
VXIchar c = *i;
if (c == L'.') {
if (lastWasPeriod) return 1;
lastWasPeriod = true;
}
if (c == L' ' || c == L'\t' || c == L'\n' || c == L'\r') return 1;
lastWasPeriod = false;
}
mutex.Lock();
externalEvents.push_back(event);
if (message == NULL || message == L'\0')
externalMessages.push_back(event);
else
externalMessages.push_back(message);
haveExternalEvents = true;
mutex.Unlock();
return 0;
}
int VXI::ClearExternalEventQueue()
{
mutex.Lock();
if( !externalEvents.empty() )
{
haveExternalEvents = false;
externalEvents.clear();
externalMessages.clear();
}
mutex.Unlock();
return 0;
}
int VXI::Run(const VXIchar * initialDocument,
const VXIchar * sessionScript,
SimpleLogger * resourceLog,
VXIinetInterface * resourceInet,
VXIcacheInterface * resourceCache,
VXIjsiInterface * resourceJsi,
VXIrecInterface * resourceRec,
VXIpromptInterface * resourcePrompt,
VXItelInterface * resourceTel,
VXIobjectInterface * resourceObject,
VXIValue ** resultValue)
{
// (1) Check arguments.
if (stopRequested) {
DeclareStopRequest(false);
if (log->IsLogging(2)) {
log->StartDiagnostic(2) << L"VXI::Run( STOP HAS BEEN REQUESTED ) exiting...";
log->EndDiagnostic();
}
return 4;
}
// (1.1) Check external resources
if (resourceLog == NULL || resourceInet == NULL || resourceJsi == NULL ||
resourceRec == NULL || resourcePrompt == NULL || resourceTel == NULL)
return 1;
log = resourceLog;
inet = resourceInet;
jsi = resourceJsi;
rec = resourceRec;
tel = resourceTel;
// These may be NULL.
object = resourceObject;
cache = resourceCache;
if (!pm->ConnectResources(log, resourcePrompt)) return 1;
if (log->IsLogging(2)) {
log->StartDiagnostic(2) << L"VXI::Run(" << initialDocument << L")";
log->EndDiagnostic();
}
// (1.2) Check document
if (initialDocument == NULL || wcslen(initialDocument) == 0) {
log->LogError(201);
return 1;
}
// (2) Delegate real work to RunDocumentLoop & handle the serious errors.
int exitCode;
try {
exitCode = RunDocumentLoop(initialDocument,
(sessionScript ? sessionScript : L""),
resultValue);
pm->PlayAll();
}
catch (VXIException::InterpreterEvent & e) {
log->LogError(207, SimpleLogger::EXCEPTION, e.GetValue().c_str());
exitCode = 0;
}
catch (const VXIException::Exit & e) {
*resultValue = e.exprResult;
exitCode = 0;
}
catch (const VXIException::Fatal &) {
log->LogError(209);
exitCode = -2;
}
catch (const VXIException::OutOfMemory &) {
PopExecutionContext();
log->LogError(202);
exitCode = 1;
}
catch (const VXIException::JavaScriptError &) {
log->LogError(212);
exitCode = -2;
}
catch (const VXIException::StopRequest &) {
exitCode = 4;
}
catch (const JumpDialog &) {
log->LogError(999, SimpleLogger::MESSAGE, L"unexpected jump to a dialog");
exitCode = -2;
}
catch (const JumpDoc &) {
log->LogError(999, SimpleLogger::MESSAGE,L"unexpected jump to a document");
exitCode = -2;
}
catch (const JumpItem &) {
log->LogError(999, SimpleLogger::MESSAGE, L"unexpected jump to an item");
exitCode = -2;
}
catch (const JumpReturn &) {
log->LogError(999, SimpleLogger::MESSAGE,
L"unexpected jump from a return element");
exitCode = -2;
}
// Clean up execution contexts.
try {
while (exe != NULL)
PopExecutionContext();
}
catch (const VXIException::JavaScriptError &) {
log->LogError(212);
exitCode = -2;
}
// Clean up event flags.
lineHungUp = false;
stopRequested = false;
//haveExternalEvents = false;
//externalEvents.clear();
//externalMessages.clear();
return exitCode;
}
int VXI::RunDocumentLoop(const vxistring & initialDocument,
const vxistring & sessionScript,
VXIValue ** resultValue)
{
// (1) Load the document containing the default handlers.
if (updateDefaultDoc) {
updateDefaultDoc = false;
log->LogDiagnostic(2, L"VXI::RunDocumentLoop - loading defaultDoc.");
// (1.1) Get URI if possible.
vxistring defaultsUri;
GetRuntimeProperty(VXI::PlatDefaultsURI, defaultsUri);
// (1.2) Load platform defaults.
try {
VXIMapHolder domDefaultProp;
if (log->IsLogging(4) && !defaultsUri.empty()) {
log->StartDiagnostic(4) << L"VXI: Loading platform defaults <"
<< defaultsUri << L">";
log->EndDiagnostic();
}
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(sessionScript)) return -1;
bool firstTime = true;
//VXIint32 loopCount = 0;
// (3) Start the loops through contexts and documents.
while (1) {
if (stopRequested) throw VXIException::StopRequest();
try {
if (firstTime) {
firstTime = false;
// Jump to the initial document. Any events which occur while
// loading the initial document are handled by the defaults.
log->LogDiagnostic(2, L"VXI::RunDocumentLoop - loading initial "
L"document.");
try {
PerformTransition(exe->platDefaults, initialDocument);
}
catch (const VXIException::InterpreterEvent & e) {
DoEvent(exe->platDefaults, e);
PopExecutionContext();
throw VXIException::Exit(NULL);
}
}
log->LogDiagnostic(2, L"VXI::RunDocumentLoop - new document");
RunInnerLoop();
break;
}
catch (JumpDoc & e) {
if (e.isSubdialog)
if (!PushExecutionContext(sessionScript)) return -1;
if (log->IsLogging(4)) {
if (e.isSubdialog)
log->StartDiagnostic(4) << L"VXI: Subdialog transition <"
<< e.documentURI << L">";
else
log->StartDiagnostic(4) << L"VXI: Document transition <"
<< e.documentURI << L">";
log->EndDiagnostic();
}
InstallDocument(e);
}
catch (JumpReturn &) {
PopExecutionContext();
if (log->IsLogging(4)) {
log->StartDiagnostic(4) << L"VXI: Subdialog returned to <"
<< exe->documentURI << L">";
log->EndDiagnostic();
}
}
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.
// If the transition is from leaf-to-root occurs in <submit> then
// the root context is initialized, otherwise it is preserved.
bool leafToRoot = !e.isSubmitElement && (!e.documentURI.empty())
&& (exe->applicationURI == e.documentURI);
bool reinitApplication
= e.isSubdialog ||
(e.applicationURI.empty() && exe->applicationURI.empty()) ||
(!leafToRoot && (e.applicationURI != exe->applicationURI));
// (2) Set the easy stuff.
exe->platDefaults = e.defaults;
exe->application = e.application;
exe->applicationURI = e.applicationURI;
exe->document = e.document;
exe->documentURI = e.documentURI;
exe->currentDialog = e.documentDialog;
exe->currentFormItem= VXMLElement();
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
// properties may differ slightly.
try {
exe->documentName = L"";
exe->gm.LoadGrammars(documentRoot, exe->documentName, exe->properties);
VXIPromptTranslator translator(exe->script);
pm->PreloadPrompts(documentRoot, exe->properties, translator);
}
catch (const VXIException::InterpreterEvent & e) {
DoEvent(documentRoot, e);
throw VXIException::Exit(NULL);
}
try {
vxistring temp;
exe->gm.LoadGrammars(applicationRoot, temp, exe->properties);
VXIPromptTranslator translator(exe->script);
pm->PreloadPrompts(applicationRoot, exe->properties, translator);
}
catch (const VXIException::InterpreterEvent & e) {
DoEvent(applicationRoot, e);
throw VXIException::Exit(NULL);
}
try {
vxistring temp;
exe->gm.LoadGrammars(exe->platDefaults, temp, exe->properties, true);
VXIPromptTranslator translator(exe->script);
pm->PreloadPrompts(exe->platDefaults, exe->properties, translator);
}
catch (const VXIException::InterpreterEvent & e) {
DoEvent(exe->platDefaults, 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_Application) && reinitApplication)
script.PopScope();
if (reinitApplication && !script.CurrentScope(SCOPE_Defaults)) {
log->LogError(999, SimpleLogger::MESSAGE,
L"ECMAScript scope inconsistent");
throw VXIException::Fatal();
}
// (5) And set the new ones.
try {
if (script.CurrentScope(SCOPE_Defaults)) {
script.PushScope(SCOPE_Application);
exe->script.MakeVar(L"lastresult$", L"undefined");
if (!exe->applicationURI.empty()) {
ProcessRootScripts(applicationRoot);
}
}
}
catch (const VXIException::InterpreterEvent & e) {
DoEvent(applicationRoot, e);
throw VXIException::Exit(NULL);
}
try {
script.PushScope(SCOPE_Document, leafToRoot || exe->applicationURI.empty());
if (!leafToRoot) {
ProcessRootScripts(documentRoot);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -