impl of autoexec.bat (wip)

This commit is contained in:
minjaesong
2020-11-04 14:33:27 +09:00
parent c90c4987a9
commit 3b2870ec9c
5 changed files with 138 additions and 92 deletions

View File

@@ -1 +1 @@
let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0], "DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode([0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power"); let p=_BIOS.FIRST_BOOTABLE_PORT;com.sendMessage(p[0],"DEVRST\x17");com.sendMessage(p[0],'OPENR"tvdos/TVDOS.SYS",'+p[1]);let r=com.getStatusCode(p[0]);if(0==r)if(com.sendMessage(p[0],"READ"),r=com.getStatusCode([0]),0==r){let g=com.pullMessage(p[0]);eval(g)}else println("I/O Error");else println("TVDOS.SYS not found");println("Shutting down...");println("It is now safe to turn off the power");

2
assets/AUTOEXEC.BAT Normal file
View File

@@ -0,0 +1,2 @@
echo "Hello, world!"
fsh

View File

@@ -10,7 +10,7 @@ _TVDOS.DRIVES["A"] = _BIOS.FIRST_BOOTABLE_PORT;
_TVDOS.defaults = { _TVDOS.defaults = {
path: [ path: [
"/tvdos/bin" "\\tvdos\\bin\\"
] ]
}; };
Object.freeze(_TVDOS); Object.freeze(_TVDOS);
@@ -31,8 +31,11 @@ filesystem._close = function(portNo) {
filesystem._flush = function(portNo) { filesystem._flush = function(portNo) {
com.sendMessage(portNo, "FLUSH"); com.sendMessage(portNo, "FLUSH");
}; };
// @return true if operation committed successfully, false otherwise; throws error // @return true if operation committed successfully, false if:
// if unknown mode or invalid drive letter was given // - opening file with R-mode and target file does not exists
// throws if:
// - java.lang.NullPointerException if path is null
// - Error if operation mode is not "R", "W" nor "A"
filesystem.open = function(driveLetter, path, operationMode) { filesystem.open = function(driveLetter, path, operationMode) {
let port = filesystem._toPorts(driveLetter); let port = filesystem._toPorts(driveLetter);
@@ -67,7 +70,8 @@ filesystem.open("A", "tvdos/gl.js", "R");
var GL = eval(filesystem.readAll("A")); var GL = eval(filesystem.readAll("A"));
// @param cmdsrc JS source code // @param cmdsrc JS source code
// @param args arguments for the program, must be Array // @param args arguments for the program, must be Array, and args[0] is always the name of the program, e.g.
// for command line 'echo foo bar', args[0] must be 'echo'
var execApp = function(cmdsrc, args) { var execApp = function(cmdsrc, args) {
let prg = eval("let _appStub=function(exec_args){"+cmdsrc+"};_appStub;"); // making 'exec_args' a app-level global let prg = eval("let _appStub=function(exec_args){"+cmdsrc+"};_appStub;"); // making 'exec_args' a app-level global
return prg(args); return prg(args);
@@ -78,8 +82,4 @@ var execApp = function(cmdsrc, args) {
// Boot script // Boot script
filesystem.open("A", "tvdos/command.js", "R"); filesystem.open("A", "tvdos/command.js", "R");
let cmdsrc = filesystem.readAll("A"); let cmdsrc = filesystem.readAll("A");
execApp(cmdsrc, ["", "/c", "\\AUTOEXEC.BAT"]);
// app execution stub
execApp(cmdsrc);
//let sh = execApp(cmdsrc, [42]);
//println(sh.test);

View File

@@ -6,25 +6,11 @@ let shell_pwd = [];
const welcome_text = "TSVM Disk Operating System, version " + _TVDOS.VERSION; const welcome_text = "TSVM Disk Operating System, version " + _TVDOS.VERSION;
function print_prompt_text() { function print_prompt_text() {
//print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT); print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT);
con.color_pair(239,161);
print(" "+CURRENT_DRIVE+":");
con.color_pair(161,253);
con.addch(16);
con.color_pair(0,253);
print(" \\"+shell_pwd.join("\\")+" ");
con.color_pair(253,255);
con.addch(16);
con.addch(32);
con.color_pair(239,255);
} }
function greet() { function greet() {
con.color_pair(0,253); println(welcome_text);
//print(welcome_text + " ".repeat(_fsh.scrwidth - welcome_text.length));
print(welcome_text + " ".repeat(80 - welcome_text.length));
con.color_pair(239,255);
println();
} }
@@ -129,27 +115,77 @@ Object.freeze(shell.coreutils);
shell.execute = function(line) { shell.execute = function(line) {
if (line.size == 0) return; if (line.size == 0) return;
let tokens = shell.parse(line); let tokens = shell.parse(line);
let cmd = tokens[0].toLowerCase(); let cmd = tokens[0];
if (shell.coreutils[cmd] !== undefined) {
shell.coreutils[cmd](tokens); if (shell.coreutils[cmd.toLowerCase()] !== undefined) {
let retval = shell.coreutils[cmd.toLowerCase()](tokens);
return retval|0; // return value of undefined will cast into 0
} }
else { else {
// search through PATH for execution
let fileExists = false;
let searchDir = (cmd.startsWith("\\")) ? [""] : ["\\"+shell_pwd.join("\\")].concat(_TVDOS.defaults.path);
searchDir.forEach(function(it) { serial.println("Searchdir: "+it); });
for (let i = 0; i < searchDir.length; i++) {
let path = (searchDir[i] + cmd).substring(1); // without substring, this will always prepend revslash
if (filesystem.open(CURRENT_DRIVE, path, "R")) {
fileExists = true;
break;
}
}
if (!fileExists) {
printerrln('Bad command or filename: "'+cmd+'"'); printerrln('Bad command or filename: "'+cmd+'"');
return -1;
}
else {
let prg = filesystem.readAll(CURRENT_DRIVE);
let extension = undefined;
// get proper extension
let dotSepTokens = cmd.split('.');
if (dotSepTokens.length > 1) extension = dotSepTokens[dotSepTokens.length - 1].toUpperCase();
if ("BAT" == extension) {
// parse and run as batch file
let lines = prg.split('\n').filter(function(it) { return it.length > 0; });
lines.forEach(function(it) { println("Batch: " + it) }); // TODO
}
else {
return execApp(prg, tokens)|0; // return value of undefined will cast into 0
}
}
} }
}; };
if (exec_args !== undefined) return Object.freeze(shell); Object.freeze(shell);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
println("Starting TVDOS...");
greet(); if (exec_args !== undefined) {
// command /c <commands>
// ^[0] ^[1] ^[2]
if (exec_args[1].toLowerCase() == "/c") {
if (exec_args[2] == "") return 0; // no commands were given, just exit successfully
return shell.execute(exec_args[2]);
}
else {
printerrln("Invalid switch: "+exec_args[1]);
return 1;
}
}
else {
println("Starting TVDOS...");
let cmdHistory = []; // zeroth element is the oldest greet();
let cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
let cmdExit = false; let cmdHistory = []; // zeroth element is the oldest
while (!cmdExit) { let cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
let cmdExit = false;
while (!cmdExit) {
print_prompt_text(); print_prompt_text();
let cmdbuf = ""; let cmdbuf = "";
@@ -217,6 +253,7 @@ while (!cmdExit) {
} }
} }
} }
}
} }
return 0; return 0;

View File

@@ -31,6 +31,12 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
} }
} }
private val DBGPRN = true
private fun printdbg(msg: Any) {
if (DBGPRN) println("[TestDiskDrive] $msg")
}
fun composePositiveAns(vararg msg: String): ByteArray { fun composePositiveAns(vararg msg: String): ByteArray {
val sb = ArrayList<Byte>() val sb = ArrayList<Byte>()
sb.addAll(msg[0].toByteArray().toTypedArray()) sb.addAll(msg[0].toByteArray().toTypedArray())
@@ -126,7 +132,7 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
val inputString = inputData.trimNull().toString(VM.CHARSET) val inputString = inputData.trimNull().toString(VM.CHARSET)
if (inputString.startsWith("DEVRST\u0017")) { if (inputString.startsWith("DEVRST\u0017")) {
println("[TestDiskDrive] Device Reset") printdbg("Device Reset")
//readModeLength = -1 //readModeLength = -1
fileOpen = false fileOpen = false
fileOpenMode = -1 fileOpenMode = -1
@@ -144,14 +150,15 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
recipient?.writeout(composePositiveAns("Testtec Virtual Disk Drive")) recipient?.writeout(composePositiveAns("Testtec Virtual Disk Drive"))
else if (inputString.startsWith("OPENR\"") || inputString.startsWith("OPENW\"") || inputString.startsWith("OPENA\"")) { else if (inputString.startsWith("OPENR\"") || inputString.startsWith("OPENW\"") || inputString.startsWith("OPENA\"")) {
if (fileOpen) { if (fileOpen) {
statusCode = STATE_CODE_FILE_ALREADY_OPENED statusCode = STATE_CODE_FILE_ALREADY_OPENED
return return
} }
println("[TestDiskDrive] msg: $inputString, lastIndex: ${inputString.lastIndex}") printdbg("msg: $inputString, lastIndex: ${inputString.lastIndex}")
val openMode = inputString[4] val openMode = inputString[4]
println("[TestDiskDrive] open mode: $openMode") printdbg("open mode: $openMode")
// split inputstring into path and optional drive-number // split inputstring into path and optional drive-number
// get position of latest delimeter (comma) // get position of latest delimeter (comma)
@@ -172,10 +179,10 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
// TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it // TODO driveNum is for disk drives that may have two or more slots built; for testing purposes we'll ignore it
file = File(rootPath, filePath) file = File(rootPath, filePath)
println("[TestDiskDrive] file path: ${file.canonicalPath}, drive num: $driveNum") printdbg("file path: ${file.canonicalPath}, drive num: $driveNum")
if (openMode == 'R' && !file.exists()) { if (openMode == 'R' && !file.exists()) {
println("! file not found") printdbg("! file not found")
statusCode = STATE_CODE_FILE_NOT_FOUND statusCode = STATE_CODE_FILE_NOT_FOUND
return return
} }
@@ -314,7 +321,7 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
val paths = path.split('/') val paths = path.split('/')
val newPaths = ArrayList<String>() val newPaths = ArrayList<String>()
paths.forEach { paths.forEach {
if (it.isBlank() || it.isEmpty()) throw IllegalArgumentException("Path cannot contain whitespaces") if (it.isBlank() || it.isEmpty()) throw IllegalArgumentException("Path cannot contain whitespaces: $paths")
if (it == "..") { if (it == "..") {
parentCount -= -1 parentCount -= -1