Files
ViperOS/Apps/Terminal/main.vp
T
TermiNexus 5e1cd04478 feat(s4): 删除 SERIAL_PUTS 私有 syscall,用户态改走 /dev/serial0
内核:删掉 SERIAL_PUTS 的枚举项/派发分支/处理函数(内核自身的 serial.puts 是直接驱动调用,不受影响)。SDK:vpsdk/devfs.vp 新增 serial_puts()(惰性 open /dev/serial0 一次 + write),syscall.vp 删掉该成员。

调用点全部切到 devfs.serial_puts:vpsdk/stdio.vp 的 printf、vpsdk/vpui.vp 的 _serial_puts、Apps/Terminal 的 _sdbg、Apps/Explorer 的 _dbg、Libs/SerialLogger 的 log_info/log_warn(.so 同样走设备节点)。顺带清掉因此失效的 import(vpui 的 _syscall、Terminal 的 _syscall、Explorer 的 syscall)。

至此私有段只剩 7 项:TELL/SIZE/OPENDIR/READDIR/CLOSEDIR(可由 lseek/fstat/openat+getdents64 表达)与 LOAD_SO/SO_CALL1(动态库加载待下沉用户层)。
2026-10-16 19:17:39 +08:00

329 lines
11 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import vpsdk.vpui as vpui
import vpsdk.window as window
import vpsdk.process as process
import vpsdk.fs as fs
import vpsdk.devfs as devfs
import vpsdk.stdlib as stdlib
import vpsdk.stdio as stdio
import string
import viperlib
from stdint import *
import t, c
@__attribute__(section(".text.startup"), aligned(16))
export def _start() -> int:
root: vpui.Tk = vpui.Tk()
root.title("Terminal")
root.set_style(window.STYLE_WIN7)
root.geometry(80, 30, 640, 480)
root.bg_color = uint32(0x0C0C0C)
master: vpui.Tk* = &root
def _sdbg(msg: str):
# S4:改走 /dev/serial0(SERIAL_PUTS 私有 syscall 已删除)
devfs.serial_puts(msg)
_sdbg("[term] start\n")
_cwd: [64]char
_cwd[0] = 47
for i in range(1, 64):
_cwd[i] = 0
sbar: vpui.Scrollbar = vpui.Scrollbar(master, 16, 446, vpui.VERTICAL)
root.pack(0, vpui.PACK_RIGHT, vpui.FILL_Y, 0, 0, 0)
term: vpui.Text = vpui.Text(master, 624, 446)
root.pack(1, vpui.PACK_LEFT, vpui.FILL_BOTH, 1, 0, 0)
term.insert("ViperOS Terminal v1.1")
term.insert("Type 'help' for commands.")
term.insert("")
term.yscrollbar = vpui.Widget*(sbar)
def _on_scroll():
act: int = sbar.action
if act == 1:
term.scroll_offset -= 1
elif act == 2:
term.scroll_offset += 1
elif act == 3:
vis: int = term._visible_lines()
term.scroll_offset -= vis
elif act == 4:
vis2: int = term._visible_lines()
term.scroll_offset += vis2
elif act == 5:
aval: int = sbar.action_value
if term.line_count > 0:
term.scroll_offset = aval * term.line_count / 1000
vis3: int = term._visible_lines()
max_off: int = term.line_count - vis3
if max_off < 0: max_off = 0
if term.scroll_offset < 0: term.scroll_offset = 0
if term.scroll_offset > max_off: term.scroll_offset = max_off
term._update_scrollbar()
sbar.command = _on_scroll
def _startswith(s: str, prefix: str) -> int:
plen: sizet = string.strlen(prefix)
if string.strncmp(s, prefix, plen) == 0:
return 1
return 0
def _build_path(out: str, out_size: int, rel: str):
if *rel == 47:
string.strncpy(out, rel, out_size - 1)
else:
i: int = 0
for i in range(63):
ch: char = _cwd[i]
*(out + i) = ch
if ch == 0: break
cwd_len: int = i
if cwd_len > 0 and _cwd[cwd_len - 1] != 47:
*(out + cwd_len) = char(47)
cwd_len += 1
j: int = 0
for j in range(out_size - 1 - cwd_len):
ch2: char = *(rel + j)
*(out + cwd_len + j) = ch2
if ch2 == 0: break
*(out + out_size - 1) = char(0)
def _print_dir_entry(name: str, is_dir: int):
buf: [80]char
j: int = 0
for j in range(78):
ch: char = *(name + j)
buf[j] = ch
if ch == 0: break
if is_dir and j < 78:
buf[j] = 47
j += 1
buf[j] = 0
term.insert_ptr(&buf[0])
def _cmd_cd(path: str):
if path is None or *path == 0:
_cwd[0] = 47
for i in range(1, 64):
_cwd[i] = 0
return
full: [256]char
_build_path(&full[0], 256, path)
dd: int = fs.opendir(&full[0])
if dd < 0:
term.insert("Error: dir not found")
return
fs.closedir(dd)
string.strncpy(&_cwd[0], &full[0], 63)
_cwd[63] = 0
def _cmd_ls():
dd: int = fs.opendir(&_cwd[0])
if dd < 0:
term.insert("Error: cannot open dir")
return
info: [320]char
string.memset(&info[0], 0, 320)
while True:
result: int = fs.readdir(dd, &info[0])
if result != 0: break
attr_val: uint8 = uint8(*(&info[4]))
name_off: int = 16
name_ptr: str = &info[name_off]
if *name_ptr == 0: break
if *name_ptr == 46:
if *(name_ptr + 1) == 0:
string.memset(&info[0], 0, 320)
continue
if *(name_ptr + 1) == 46 and *(name_ptr + 2) == 0:
string.memset(&info[0], 0, 320)
continue
if (attr_val & 0x10) != 0:
_print_dir_entry(name_ptr, 1)
else:
_print_dir_entry(name_ptr, 0)
string.memset(&info[0], 0, 320)
fs.closedir(dd)
def _cmd_cat(path: str):
full: [256]char
_build_path(&full[0], 256, path)
fd: int = fs.open(&full[0], fs.O_RDONLY)
if fd < 0:
term.insert("Error: file not found")
return
buf: [80]char
while True:
string.memset(&buf[0], 0, 80)
n: int = fs.read(fd, &buf[0], 78)
if n <= 0: break
if n > 78: n = 78
buf[n] = 0
term.insert_ptr(&buf[0])
fs.close(fd)
def _cmd_mkdir(path: str):
full: [256]char
_build_path(&full[0], 256, path)
result: int = fs.mkdir(&full[0])
if result < 0:
term.insert("Error: mkdir failed")
else:
term.insert("Directory created")
def _cmd_rm(path: str):
full: [256]char
_build_path(&full[0], 256, path)
result: int = fs.remove(&full[0])
if result < 0:
term.insert("Error: remove failed")
else:
term.insert("Removed")
def _cmd_touch(path: str):
full: [256]char
_build_path(&full[0], 256, path)
fd: int = fs.open(&full[0], fs.O_WRONLY | fs.O_CREAT)
if fd < 0:
term.insert("Error: touch failed")
return
fs.close(fd)
term.insert("File created")
def _cmd_sysinfo():
term.insert("ViperOS v1.0 (x86_64)")
term.insert("Framebuffer: 32bpp")
term.insert("Compiler: TransPyC")
def _cmd_hexdump(path: str):
full: [256]char
_build_path(&full[0], 256, path)
fd: int = fs.open(&full[0], fs.O_RDONLY)
if fd < 0:
term.insert("Error: file not found")
return
offset: int = 0
buf: [16]char
while True:
string.memset(&buf[0], 0, 16)
n: int = fs.read(fd, &buf[0], 16)
if n <= 0: break
if n > 16: n = 16
line: [80]char
string.memset(&line[0], 0, 80)
viperlib.snprintf(&line[0], 80, "%08x: ", offset)
pos: int = 10
j: int = 0
for j in range(16):
if j < n:
ub: uint32 = uint32(buf[j]) & 0xFF
hi: int = int(ub >> 4)
lo: int = int(ub & 0xF)
if hi < 10:
line[pos] = char(48 + hi)
else:
line[pos] = char(65 + hi - 10)
pos += 1
if lo < 10:
line[pos] = char(48 + lo)
else:
line[pos] = char(65 + lo - 10)
pos += 1
else:
line[pos] = 32
pos += 1
line[pos] = 32
pos += 1
line[pos] = 32
pos += 1
if j == 7:
line[pos] = 32
pos += 1
line[pos] = 124
pos += 1
for j in range(n):
b2: uint32 = uint32(buf[j]) & 0xFF
if b2 >= 32 and b2 < 127:
line[pos] = char(b2)
else:
line[pos] = 46
pos += 1
line[pos] = 0
term.insert_ptr(&line[0])
offset += n
fs.close(fd)
def _cmd_run(path: str, blocking: int):
full: [256]char
_build_path(&full[0], 256, path)
pid: int = process.spawn(&full[0], blocking)
if pid < 0:
term.insert("Error: cannot spawn")
elif blocking:
term.insert("Process exited")
else:
msg: [32]char
viperlib.snprintf(&msg[0], 32, "Spawned pid=%d", pid)
term.insert_ptr(&msg[0])
def _on_command() -> int:
_sdbg("[cmd] enter\n")
text: str = term.get()
_sdbg("[cmd] text=")
_sdbg(text)
_sdbg("\n")
if _startswith(text, "echo "):
term.insert_ptr(text + 5)
elif string.samestr(text, "echo"):
pass
elif string.samestr(text, "clear"):
term.delete(0, -1)
elif string.samestr(text, "help"):
term.insert("File: ls cd cat pwd mkdir rm touch")
term.insert("Sys: ver about sysinfo reboot")
term.insert("Util: echo clear help hexdump run runb")
elif string.samestr(text, "ver"):
term.insert("ViperOS Terminal v1.1")
elif string.samestr(text, "about"):
term.insert("ViperOS - A tiny OS in Viper lang")
elif string.samestr(text, "pwd"):
term.insert_ptr(&_cwd[0])
elif string.samestr(text, "ls"):
_cmd_ls()
elif string.samestr(text, "cd"):
_cmd_cd("")
elif _startswith(text, "cd "):
_cmd_cd(text + 3)
elif _startswith(text, "cat "):
_cmd_cat(text + 4)
elif _startswith(text, "mkdir "):
_cmd_mkdir(text + 6)
elif _startswith(text, "rm "):
_cmd_rm(text + 3)
elif _startswith(text, "touch "):
_cmd_touch(text + 6)
elif string.samestr(text, "sysinfo"):
_cmd_sysinfo()
elif string.samestr(text, "reboot"):
process.exit(0)
elif _startswith(text, "hexdump "):
_cmd_hexdump(text + 8)
elif _startswith(text, "run "):
_cmd_run(text + 4, 0)
elif _startswith(text, "runb "):
_cmd_run(text + 5, 1)
else:
if text is not None and *text != 0:
term.insert("Unknown command. Type 'help'.")
return 0
term.on_command = _on_command
root.mainloop()
process.exit(0)
return 0