The first PDPjs script is operational (see /devices/pdp11/machine/1170/panel/debugger/xxdp)
This commit is contained in:
parent
f257cc3776
commit
033f0bf212
7 changed files with 1602 additions and 1373 deletions
|
|
@ -618,6 +618,159 @@ class Component {
|
|||
return ae;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component.getScriptCommands(sScript)
|
||||
*
|
||||
* @param {string} sScript
|
||||
* @return {Array}
|
||||
*/
|
||||
static getScriptCommands(sScript)
|
||||
{
|
||||
var cch = sScript.length;
|
||||
var aaCommands = [], aTokens = [], sToken = "", chQuote = null;
|
||||
for (var i = 0; i < cch; i++) {
|
||||
var ch = sScript[i];
|
||||
if (ch == '"' || ch == "'") {
|
||||
if (chQuote && ch != chQuote) {
|
||||
sToken += ch;
|
||||
continue;
|
||||
}
|
||||
if (!chQuote) {
|
||||
chQuote = ch;
|
||||
} else {
|
||||
chQuote = null;
|
||||
}
|
||||
if (sToken) {
|
||||
aTokens.push(sToken);
|
||||
sToken = "";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!chQuote) {
|
||||
if (ch == '\r' || ch == '\n') {
|
||||
ch = ';';
|
||||
}
|
||||
if (ch == ' ' || ch == '\t' || ch == ';') {
|
||||
if (sToken) {
|
||||
aTokens.push(sToken);
|
||||
sToken = "";
|
||||
}
|
||||
if (ch == ';' && aTokens.length) {
|
||||
aaCommands.push(aTokens);
|
||||
aTokens = [];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
sToken += ch;
|
||||
}
|
||||
if (aTokens.length) {
|
||||
aaCommands.push(aTokens);
|
||||
}
|
||||
return aaCommands;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component.processScript(idMachine, sComponent, sScript)
|
||||
*
|
||||
* @param {string} idMachine
|
||||
* @param {string} sComponent
|
||||
* @param {string} sScript
|
||||
* @return {boolean}
|
||||
*/
|
||||
static processScript(idMachine, sComponent, sScript)
|
||||
{
|
||||
var fSuccess = false;
|
||||
if (typeof sScript == "string") {
|
||||
fSuccess = true;
|
||||
var aaCommands = Component.getScriptCommands(sScript);
|
||||
if (!Component.processCommands(idMachine + ".machine", aaCommands, 0)) {
|
||||
fSuccess = false;
|
||||
}
|
||||
}
|
||||
return fSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component.processCommands(idMachine, aaCommands, iCommand)
|
||||
*
|
||||
* @param {string} idMachine
|
||||
* @param {Array} aaCommands
|
||||
* @param {number} iCommand
|
||||
* @return {boolean}
|
||||
*/
|
||||
static processCommands(idMachine, aaCommands, iCommand)
|
||||
{
|
||||
var fSuccess = true;
|
||||
while (iCommand < aaCommands.length) {
|
||||
|
||||
var aTokens = aaCommands[iCommand];
|
||||
var sCommand = aTokens[0];
|
||||
var fnScript = Component.scriptCommands[sCommand];
|
||||
var component = Component.getComponentByType(aTokens[1], idMachine);
|
||||
|
||||
if (fnScript) {
|
||||
fSuccess = fnScript(component, aTokens[2], aTokens[3]);
|
||||
}
|
||||
else {
|
||||
fSuccess = false;
|
||||
if (component) {
|
||||
var exports = component['exports'];
|
||||
if (exports) {
|
||||
var fnCommand = exports[sCommand];
|
||||
if (fnCommand) {
|
||||
if (sCommand == "wait") {
|
||||
var fnCallReady = function processNextCommand(iNextCommand) {
|
||||
return function() {
|
||||
Component.processCommands(idMachine, aaCommands, iNextCommand);
|
||||
}
|
||||
}(iCommand + 1);
|
||||
fSuccess = fnCommand.call(component, fnCallReady);
|
||||
break;
|
||||
}
|
||||
fSuccess = fnCommand.call(component, aTokens[2], aTokens[3]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!fSuccess) {
|
||||
Component.alertUser("error processing script command (" + sCommand + ")");
|
||||
break;
|
||||
}
|
||||
iCommand++;
|
||||
}
|
||||
return fSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* Component.scriptSelect(component, sBinding, sValue)
|
||||
*
|
||||
* @param {Component} component
|
||||
* @param {string} sBinding
|
||||
* @param {string} sValue
|
||||
* @return {boolean}
|
||||
*/
|
||||
static scriptSelect(component, sBinding, sValue)
|
||||
{
|
||||
var fSuccess = false;
|
||||
if (component) {
|
||||
var aBindings = component['bindings'];
|
||||
var control = aBindings[sBinding];
|
||||
if (control) {
|
||||
for (var i = 0; i < control.options.length; i++) {
|
||||
if (control.options[i].textContent == sValue) {
|
||||
if (control.selectedIndex != i) {
|
||||
control.selectedIndex = i;
|
||||
}
|
||||
fSuccess = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return fSuccess;
|
||||
}
|
||||
|
||||
/**
|
||||
* toString()
|
||||
*
|
||||
|
|
@ -1070,6 +1223,10 @@ if (window) {
|
|||
Component.machines = window? window['PCjs']['Machines'] : {};
|
||||
Component.components = window? window['PCjs']['Components'] : [];
|
||||
|
||||
Component.scriptCommands = {
|
||||
'select': Component.scriptSelect
|
||||
};
|
||||
|
||||
/*
|
||||
* The following polyfills provide ES5 functionality that's missing in older browsers (eg, IE8),
|
||||
* allowing PCjs apps to run without slamming into exceptions; however, due to the lack of HTML5 canvas
|
||||
|
|
|
|||
|
|
@ -606,8 +606,24 @@ function findMachineComponent(idMachine, sType)
|
|||
return Component.getComponentByType(sType, idMachine + ".machine");
|
||||
}
|
||||
|
||||
/**
|
||||
* processMachineScript(idMachine, sComponent, sScript)
|
||||
*
|
||||
* @param {string} idMachine
|
||||
* @param {string} sComponent
|
||||
* @param {string} sScript
|
||||
* @return {boolean}
|
||||
*/
|
||||
function processMachineScript(idMachine, sComponent, sScript)
|
||||
{
|
||||
return Component.processScript(idMachine, sComponent, sScript);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevent the Closure Compiler from renaming functions we want to export, by adding them as global properties.
|
||||
*
|
||||
* TODO: Consider making all these functions properties on a single global object (eg, 'PCjs'), to minimize global
|
||||
* pollution and risk of name collision.
|
||||
*/
|
||||
if (APPNAME == "C1Pjs") {
|
||||
window['embedC1P'] = embedC1P;
|
||||
|
|
@ -624,6 +640,7 @@ if (APPNAME == "PDPjs") {
|
|||
}
|
||||
|
||||
window['findMachineComponent'] = findMachineComponent;
|
||||
window['processMachineScript'] = processMachineScript;
|
||||
|
||||
window['enableEvents'] = Web.enablePageEvents;
|
||||
window['sendEvent'] = Web.sendPageEvent;
|
||||
|
|
|
|||
|
|
@ -94,9 +94,10 @@ function addStickyMachine(idMachine, sPosition)
|
|||
* website rather than of the machines. And since the machines are compiled, all their code and data is completely
|
||||
* opaque to us, except for those functions explicitly exported by embed.js.
|
||||
*
|
||||
* So now, in addition to the functions for embedding machines on a webpage, embed.js includes a new function:
|
||||
* So now, in addition to the functions for embedding machines on a webpage, embed.js includes a few new functions:
|
||||
*
|
||||
* findMachineComponent()
|
||||
* processMachineScript()
|
||||
*
|
||||
* which uses existing Component methods to find the requested component for a specific machine, and if the
|
||||
* component is found, then its 'exports' table is checked for an entry matching the specified command string, and if
|
||||
|
|
@ -106,30 +107,28 @@ function addStickyMachine(idMachine, sPosition)
|
|||
* @param {string} sComponent
|
||||
* @param {string} sCommand
|
||||
* @param {string} [sValue]
|
||||
* @return {boolean}
|
||||
*/
|
||||
function commandMachine(idMachine, sComponent, sCommand, sValue)
|
||||
{
|
||||
if (window.findMachineComponent) {
|
||||
if (sCommand == "script" && window.processMachineScript) {
|
||||
return window.processMachineScript(idMachine, sComponent, sValue);
|
||||
}
|
||||
if (sComponent && window.findMachineComponent) {
|
||||
var component = window.findMachineComponent(idMachine, sComponent);
|
||||
if (component) {
|
||||
if (sCommand == "script") {
|
||||
window.alert("commandScript('" + sValue + "')");
|
||||
} else {
|
||||
var exports = component['exports'];
|
||||
if (exports) {
|
||||
var fnCommand = exports[sCommand];
|
||||
if (fnCommand) {
|
||||
//noinspection JSUnresolvedFunction
|
||||
if (!fnCommand.call(component, sValue)) {
|
||||
window.alert("Error calling " + idMachine + "." + sComponent + "." + sCommand + "(" + sValue + ")");
|
||||
}
|
||||
return;
|
||||
}
|
||||
var exports = component['exports'];
|
||||
if (exports) {
|
||||
var fnCommand = exports[sCommand];
|
||||
if (fnCommand) {
|
||||
//noinspection JSUnresolvedFunction
|
||||
return !!fnCommand.call(component, sValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log("unimplemented: commandMachine('" + idMachine + "','" + sComponent + "','" + sCommand + "','" + sValue + "')");
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in a new issue