Node pdp11 utility can now load machine XML files
This commit is contained in:
parent
0f680839f7
commit
1543583c01
1 changed files with 108 additions and 94 deletions
|
|
@ -33,10 +33,12 @@
|
||||||
var path = require("path");
|
var path = require("path");
|
||||||
var fs = require("fs");
|
var fs = require("fs");
|
||||||
var repl = require("repl");
|
var repl = require("repl");
|
||||||
|
var xml2js = require("xml2js");
|
||||||
var Defines = require("../../shared/es6/defines");
|
var Defines = require("../../shared/es6/defines");
|
||||||
var Str = require("../../shared/es6/strlib");
|
var Str = require("../../shared/es6/strlib");
|
||||||
var Proc = require("../../shared/es6/proclib");
|
var Proc = require("../../shared/es6/proclib");
|
||||||
|
|
||||||
|
var idAttrs = '@';
|
||||||
var fConsole = false;
|
var fConsole = false;
|
||||||
var fDebug = false;
|
var fDebug = false;
|
||||||
var args = Proc.getArgs();
|
var args = Proc.getArgs();
|
||||||
|
|
@ -185,118 +187,130 @@ function getComponentByType(sType)
|
||||||
return component;
|
return component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initMachine(xml)
|
||||||
|
*
|
||||||
|
* @param {Object} xml
|
||||||
|
*/
|
||||||
|
function initMachine(xml)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Clear any/all saved objects from any previous machine
|
||||||
|
*/
|
||||||
|
Component = dbg = null;
|
||||||
|
for (var i = 0; i < aComponents.length; i++) {
|
||||||
|
aComponents[i].objects = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
var machine = xml['machine'];
|
||||||
|
var idMachine = machine[idAttrs] && machine[idAttrs]['id'] || "";
|
||||||
|
|
||||||
|
for (var iComponent = 0; iComponent < aComponents.length; iComponent++) {
|
||||||
|
|
||||||
|
var component = aComponents[iComponent], aDevices = machine[component.name];
|
||||||
|
/*
|
||||||
|
* If aDevices is undefined, then that component does not exist in this machine.
|
||||||
|
*/
|
||||||
|
if (aDevices === undefined) continue;
|
||||||
|
|
||||||
|
for (var iDevice = 0; iDevice < aDevices.length; iDevice++) {
|
||||||
|
|
||||||
|
var obj;
|
||||||
|
var device = aDevices[iDevice];
|
||||||
|
var parmsObj = device[idAttrs];
|
||||||
|
|
||||||
|
if (idMachine) parmsObj['id'] = idMachine + '.' + parmsObj['id'];
|
||||||
|
|
||||||
|
if (fDebug) {
|
||||||
|
console.log("creating " + component.name + "...");
|
||||||
|
console.log(parmsObj);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (component.name == "cpu") {
|
||||||
|
parmsObj['autoStart'] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
obj = new component.Create(parmsObj);
|
||||||
|
} catch (err) {
|
||||||
|
console.log("error creating " + component.name + ": " + err.message);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(obj['id'] + " object created");
|
||||||
|
component.objects.push(obj);
|
||||||
|
|
||||||
|
if (obj.type == "Debugger") {
|
||||||
|
dbg = obj;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* loadMachine(sFile)
|
* loadMachine(sFile)
|
||||||
*
|
*
|
||||||
* @param {string} sFile
|
* @param {string} sFile
|
||||||
* @return {Object} representing the machine whose component objects have been loaded into aComponents
|
* @return {boolean}
|
||||||
*/
|
*/
|
||||||
function loadMachine(sFile)
|
function loadMachine(sFile)
|
||||||
{
|
{
|
||||||
if (fDebug) console.log('loadMachine("' + sFile + '")');
|
if (fDebug) console.log('loadMachine("' + sFile + '")');
|
||||||
|
var xml = {_resolving: 0};
|
||||||
/*
|
return readXML(xml, 'machine', sFile, null, 0, initMachine);
|
||||||
* Clear any/all saved objects from any previous machine
|
}
|
||||||
*/
|
|
||||||
var i, j;
|
/**
|
||||||
Component = dbg = null;
|
* readXML(xml, sNode, sFile, aTags, iTag, done)
|
||||||
for (i = 0; i < aComponents.length; i++) {
|
*
|
||||||
aComponents[i].objects = [];
|
* @param {Object} xml
|
||||||
}
|
* @param {string} sNode
|
||||||
|
* @param {string} sFile
|
||||||
var machine;
|
* @param {Array|null} aTags
|
||||||
|
* @param {number} iTag
|
||||||
|
* @param {function(Object)} done
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
function readXML(xml, sNode, sFile, aTags, iTag, done)
|
||||||
|
{
|
||||||
|
var fLoading = false;
|
||||||
try {
|
try {
|
||||||
/*
|
xml._resolving++;
|
||||||
* Since our JSON files may contain comments, hex values, and/or other tokens deemed
|
var sXML = fs.readFileSync(sFile, {encoding: "utf8"});
|
||||||
* unacceptable by the JSON Overlords, we can't use require() to load it, as we're able to
|
var parser = new xml2js.Parser({attrkey: idAttrs});
|
||||||
* do with "package.json". Also note that require() assumes the same path as that of the
|
parser.parseString(sXML, function(err, xmlNode) {
|
||||||
* requiring file, whereas fs.readFileSync() assumes the path reported by process.cwd().
|
if (!aTags) {
|
||||||
*
|
xml[sNode] = xmlNode[sNode];
|
||||||
* TODO: I've since removed the comments from my sample "ibm5150.json" file, so we could
|
} else {
|
||||||
* try to reinstate this code; however, there are still hex constants, which I find *much*
|
aTags[iTag] = xmlNode[sNode];
|
||||||
* preferable to the decimal equivalents. JSON's restrictions continue to irritate me.
|
|
||||||
*
|
|
||||||
* var machine = require(lib + "../bin/" +sFile);
|
|
||||||
*/
|
|
||||||
var sMachine = fs.readFileSync(sFile, {encoding: "utf8"});
|
|
||||||
sMachine = '(' + sMachine + ')';
|
|
||||||
if (fDebug) console.log(sMachine);
|
|
||||||
machine = eval(sMachine); // jshint ignore:line
|
|
||||||
if (machine) {
|
|
||||||
/*
|
|
||||||
* Since we have a machine object, we now mimic the initialization sequence that occurs
|
|
||||||
* in the browser, by walking the list of PDPjs components we loaded above and looking for
|
|
||||||
* matches.
|
|
||||||
*/
|
|
||||||
var idMachine = "";
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 'machine' is a pseudo-component that is only used to define an ID for the entire machine;
|
|
||||||
* if it exists, then that ID is prepended to every component ID, just as our XSLT code would
|
|
||||||
* do for a machine XML file. This relieves the JSON file from having to manually prepend
|
|
||||||
* a machine ID to every component ID itself.
|
|
||||||
*
|
|
||||||
* This doesn't mean I anticipate a Node environment running multiple machines, as we do in
|
|
||||||
* a browser; it only means that I'm trying to make both environments operate similarly.
|
|
||||||
*/
|
|
||||||
if (machine['machine']) {
|
|
||||||
idMachine = machine['machine']['id'];
|
|
||||||
}
|
}
|
||||||
|
if (err) {
|
||||||
for (i = 0; i < aComponents.length; i++) {
|
console.log(err.message);
|
||||||
|
}
|
||||||
var component = aComponents[i];
|
else if (xmlNode && xmlNode[sNode]) {
|
||||||
var parms = machine[component.name];
|
for (var sTag in xmlNode[sNode]) {
|
||||||
/*
|
var aTagsXML = xmlNode[sNode][sTag];
|
||||||
* If parms is undefined, it means there is no component with that name defined in the
|
for (var iTagXML = 0; iTagXML < aTagsXML.length; iTagXML++) {
|
||||||
* machine object (NOT that the component has no parms), and therefore we should skip it.
|
var tag = aTagsXML[iTagXML];
|
||||||
*/
|
var attrs = tag[idAttrs];
|
||||||
if (parms === undefined) continue;
|
if (attrs) {
|
||||||
/*
|
for (var attr in attrs) {
|
||||||
* If parms is an Array, then we must create an object for each parms element; and yes,
|
if (attr == "ref") {
|
||||||
* I'm relying on the fact that none of my parm objects use a "length" property, as a quick
|
var sFileXML = "../../.." + attrs[attr];
|
||||||
* and dirty way of differentiating objects from arrays.
|
readXML(xml, sTag, sFileXML, aTagsXML, iTagXML, done);
|
||||||
*/
|
}
|
||||||
var aParms = parms.length !== undefined? parms : [parms];
|
}
|
||||||
for (j = 0; j < aParms.length; j++) {
|
}
|
||||||
|
|
||||||
var obj;
|
|
||||||
var parmsObj = aParms[j];
|
|
||||||
if (idMachine) parmsObj['id'] = idMachine + '.' + parmsObj['id'];
|
|
||||||
|
|
||||||
if (fDebug) {
|
|
||||||
console.log("creating " + component.name + "...");
|
|
||||||
console.log(parmsObj);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (component.name == "cpu") {
|
|
||||||
parmsObj['autoStart'] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
obj = new component.Create(parmsObj);
|
|
||||||
} catch(err) {
|
|
||||||
console.log("error creating " + component.name + ": " + err.message);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(obj['id'] + " object created");
|
|
||||||
component.objects.push(obj);
|
|
||||||
|
|
||||||
if (obj.type == "Debugger") {
|
|
||||||
dbg = obj;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!--xml._resolving) done(xml);
|
||||||
}
|
}
|
||||||
/*
|
});
|
||||||
* Return the original machine object only in DEBUG mode
|
fLoading = true;
|
||||||
*/
|
|
||||||
if (!fDebug) machine = true;
|
|
||||||
}
|
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
console.log(err.message);
|
console.log(err.message);
|
||||||
}
|
}
|
||||||
return machine;
|
return fLoading;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue