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 = {
path: [
"/tvdos/bin"
"\\tvdos\\bin\\"
]
};
Object.freeze(_TVDOS);
@@ -31,8 +31,11 @@ filesystem._close = function(portNo) {
filesystem._flush = function(portNo) {
com.sendMessage(portNo, "FLUSH");
};
// @return true if operation committed successfully, false otherwise; throws error
// if unknown mode or invalid drive letter was given
// @return true if operation committed successfully, false if:
// - 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) {
let port = filesystem._toPorts(driveLetter);
@@ -67,7 +70,8 @@ filesystem.open("A", "tvdos/gl.js", "R");
var GL = eval(filesystem.readAll("A"));
// @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) {
let prg = eval("let _appStub=function(exec_args){"+cmdsrc+"};_appStub;"); // making 'exec_args' a app-level global
return prg(args);
@@ -78,8 +82,4 @@ var execApp = function(cmdsrc, args) {
// Boot script
filesystem.open("A", "tvdos/command.js", "R");
let cmdsrc = filesystem.readAll("A");
// app execution stub
execApp(cmdsrc);
//let sh = execApp(cmdsrc, [42]);
//println(sh.test);
execApp(cmdsrc, ["", "/c", "\\AUTOEXEC.BAT"]);

View File

@@ -6,25 +6,11 @@ let shell_pwd = [];
const welcome_text = "TSVM Disk Operating System, version " + _TVDOS.VERSION;
function print_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);
print(CURRENT_DRIVE + ":\\" + shell_pwd.join("\\") + PROMPT_TEXT);
}
function greet() {
con.color_pair(0,253);
//print(welcome_text + " ".repeat(_fsh.scrwidth - welcome_text.length));
print(welcome_text + " ".repeat(80 - welcome_text.length));
con.color_pair(239,255);
println();
println(welcome_text);
}
@@ -129,77 +115,116 @@ Object.freeze(shell.coreutils);
shell.execute = function(line) {
if (line.size == 0) return;
let tokens = shell.parse(line);
let cmd = tokens[0].toLowerCase();
if (shell.coreutils[cmd] !== undefined) {
shell.coreutils[cmd](tokens);
let cmd = tokens[0];
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 {
printerrln('Bad command or filename: "'+cmd+'"');
// 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+'"');
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
let cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
let cmdExit = false;
while (!cmdExit) {
print_prompt_text();
greet();
let cmdbuf = "";
let cmdHistory = []; // zeroth element is the oldest
let cmdHistoryScroll = 0; // 0 for outside-of-buffer, 1 for most recent
let cmdExit = false;
while (!cmdExit) {
print_prompt_text();
while (true) {
let key = con.getch();
let cmdbuf = "";
// printable chars
if (key >= 32 && key <= 126) {
let s = String.fromCharCode(key);
cmdbuf += s;
print(s);
}
// backspace
else if (key === 8 && cmdbuf.length > 0) {
cmdbuf = cmdbuf.substring(0, cmdbuf.length - 1);
print(String.fromCharCode(key));
}
// enter
else if (key === 10 || key === 13) {
println();
try {
shell.execute(cmdbuf);
while (true) {
let key = con.getch();
// printable chars
if (key >= 32 && key <= 126) {
let s = String.fromCharCode(key);
cmdbuf += s;
print(s);
}
catch (e) {
printerrln(e);
// backspace
else if (key === 8 && cmdbuf.length > 0) {
cmdbuf = cmdbuf.substring(0, cmdbuf.length - 1);
print(String.fromCharCode(key));
}
finally {
if (cmdbuf.trim().length > 0)
cmdHistory.push(cmdbuf);
// enter
else if (key === 10 || key === 13) {
println();
try {
shell.execute(cmdbuf);
}
catch (e) {
printerrln(e);
}
finally {
if (cmdbuf.trim().length > 0)
cmdHistory.push(cmdbuf);
cmdHistoryScroll = 0;
break;
cmdHistoryScroll = 0;
break;
}
}
}
// up arrow
else if (key === 19 && cmdHistory.length > 0 && cmdHistoryScroll < cmdHistory.length) {
cmdHistoryScroll += 1;
// up arrow
else if (key === 19 && cmdHistory.length > 0 && cmdHistoryScroll < cmdHistory.length) {
cmdHistoryScroll += 1;
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command
print(cmdbuf);
}
// down arrow
else if (key === 20) {
if (cmdHistoryScroll > 0) {
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
@@ -207,13 +232,25 @@ while (!cmdExit) {
// re-type the new command
print(cmdbuf);
cmdHistoryScroll -= 1;
}
else {
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = "";
// down arrow
else if (key === 20) {
if (cmdHistoryScroll > 0) {
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = cmdHistory[cmdHistory.length - cmdHistoryScroll];
// re-type the new command
print(cmdbuf);
cmdHistoryScroll -= 1;
}
else {
// back the cursor in order to type new cmd
let x = 0;
for (x = 0; x < cmdbuf.length; x++) print(String.fromCharCode(8));
cmdbuf = "";
}
}
}
}

View File

@@ -31,7 +31,13 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
}
}
fun composePositiveAns(vararg msg: String): ByteArray {
private val DBGPRN = true
private fun printdbg(msg: Any) {
if (DBGPRN) println("[TestDiskDrive] $msg")
}
fun composePositiveAns(vararg msg: String): ByteArray {
val sb = ArrayList<Byte>()
sb.addAll(msg[0].toByteArray().toTypedArray())
for (k in 1 until msg.size) {
@@ -126,7 +132,7 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
val inputString = inputData.trimNull().toString(VM.CHARSET)
if (inputString.startsWith("DEVRST\u0017")) {
println("[TestDiskDrive] Device Reset")
printdbg("Device Reset")
//readModeLength = -1
fileOpen = false
fileOpenMode = -1
@@ -144,14 +150,15 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
recipient?.writeout(composePositiveAns("Testtec Virtual Disk Drive"))
else if (inputString.startsWith("OPENR\"") || inputString.startsWith("OPENW\"") || inputString.startsWith("OPENA\"")) {
if (fileOpen) {
statusCode = STATE_CODE_FILE_ALREADY_OPENED
return
}
println("[TestDiskDrive] msg: $inputString, lastIndex: ${inputString.lastIndex}")
printdbg("msg: $inputString, lastIndex: ${inputString.lastIndex}")
val openMode = inputString[4]
println("[TestDiskDrive] open mode: $openMode")
printdbg("open mode: $openMode")
// split inputstring into path and optional drive-number
// 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
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()) {
println("! file not found")
printdbg("! file not found")
statusCode = STATE_CODE_FILE_NOT_FOUND
return
}
@@ -314,7 +321,7 @@ class TestDiskDrive(private val driveNum: Int, theRootPath: File? = null) : Bloc
val paths = path.split('/')
val newPaths = ArrayList<String>()
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 == "..") {
parentCount -= -1