summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rwxr-xr-xCopyToFDD.sh14
-rwxr-xr-xCopyToHDD.sh2
-rw-r--r--Makefile15
-rw-r--r--Media/Screenshots/2009-12-20-193041_1032x794_scrot.pngbin0 -> 39390 bytes
-rwxr-xr-xMount/boot/menu.cfg27
-rwxr-xr-xMount/boot/stage1bin0 -> 512 bytes
-rwxr-xr-xMount/boot/stage2bin0 -> 99882 bytes
-rw-r--r--Source/Applications/Demos/GOL.cpp7
-rw-r--r--Source/Applications/PaperWork/Makefile2
-rw-r--r--Source/Applications/PaperWork/PaperWork.cpp13
-rwxr-xr-xSource/Applications/Shell/Applets/rot13bin0 -> 73404 bytes
-rw-r--r--Source/Applications/Shell/Applets/rot13.cpp30
-rw-r--r--Source/Applications/Shell/Makefile8
-rw-r--r--Source/Applications/Shell/Shell-fs.class.cpp4
-rw-r--r--Source/Applications/Shell/Shell.class.cpp5
-rw-r--r--Source/Applications/Shell/main.cpp5
-rw-r--r--Source/Kernel/Core/Sys.ns.cpp4
-rw-r--r--Source/Kernel/Core/Sys.ns.h2
-rw-r--r--Source/Kernel/TaskManager/Thread.class.cpp6
-rw-r--r--Source/Kernel/VFS/FSNode-sc.proto.cpp1
-rw-r--r--Source/Kernel/VTManager/FileVT.class.cpp2
-rw-r--r--Source/Kernel/VTManager/VirtualTerminal-kbd.proto.cpp3
-rw-r--r--Source/Library/Common/FileStream.class.cpp71
-rw-r--r--Source/Library/Common/FileStream.class.h43
-rw-r--r--Source/Library/Common/IStream.proto.cpp81
-rw-r--r--Source/Library/Common/IStream.proto.h32
-rw-r--r--Source/Library/Common/OStream.proto.cpp65
-rw-r--r--Source/Library/Common/OStream.proto.h39
-rw-r--r--Source/Library/Common/SimpleList.class.h13
-rw-r--r--Source/Library/Common/StringStream.class.cpp28
-rw-r--r--Source/Library/Common/StringStream.class.h35
-rw-r--r--Source/Library/Common/WChar.class.h2
-rw-r--r--Source/Library/Makefile5
-rw-r--r--Source/Library/Userland/App/ShellApp.proto.cpp34
-rw-r--r--Source/Library/Userland/App/ShellApp.proto.h3
-rw-r--r--Source/Library/Userland/App/StreamApp.proto.cpp40
-rw-r--r--Source/Library/Userland/App/StreamApp.proto.h27
-rw-r--r--Source/Library/Userland/Binding/Process.class.h4
-rw-r--r--Source/Library/Userland/Binding/VirtualTerminal.class.h32
-rw-r--r--Source/Library/Userland/Syscall/RessourceCaller.class.h4
41 files changed, 648 insertions, 67 deletions
diff --git a/.gitignore b/.gitignore
index 254c5a7..d9255a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,11 +2,12 @@
*.o
*.uo
Init.rfs
-Source/Kernel/Map.txt
+Map.txt
+Source/Applications/Shell/Applets/*.map
Source/Kernel/Melon.ke
Ports
Ports/*
-Cross
-Cross/*
Unix
Unix/*
+Cross
+Cross/*
diff --git a/CopyToFDD.sh b/CopyToFDD.sh
index 7b8459a..936be0a 100755
--- a/CopyToFDD.sh
+++ b/CopyToFDD.sh
@@ -5,8 +5,15 @@
# Update GRUB's menu.cfg
cp Grub-menu-fdd.cfg Mount/boot/menu.cfg
+# Cleanup old stuff
+cd Mount
+for a in `ls`; do
+ if [ $a != boot ]; then rm -rf $a; fi
+done
+cd ..
+
# Create directories
-mkdir Mount/{System,Applications,Volumes}
+mkdir Mount/{System,Applications,Volumes,Sandbox}
mkdir Mount/Applications/{Shell,Demos}
mkdir Mount/System/{Applications,Logs,Configuration}
mkdir Mount/Volumes/{HDD,InitRFS}
@@ -17,11 +24,14 @@ cp Init.rfs Mount/System
# Copy system files
cp Source/Kernel/Ressources/Configuration/* Mount/System/Configuration
+
+# Copy system apps
cp Source/Applications/PaperWork/PaperWork Mount/System/Applications/PaperWork.app
cp Source/Applications/Shell/Shell Mount/Applications/Shell/Shell.app
+cp Source/Applications/Shell/Help.txt Mount/Applications/Shell/Help.txt
# Create mount configuration file
-echo "/Volumes/InitRFS:ramfs:0" > Mount/System/Configuration/Mount
+echo "/Sandbox:ramfs:0" > Mount/System/Configuration/Mount
echo "/Volumes/HDD:block.ata:0:1" >> Mount/System/Configuration/Mount
# Copy demo apps
diff --git a/CopyToHDD.sh b/CopyToHDD.sh
index d901b1b..7a0890e 100755
--- a/CopyToHDD.sh
+++ b/CopyToHDD.sh
@@ -9,6 +9,7 @@ cp Grub-menu-hdd.cfg Mount/grub/menu.lst
mkdir Mount/{System,Applications,Volumes}
mkdir Mount/System/{Applications,Configuration,Logs,Keymaps}
mkdir Mount/Applications/{Demos,Shell}
+mkdir Mount/Applications/Shell/Applets
mkdir Mount/Volumes/{Floppy,InitRFS}
# Copy welcome text
@@ -23,6 +24,7 @@ cp Source/Kernel/Ressources/Configuration/* Mount/System/Configuration
cp Source/Kernel/Ressources/Keymaps/*.mkm Mount/System/Keymaps
cp Source/Applications/PaperWork/PaperWork Mount/System/Applications/PaperWork.app
cp Source/Applications/Shell/Shell Mount/Applications/Shell/Shell.app
+cp Source/Applications/Shell/Applets/rot13 Mount/Applications/Shell/Applets
cp Source/Applications/Shell/Help.txt Mount/Applications/Shell
# Create mount configuration file
diff --git a/Makefile b/Makefile
index 58bdf13..e9e6a77 100644
--- a/Makefile
+++ b/Makefile
@@ -4,20 +4,15 @@ Projects = Kernel Library Tools/MakeRamFS Applications/Shell Applications/PaperW
Kernel = Source/Kernel/Melon.ke
RamFS = Init.rfs
-RamFSFiles = :/System :/System/Applications :/System/Configuration :/System/Keymaps \
- :/Applications :/Applications/Demos :/Applications/Shell :/Mount \
+RamFSFiles = :/System :/System/Configuration :/System/Keymaps \
Source/Kernel/Ressources/Configuration/Users:/System/Configuration/Users \
Source/Kernel/Ressources/Configuration/Groups:/System/Configuration/Groups \
Source/Kernel/Ressources/Keymaps/fr.mkm:/System/Keymaps/fr.mkm \
Source/Kernel/Ressources/Texts/Welcome.txt:/Welcome.txt \
- Source/Applications/Demos/asmdemo:/Applications/Demos/ASMDemo.app \
- Source/Applications/Demos/cxxdemo:/Applications/Demos/CPPDemo.app \
- Source/Applications/Demos/GOL:/Applications/Demos/GOL.app \
- Source/Applications/Shell/Shell:/Applications/Shell/Shell.app \
- Source/Applications/Shell/Help.txt:/Applications/Shell/Help.txt \
- Source/Applications/PaperWork/PaperWork:/System/Applications/PaperWork.app \
- :/Useless \
- Source/Kernel/Ressources/Graphics/logo.text.cxd:/Useless/Melon-logo
+ Source/Applications/Shell/Shell:/Shell.app \
+ Source/Applications/Shell/Help.txt:/Shell-Help.txt \
+ Source/Applications/Shell/Applets/rot13:/rot13 \
+ Source/Kernel/Ressources/Graphics/logo.text.cxd:/Melon-logo
Files = $(Kernel) $(RamFS)
Floppy = Melon.img
diff --git a/Media/Screenshots/2009-12-20-193041_1032x794_scrot.png b/Media/Screenshots/2009-12-20-193041_1032x794_scrot.png
new file mode 100644
index 0000000..069ba9e
--- /dev/null
+++ b/Media/Screenshots/2009-12-20-193041_1032x794_scrot.png
Binary files differ
diff --git a/Mount/boot/menu.cfg b/Mount/boot/menu.cfg
new file mode 100755
index 0000000..37bcfb0
--- /dev/null
+++ b/Mount/boot/menu.cfg
@@ -0,0 +1,27 @@
+default 2
+
+title The Melon Operating System
+root (fd0)
+kernel /System/Melon.ke root:block.floppy:0:0
+module /System/Init.rfs
+
+title Melon without VESA
+root (fd0)
+kernel /System/Melon.ke vesa:disabled root:block.floppy:0:0
+module /System/Init.rfs
+
+title Melon without init
+root (fd0)
+kernel /System/Melon.ke init: root:block.floppy:0:0
+module /System/Init.rfs
+
+title Melon without init, boot on initramfs
+root (fd0)
+kernel /System/Melon.ke init: root:ramfs:0
+module /System/Init.rfs
+
+title Game of life simulator
+root (fd0)
+kernel /System/Melon.ke init:/Applications/Demos/GOL.app root:block.floppy:0:0
+module /System/Init.rfs
+
diff --git a/Mount/boot/stage1 b/Mount/boot/stage1
new file mode 100755
index 0000000..c10df80
--- /dev/null
+++ b/Mount/boot/stage1
Binary files differ
diff --git a/Mount/boot/stage2 b/Mount/boot/stage2
new file mode 100755
index 0000000..8b578cf
--- /dev/null
+++ b/Mount/boot/stage2
Binary files differ
diff --git a/Source/Applications/Demos/GOL.cpp b/Source/Applications/Demos/GOL.cpp
index 675c159..ba9cb1c 100644
--- a/Source/Applications/Demos/GOL.cpp
+++ b/Source/Applications/Demos/GOL.cpp
@@ -46,7 +46,8 @@ int GOL::run() {
}
}
outvt.moveCursor(0, 0);
- outvt << tmp.toString() << "Press Ctrl+h for help";
+ outvt.write(tmp.toString()); //BYPASS buffering
+ outvt<< "Press Ctrl+h for help" << FLUSH;
//Compute next generation
for (int y = 0; y < h; y++) {
@@ -92,7 +93,7 @@ int GOL::run() {
cells[x * h + y] = true;
}
} else if (kp.character == WChar("p")) {
- outvt << " [PAUSED] press a key to resume";
+ outvt << " [PAUSED] press a key to resume" << FLUSH;
invt.getKeypress();
} else if (kp.character == WChar("h")) {
outvt << "\n\n** Melon's demo Game Of Life Simulator help :\n";
@@ -101,7 +102,7 @@ int GOL::run() {
outvt << " - ctrl+p : pause\n";
outvt << " - ctrl+r : add some random cells\n";
outvt << " - ctrl+R : add more cells, still random\n\n";
- outvt << "Press any key to return to simultaor...";
+ outvt << "Press any key to return to simultaor..." << FLUSH;
invt.getKeypress();
}
kp = invt.getKeypress(false, false);
diff --git a/Source/Applications/PaperWork/Makefile b/Source/Applications/PaperWork/Makefile
index d3203cf..8d079ec 100644
--- a/Source/Applications/PaperWork/Makefile
+++ b/Source/Applications/PaperWork/Makefile
@@ -4,7 +4,7 @@ CXX = g++
CXXFLAGS = -nostartfiles -nostdlib -ffreestanding -fno-exceptions -fno-rtti -I ../../Library/Common -I ../../Library/Interface -I ../../Library/Userland -D THIS_IS_MELON_USERLAND
LD = ld
-LDFLAGS = -T ../../Library/Link.ld -L ../../Library
+LDFLAGS = -T ../../Library/Link.ld -L ../../Library -Map Map.txt
Objects = PaperWork.o
OutFile = PaperWork
diff --git a/Source/Applications/PaperWork/PaperWork.cpp b/Source/Applications/PaperWork/PaperWork.cpp
index 4f9cb0e..15497e4 100644
--- a/Source/Applications/PaperWork/PaperWork.cpp
+++ b/Source/Applications/PaperWork/PaperWork.cpp
@@ -1,6 +1,7 @@
#include <App/ShellApp.proto.h>
#define DEFAULT_SHELL "/Applications/Shell/Shell.app"
+#define PAPERWORK_PATH "/System/Applications/PaperWork.app"
class PaperWork : public ShellApp {
public:
@@ -20,7 +21,7 @@ int PaperWork::run() {
if (act == "init") {
while (1) {
- Process p = Process::run("/System/Applications/PaperWork.app");
+ Process p = Process::run(PAPERWORK_PATH);
if (p.valid()) {
p.setInVT(invt);
p.setOutVT(outvt);
@@ -35,16 +36,16 @@ int PaperWork::run() {
outvt << "Logging in to Melon\n";
String user, pw;
while (1) {
- outvt << "Username: ";
- user = invt.readLine();
- outvt << "Password: ";
+ outvt << "Username: " << FLUSH;
+ user = invt.get();
+ outvt << "Password: " << FLUSH;
pw = invt.readLine(false);
if (!Process::get().authenticatePW(user, pw)) {
outvt << "Authentication failed.\n\n";
continue;
}
- outvt << "What shell to run [" << sFlag("shell") << "]? ";
- String sh = invt.readLine();
+ outvt << "What shell to run [" << sFlag("shell") << "]? "<< FLUSH;
+ String sh = invt.get();
if (sh == "") sh = sFlag("shell");
Process p = Process::run(sh);
if (p.valid()) {
diff --git a/Source/Applications/Shell/Applets/rot13 b/Source/Applications/Shell/Applets/rot13
new file mode 100755
index 0000000..0399a6f
--- /dev/null
+++ b/Source/Applications/Shell/Applets/rot13
Binary files differ
diff --git a/Source/Applications/Shell/Applets/rot13.cpp b/Source/Applications/Shell/Applets/rot13.cpp
new file mode 100644
index 0000000..e5638b8
--- /dev/null
+++ b/Source/Applications/Shell/Applets/rot13.cpp
@@ -0,0 +1,30 @@
+#include <App/StreamApp.proto.h>
+
+class rot13 : public StreamApp {
+ public:
+ rot13() : StreamApp("rot13", "Cat a file, but ROT13 it") {}
+ int run();
+};
+
+APP(rot13);
+
+int rot13::run() {
+ while (!in->eof()) {
+ String s = in->get();
+ if (in->eof() && s.empty()) break;
+ for (u32int i = 0; i < s.size(); i++) {
+ WChar &c = s[i];
+ if (c >= WChar('A') and c <= WChar('Z')) {
+ c += 13;
+ if (c > WChar('Z')) c -= 26;
+ }
+ if (c >= WChar('a') and c <= WChar('z')) {
+ c += 13;
+ if (c > WChar('z')) c -= 26;
+ }
+ }
+ *out << s << ENDL;
+ }
+ return 0;
+}
+
diff --git a/Source/Applications/Shell/Makefile b/Source/Applications/Shell/Makefile
index d546a15..e972dfb 100644
--- a/Source/Applications/Shell/Makefile
+++ b/Source/Applications/Shell/Makefile
@@ -10,7 +10,9 @@ Objects = Shell.class.o \
Shell-fs.class.o
OutFile = Shell
-all: $(OutFile)
+Applets = Applets/rot13
+
+all: $(OutFile) $(Applets)
echo "* Done with $(OutFile)."
rebuild: mrproper all
@@ -19,6 +21,10 @@ $(OutFile): $(Objects)
echo "* Linking $@..."
$(LD) $(LDFLAGS) $^ -o $@
+Applets/%: Applets/%.o
+ echo "* Linking $@..."
+ $(LD) $(LDFLAGS) $^ -o $@ -Map $@.map
+
%.o: %.cpp
echo "* Compiling $<..."
$(CXX) $(CXXFLAGS) -c $< -o $@
diff --git a/Source/Applications/Shell/Shell-fs.class.cpp b/Source/Applications/Shell/Shell-fs.class.cpp
index 150b877..30faaf7 100644
--- a/Source/Applications/Shell/Shell-fs.class.cpp
+++ b/Source/Applications/Shell/Shell-fs.class.cpp
@@ -28,11 +28,11 @@ void Shell::ls(Vector<String>& args) {
if (((p >> i) & 1) == 0) perm[8 - i] = "-";
}
if (n.type() == NT_FILE) {
- outvt << " FILE " << perm << " " << n.getName();
+ outvt << " FILE " << perm << " " << n.getName() << FLUSH;
outvt.setCsrCol(30);
outvt << (s32int)n.getLength() << " bytes.\n";
} else if (n.type() == NT_DIRECTORY) {
- outvt << " DIR " << perm << " " << n.getName() << "/";
+ outvt << " DIR " << perm << " " << n.getName() << "/" << FLUSH;
outvt.setCsrCol(30);
outvt << (s32int)n.getLength() << " items.\n";
}
diff --git a/Source/Applications/Shell/Shell.class.cpp b/Source/Applications/Shell/Shell.class.cpp
index 3d406c8..4283b30 100644
--- a/Source/Applications/Shell/Shell.class.cpp
+++ b/Source/Applications/Shell/Shell.class.cpp
@@ -25,8 +25,9 @@ int Shell::run() {
cwd = FS::cwdNode();
while (1) {
- outvt << "{" << cwd.getName() << "}: ";
- String s = invt.readLine();
+ outvt << "{" << cwd.getName() << "}: " << FLUSH;
+ String s = invt.get();
+ if (s.contains(EOF)) return 0;
if (s.empty()) continue;
while (s[0] == WChar(" ") or s[0] == WChar("\t")) {
s = s.substr(1, s.size() - 1);
diff --git a/Source/Applications/Shell/main.cpp b/Source/Applications/Shell/main.cpp
deleted file mode 100644
index 66c4269..0000000
--- a/Source/Applications/Shell/main.cpp
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "Shell.ns.h"
-
-int main(const Vector<String>& args) {
- return Shell::run();
-}
diff --git a/Source/Kernel/Core/Sys.ns.cpp b/Source/Kernel/Core/Sys.ns.cpp
index c5af3e8..59da244 100644
--- a/Source/Kernel/Core/Sys.ns.cpp
+++ b/Source/Kernel/Core/Sys.ns.cpp
@@ -85,9 +85,9 @@ void dumpRegs(registers_t *regs, VirtualTerminal& vt) {
vt << "eflags=" << (u32int)regs->eflags << ", useresp=" << (u32int)regs->useresp << ", ss=" << (u32int)regs->ss << "\n";
}
-void stackTrace(u32int ebp, VirtualTerminal& vt, u32int maxframes) {
+void stackTrace(u32int ebp, VirtualTerminal& vt, u32int maxframes, bool isUser) {
u32int *stack = (u32int*)ebp;
- for (u32int i = 0; i < maxframes and (u32int)stack > 0xC0000000 and (u32int)stack < (ebp + 0x10000); i++) {
+ for (u32int i = 0; i < maxframes and (isUser or ((u32int)stack > 0xC0000000)) and (u32int)stack < (ebp + 0x10000); i++) {
vt << "Frame: " << (u32int)stack << " n:" << stack[0] << " r:" << stack[1] << "\n";
stack = (u32int*)stack[0];
}
diff --git a/Source/Kernel/Core/Sys.ns.h b/Source/Kernel/Core/Sys.ns.h
index 26f04e6..f386135 100644
--- a/Source/Kernel/Core/Sys.ns.h
+++ b/Source/Kernel/Core/Sys.ns.h
@@ -30,7 +30,7 @@ namespace Sys {
u8int inb(u16int port);
u16int inw(u16int port);
void dumpRegs(registers_t *regs, VirtualTerminal& vt);
- void stackTrace(u32int ebp, VirtualTerminal& vt, u32int maxframes);
+ void stackTrace(u32int ebp, VirtualTerminal& vt, u32int maxframes, bool isUser = false);
void panic(char* message, char *file, u32int line);
void panic(char* message, registers_t *regs, char *file, u32int line);
void panic_assert(char* file, u32int line, char *desc);
diff --git a/Source/Kernel/TaskManager/Thread.class.cpp b/Source/Kernel/TaskManager/Thread.class.cpp
index af501fe..2cd9515 100644
--- a/Source/Kernel/TaskManager/Thread.class.cpp
+++ b/Source/Kernel/TaskManager/Thread.class.cpp
@@ -182,9 +182,11 @@ void Thread::handleException(registers_t *regs, int no) {
if (rw) vt << "R/W ";
if (us) vt << "User ";
if (rsvd) vt << "Rsvd ";
- vt << "At:" << (u32int)faddr;
+ vt << "At:" << (u32int)faddr << "\n";
- vt << "\nThread finishing.\n";
+ Sys::stackTrace(regs->ebp, vt, 5, true);
+
+ vt << "Thread finishing.\n";
Task::currentThreadExits(E_PAGEFAULT); //Calling this will setup a new stack
return;
}
diff --git a/Source/Kernel/VFS/FSNode-sc.proto.cpp b/Source/Kernel/VFS/FSNode-sc.proto.cpp
index 717ccef..d86014c 100644
--- a/Source/Kernel/VFS/FSNode-sc.proto.cpp
+++ b/Source/Kernel/VFS/FSNode-sc.proto.cpp
@@ -90,6 +90,7 @@ bool FSNode::readable(User* user) {
}
bool FSNode::writable(User* user) {
+ if (!m_fs->isWritable()) return false;
if (ISROOT) return true;
if (user == 0) user = Usr::user();
if (user->getUid() == m_uid)
diff --git a/Source/Kernel/VTManager/FileVT.class.cpp b/Source/Kernel/VTManager/FileVT.class.cpp
index 5469fbd..24a1b63 100644
--- a/Source/Kernel/VTManager/FileVT.class.cpp
+++ b/Source/Kernel/VTManager/FileVT.class.cpp
@@ -39,7 +39,7 @@ keypress_t FileVT::getKeypress(bool show, bool block) {
ret.hascmd = true;
ret.command = KBDC_ENTER;
if (m_file.eof()) {
- m_buffer = ".";
+ m_buffer = EOF;
} else {
m_buffer = m_file.readLine();
}
diff --git a/Source/Kernel/VTManager/VirtualTerminal-kbd.proto.cpp b/Source/Kernel/VTManager/VirtualTerminal-kbd.proto.cpp
index 5b551eb..e96c327 100644
--- a/Source/Kernel/VTManager/VirtualTerminal-kbd.proto.cpp
+++ b/Source/Kernel/VTManager/VirtualTerminal-kbd.proto.cpp
@@ -64,6 +64,9 @@ String VirtualTerminal::readLine(bool show) {
else if (show) put(" "); //Put a space so that cursor stays at same place
} else if (tmp.hascmd && !tmp.haschar && tmp.command == KBDC_TAB) {
ret += "\t";
+ } else if (tmp.hascmd && tmp.haschar && tmp.modifiers == STATUS_CTRL && tmp.character == WChar("d")) {
+ ret += EOF;
+ break;
} else if (tmp.haschar && !tmp.hascmd) {
ret += tmp.character;
}
diff --git a/Source/Library/Common/FileStream.class.cpp b/Source/Library/Common/FileStream.class.cpp
new file mode 100644
index 0000000..317a023
--- /dev/null
+++ b/Source/Library/Common/FileStream.class.cpp
@@ -0,0 +1,71 @@
+#include "FileStream.class.h"
+
+//************************************
+// INPUT FILE STREAM
+// ********************
+
+FileIStream::FileIStream(const String &filename, u8int encoding, FSNode start) : m_start(start) {
+ m_file = new File(filename, FM_READ, start);
+ m_filenames = 0;
+ m_encoding = encoding;
+}
+
+FileIStream::FileIStream(u8int encoding, FSNode start) : m_start(start) {
+ m_file = 0;
+ m_filenames = 0;
+ m_encoding = encoding;
+}
+
+FileIStream::~FileIStream() {
+ if (m_file != 0) {
+ m_file->close();
+ delete m_file;
+ }
+}
+
+void FileIStream::appendFile(const String &filename) {
+ if (m_filenames == 0) {
+ m_filenames = new SimpleList<String>(filename);
+ } else {
+ m_filenames->addAtEnd(filename);
+ }
+}
+
+String FileIStream::read() {
+ while (m_file == 0 or m_file->eof() or !m_file->valid()) {
+ if (m_file != 0) {
+ m_file->close();
+ delete m_file;
+ }
+ m_file = 0;
+ if (m_filenames == 0) {
+ return "";
+ } else {
+ m_file = new File(m_filenames->v(), FM_READ, m_start);
+ m_filenames = m_filenames->delThis();
+ }
+ }
+ ByteArray temp;
+ temp.resize(512);
+ u32int r = m_file->read(temp);
+ temp.resize(r);
+ return temp.toString(m_encoding);
+}
+
+//************************************
+// OUTPUT FILE STREAM
+// ********************
+
+FileOStream::FileOStream(const String& filename, u8int mode, u8int encoding, FSNode start) {
+ m_file = new File(filename, mode, start);
+ m_encoding = encoding;
+}
+
+FileOStream::~FileOStream() {
+ delete m_file;
+}
+
+void FileOStream::write(const String &s) {
+ ByteArray a(s, m_encoding);
+ m_file->write(a);
+}
diff --git a/Source/Library/Common/FileStream.class.h b/Source/Library/Common/FileStream.class.h
new file mode 100644
index 0000000..99bf0e8
--- /dev/null
+++ b/Source/Library/Common/FileStream.class.h
@@ -0,0 +1,43 @@
+#ifndef DEF_FILESTREAM_CLASS_H
+#define DEF_FILESTREAM_CLASS_H
+
+#include <IStream.proto.h>
+#include <OStream.proto.h>
+
+#ifdef THIS_IS_MELON_KERNEL
+#include <VFS/File.class.h>
+#else
+#include <Binding/File.class.h>
+#endif
+
+class FileIStream : public IStream {
+ private:
+ String read();
+
+ SimpleList<String> *m_filenames;
+
+ File *m_file;
+ u8int m_encoding;
+ FSNode m_start;
+
+ public:
+ FileIStream(const String &filename, u8int encoding = UE_UTF8, FSNode start = FSNode(0));
+ FileIStream(u8int encoding = UE_UTF8, FSNode start = FSNode(0));
+ ~FileIStream();
+
+ void appendFile(const String &filename);
+};
+
+class FileOStream : public OStream {
+ private:
+ File *m_file;
+ u8int m_encoding;
+
+ public:
+ FileOStream(const String &filename, u8int mode, u8int encoding = UE_UTF8, FSNode start = FSNode(0));
+ ~FileOStream();
+
+ void write(const String &s);
+};
+
+#endif
diff --git a/Source/Library/Common/IStream.proto.cpp b/Source/Library/Common/IStream.proto.cpp
new file mode 100644
index 0000000..6176eac
--- /dev/null
+++ b/Source/Library/Common/IStream.proto.cpp
@@ -0,0 +1,81 @@
+#include "IStream.proto.h"
+
+IStream::IStream() {
+ m_buffer = NULL;
+ m_ptr = 0;
+ m_eof = false;
+}
+
+IStream::IStream(const IStream& other) {
+ m_buffer = NULL;
+ m_ptr = 0;
+}
+
+IStream::~IStream() {
+ delete m_buffer;
+}
+
+bool IStream::populate() {
+ if (m_eof) return false;
+ String s = read();
+ if (s.empty()) {
+ m_eof = true;
+ return false;
+ }
+ if (m_buffer == NULL) {
+ m_buffer = new SimpleList<String>(s);
+ } else {
+ m_buffer->addAtEnd(s);
+ }
+ return true;
+}
+
+WChar IStream::getChar() {
+ waitLock();
+ if (m_buffer == 0) {
+ if (!populate()) {
+ unlock();
+ return WChar("\0");
+ }
+ }
+ WChar ret = m_buffer->v()[m_ptr];
+ m_ptr++;
+ if (m_ptr >= m_buffer->v().size()) {
+ m_buffer = m_buffer->delThis();
+ m_ptr = 0;
+ }
+ unlock();
+ return ret;
+}
+
+String IStream::get(WChar delimiter) {
+ waitLock();
+ //calculate length of string to read
+ if (m_buffer == 0) {
+ unlock();
+ if (!populate()) return "";
+ }
+ int length = 0, ptr = m_ptr;
+ for (SimpleList<String> *iter = m_buffer; iter != 0;) {
+ if (iter->v()[ptr] == delimiter) break;
+ ptr++;
+ length++;
+ if (ptr >= iter->v().size()) {
+ if (iter->next() == 0) populate();
+ iter = iter->next();
+ ptr = 0;
+ }
+ }
+ //get it
+ String ret(WChar(" "), length);
+ for (int i = 0; i <= length; i++) {
+ if (i != length) ret[i] = m_buffer->v()[m_ptr];
+ m_ptr++;
+ if (m_ptr >= m_buffer->v().size()) {
+ m_buffer = m_buffer->delThis();
+ m_ptr = 0;
+ }
+ }
+ unlock();
+ return ret;
+}
diff --git a/Source/Library/Common/IStream.proto.h b/Source/Library/Common/IStream.proto.h
new file mode 100644
index 0000000..e844726
--- /dev/null
+++ b/Source/Library/Common/IStream.proto.h
@@ -0,0 +1,32 @@
+#ifndef DEF_ISTREAM_PROTO_h
+#define DEF_ISTREAM_PROTO_h
+
+#include <String.class.h>
+#include <SimpleList.class.h>
+#include <Mutex.class.h>
+
+class IStream : private Mutex {
+ private:
+ SimpleList<String> *m_buffer;
+ int m_ptr;
+ void operator =(IStream& other);
+ bool m_eof;
+
+ bool populate();
+
+ protected:
+ virtual String read() = 0;
+
+ public:
+ IStream();
+ IStream(const IStream& other);
+ virtual ~IStream();
+
+ bool eof() const { return m_eof && (m_buffer == NULL); }
+
+ WChar getChar();
+ String get(WChar delimiter = "\n");
+ String getWord() { return get(" "); }
+};
+
+#endif
diff --git a/Source/Library/Common/OStream.proto.cpp b/Source/Library/Common/OStream.proto.cpp
new file mode 100644
index 0000000..f0667e7
--- /dev/null
+++ b/Source/Library/Common/OStream.proto.cpp
@@ -0,0 +1,65 @@
+#include <OStream.proto.h>
+
+OStream::OStream() {
+ m_buffer = NULL;
+ m_last = NULL;
+}
+
+OStream::OStream(const OStream& other) {
+ m_buffer = NULL;
+ m_last = NULL;
+}
+
+void OStream::put(const String &s) {
+ if (s.empty()) return;
+ waitLock();
+ if (m_buffer == NULL or m_last == NULL) {
+ m_buffer = m_last = new SimpleList<String>(s);
+ } else {
+ m_last = m_last->addAtEnd(s);
+ }
+ unlock();
+}
+
+void OStream::flush() {
+ if (m_buffer == NULL or m_last == NULL) return;
+
+ waitLock();
+ //Calculate buffer size
+ int size = 0;
+ SimpleList<String>* iter = m_buffer;
+ for (; iter != 0; iter = iter->next()) {
+ size += iter->v().size();
+ }
+ //Get stuff
+ String buff(WChar(" "), size);
+ iter = m_buffer;
+ for (int i = 0, pos = 0; i < size; i++, pos++) {
+ if (pos >= iter->v().size()) {
+ iter = iter->next();
+ pos = 0;
+ }
+ buff[i] = iter->v()[pos];
+ }
+ //Write it
+ write(buff);
+
+ delete m_buffer;
+ m_buffer = NULL;
+ m_last = NULL;
+
+ unlock();
+}
+
+OStream& OStream::operator<< (ostream_modifiers_e m) {
+ if (m == FLUSH) {
+ flush();
+ } else if (m == ENDL) {
+ put("\n");
+ flush();
+ } else if (m == END) {
+ put(EOF);
+ flush();
+ }
+ return *this;
+}
diff --git a/Source/Library/Common/OStream.proto.h b/Source/Library/Common/OStream.proto.h
new file mode 100644
index 0000000..ff19e7b
--- /dev/null
+++ b/Source/Library/Common/OStream.proto.h
@@ -0,0 +1,39 @@
+#ifndef DEF_ISTREAM_PROTO_H
+#define DEF_ISTREAM_PROTO_H
+
+#include <String.class.h>
+#include <SimpleList.class.h>
+#include <Mutex.class.h>
+
+enum ostream_modifiers_e {
+ FLUSH,
+ ENDL,
+ END
+};
+
+class OStream : private Mutex {
+ private:
+ SimpleList<String> *m_buffer;
+ SimpleList<String> *m_last;
+ void operator =(OStream& other);
+
+ protected:
+ virtual void write(const String &s) = 0;
+
+ public:
+ OStream();
+ OStream(const OStream& other);
+ virtual ~OStream() { flush(); }
+
+ void put(const String& s);
+ void flush();
+
+ //Formatting functions
+ OStream& operator << (const String& s) { put(s); if (s.contains("\n")) flush(); return *this; }
+ OStream& operator << (s64int i) { put(String::number(i)); return *this; }
+ OStream& operator << (s32int i) { put(String::number(i)); return *this; }
+ OStream& operator << (u32int i) { put(String::hex(i)); return *this; }
+ OStream& operator << (ostream_modifiers_e m);
+};
+
+#endif
diff --git a/Source/Library/Common/SimpleList.class.h b/Source/Library/Common/SimpleList.class.h
index 8fcd834..2bbbace 100644
--- a/Source/Library/Common/SimpleList.class.h
+++ b/Source/Library/Common/SimpleList.class.h
@@ -25,6 +25,19 @@ class SimpleList {
return new SimpleList<T>(value, this);
}
+ SimpleList<T>* addAtEnd(const T& value) {
+ if (this == 0) {
+ return new SimpleList<T>(value);
+ } else {
+ if (m_next == 0) {
+ m_next = new SimpleList<T>(value);
+ return m_next;
+ } else {
+ return m_next->addAtEnd(value);
+ }
+ }
+ }
+
SimpleList<T>* next() {
return m_next;
}
diff --git a/Source/Library/Common/StringStream.class.cpp b/Source/Library/Common/StringStream.class.cpp
new file mode 100644
index 0000000..c4377ce
--- /dev/null
+++ b/Source/Library/Common/StringStream.class.cpp
@@ -0,0 +1,28 @@
+#include "StringStream.class.h"
+
+StringIStream::StringIStream(const String &e) {
+ m_elements = new SimpleList<String>(e);
+}
+
+StringIStream::StringIStream() {
+ m_elements = 0;
+}
+
+StringIStream::~StringIStream() {
+ if (m_elements != 0) delete m_elements;
+}
+
+String StringIStream::read() {
+ if (m_elements == 0) return "";
+ String ret = m_elements->v();
+ m_elements = m_elements->delThis();
+ return ret;
+}
+
+void StringIStream::append(const String &e) {
+ if (m_elements == 0) {
+ m_elements = new SimpleList<String>(e);
+ } else {
+ m_elements->addAtEnd(e);
+ }
+}
diff --git a/Source/Library/Common/StringStream.class.h b/Source/Library/Common/StringStream.class.h
new file mode 100644
index 0000000..814b539
--- /dev/null
+++ b/Source/Library/Common/StringStream.class.h
@@ -0,0 +1,35 @@
+#ifndef DEF_STRINGSTREAM_CLASS_H
+#define DEF_STRINGSTREAM_CLASS_H
+
+#include <IStream.proto.h>
+#include <OStream.proto.h>
+
+class StringIStream : public IStream {
+ private:
+ SimpleList<String> *m_elements;
+
+ String read();
+
+ public:
+ StringIStream(const String &e);
+ StringIStream();
+ ~StringIStream();
+
+ void append(const String &e);
+};
+
+class StringOStream : public OStream {
+ private:
+ String m_str;
+
+ void write(const String& s) { m_str += s; }
+
+ public:
+
+ const String &str() const { return m_str; }
+ void clear() { m_str = ""; }
+};
+
+
+#endif
+
diff --git a/Source/Library/Common/WChar.class.h b/Source/Library/Common/WChar.class.h
index afaeb44..6db4b1b 100644
--- a/Source/Library/Common/WChar.class.h
+++ b/Source/Library/Common/WChar.class.h
@@ -7,6 +7,8 @@
#include <common.h>
#endif
+#define EOF "\3"
+
enum {
UE_UTF8,
UE_UTF16_LE,
diff --git a/Source/Library/Makefile b/Source/Library/Makefile
index b3040d4..c67daf7 100644
--- a/Source/Library/Makefile
+++ b/Source/Library/Makefile
@@ -19,8 +19,13 @@ Objects = Common/WChar.class.uo \
Common/TextFile.class.uo \
Common/ByteArray.class.uo \
Common/Rand.ns.uo \
+ Common/OStream.proto.uo \
+ Common/IStream.proto.uo \
+ Common/FileStream.class.uo \
+ Common/StringStream.class.uo \
Common/cppsupport.wtf.uo \
Userland/App/ShellApp.proto.uo \
+ Userland/App/StreamApp.proto.uo \
Userland/Syscall/Syscall.wtf.uo \
Userland/Syscall/RessourceCaller.class.uo \
Userland/Start.uo
diff --git a/Source/Library/Userland/App/ShellApp.proto.cpp b/Source/Library/Userland/App/ShellApp.proto.cpp
index a3d9737..123eb73 100644
--- a/Source/Library/Userland/App/ShellApp.proto.cpp
+++ b/Source/Library/Userland/App/ShellApp.proto.cpp
@@ -1,6 +1,6 @@
#include "ShellApp.proto.h"
-ShellApp::ShellApp(String name, String desc)
+ShellApp::ShellApp(const String &name, const String &desc)
: Application(), invt(VirtualTerminal::getIn()), outvt(VirtualTerminal::getOut()) {
appName = name, appDesc = desc;
if (!invt.valid()) exit(1);
@@ -9,11 +9,17 @@ ShellApp::ShellApp(String name, String desc)
addFlag("h", "help", "Show this help screen");
}
+ShellApp::~ShellApp() {
+ outvt << END;
+}
+
void ShellApp::init() {
//Parse flags
u32int argc = pr.argc();
- for (u32int i = 0; i < argc; i++) {
+ args.clear();
+ for (u32int i = 1; i < argc; i++) {
String arg = pr.argv(i);
+ if (arg.empty()) continue;
if (arg == "-") {
i++;
if (i == argc) {
@@ -26,13 +32,13 @@ void ShellApp::init() {
bool found = false;
for (u32int i = 0; i < flags.size(); i++) {
if (flags[i].type == FT_BOOL) {
- if (arg == String("--no-") + flags[i].lName) {
+ if (arg == (String("--no-") += flags[i].lName)) {
flags[i].boolVal = false;
found = true;
}
}
}
- if (!found) outvt << "Unknown option : " << arg << "\n";
+ if (!found) outvt << "Unknown option : " << arg << ENDL;
} else if (arg.substr(0, 2) == "--") {
bool found = false;
for (u32int i = 0; i < flags.size(); i++) {
@@ -49,21 +55,29 @@ void ShellApp::init() {
}
}
}
- if (!found) outvt << "Unknown option : " << arg << "\n";
+ if (!found) outvt << "Unknown option : " << arg << ENDL;
} else {
for (u32int j = 1; j < arg.size(); j++) {
bool found = false;
for (u32int k = 0; k < flags.size(); k++) {
if (flags[k].sName == arg[j]) {
found = true;
- if (flags[k].type == FT_BOOL) flags[k].boolVal = true;
- if (flags[k].type == FT_INT) flags[k].intVal = pr.argv(++i).toInt();
- if (flags[k].type == FT_STR) flags[k].strVal = pr.argv(++i);
+ if (flags[k].type == FT_BOOL) {
+ flags[k].boolVal = true;
+ } else {
+ i++;
+ if (i >= argc) {
+ outvt << "Missing argument for flag : -" << String(arg[j], 1) << ENDL;
+ } else {
+ flags[k].strVal = pr.argv(i);
+ if (flags[k].type == FT_INT) flags[k].intVal = flags[k].strVal.toInt();
+ }
+ }
break;
}
}
if (!found) {
- outvt << "Unknown option : -" << String(arg[j]) << "\n";
+ outvt << "Unknown option : -" << String(arg[j], 1) << ENDL;
exit(-1);
}
}
@@ -76,7 +90,7 @@ void ShellApp::init() {
//Eventually show help screen
if (bFlag("help")) {
outvt << appName << ": " << appDesc << "\n";
- outvt << "Usage: \t" << appName << " <flags> [-] <arguments>\n\n";
+ outvt << "Usage: \t" << pr.argv(0) << " <flags> [-] <arguments>\n\n";
outvt << "Possible flags :\n";
for (u32int i = 0; i < flags.size(); i++) {
outvt << " --" << flags[i].lName << "\t" << (flags[i].sName != 0 ? "-" : "") << String(flags[i].sName) << "\t";
diff --git a/Source/Library/Userland/App/ShellApp.proto.h b/Source/Library/Userland/App/ShellApp.proto.h
index 5575112..bc57cd0 100644
--- a/Source/Library/Userland/App/ShellApp.proto.h
+++ b/Source/Library/Userland/App/ShellApp.proto.h
@@ -23,7 +23,8 @@ class ShellApp : public Application {
Vector<String> args;
Vector<flag_t> flags;
String appName, appDesc;
- ShellApp(String name, String desc);
+ ShellApp(const String &name, const String &desc);
+ ~ShellApp();
virtual void init();
diff --git a/Source/Library/Userland/App/StreamApp.proto.cpp b/Source/Library/Userland/App/StreamApp.proto.cpp
new file mode 100644
index 0000000..b1dc7dd
--- /dev/null
+++ b/Source/Library/Userland/App/StreamApp.proto.cpp
@@ -0,0 +1,40 @@
+#include "StreamApp.proto.h"
+
+#include <FileStream.class.h>
+
+StreamApp::StreamApp(const String& name, const String& desc)
+ : ShellApp(name, desc) {
+ addFlag("o", "output", "Set the output to a file instead of the text output", FT_STR, "");
+ addFlag("e", "encoding", "Set the encoding for files (input and output)", FT_STR, "utf8");
+ addFlag("a", "append", "When writing to a file, append instead of truncating", FT_BOOL, "");
+}
+
+StreamApp::~StreamApp() {
+}
+
+void StreamApp::init() {
+ ShellApp::init();
+
+ u8int encoding = UE_UTF8;
+ if (sFlag("encoding") == "utf8") encoding = UE_UTF8;
+ if (sFlag("encoding") == "utf16be") encoding = UE_UTF16_BE;
+ if (sFlag("encoding") == "utf16le") encoding = UE_UTF16_LE;
+ if (sFlag("encoding") == "utf32be") encoding = UE_UTF32_BE;
+ if (sFlag("encoding") == "utf32le") encoding = UE_UTF32_LE;
+
+ if (sFlag("output") == "") {
+ out = &outvt;
+ } else {
+ out = new FileOStream(sFlag("output"), (bFlag("append") ? FM_APPEND : FM_TRUNCATE), encoding, FS::cwdNode());
+ }
+
+ if (args.size() == 0) {
+ in = &invt;
+ } else {
+ FileIStream *f = new FileIStream(encoding, FS::cwdNode());
+ for (u32int i = 0; i < args.size(); i++) {
+ f->appendFile(args[i]);
+ }
+ in = f;
+ }
+}
diff --git a/Source/Library/Userland/App/StreamApp.proto.h b/Source/Library/Userland/App/StreamApp.proto.h
new file mode 100644
index 0000000..462b1f3
--- /dev/null
+++ b/Source/Library/Userland/App/StreamApp.proto.h
@@ -0,0 +1,27 @@
+#ifndef DEF_STREAMAPP_PROTO_H
+#define DEF_STREAMAPP_PROTO_H
+
+#include "ShellApp.proto.h"
+
+#include <IStream.proto.h>
+#include <OStream.proto.h>
+
+/*
+ * This class implements basic utilities for apps that simply take some input, process it and output something.
+ * Examples : cat, grep, ...
+ */
+
+class StreamApp : public ShellApp {
+ protected:
+
+ IStream *in;
+ OStream *out;
+
+ public:
+ StreamApp(const String& name, const String& desc);
+ ~StreamApp();
+
+ virtual void init();
+};
+
+#endif
diff --git a/Source/Library/Userland/Binding/Process.class.h b/Source/Library/Userland/Binding/Process.class.h
index 2200f59..e94084b 100644
--- a/Source/Library/Userland/Binding/Process.class.h
+++ b/Source/Library/Userland/Binding/Process.class.h
@@ -54,10 +54,10 @@ class Process : public RessourceCaller {
void pushArg(const String& arg) {
doCall(PRIF_PUSHARG, (u32int)&arg);
}
- void setInVT(VirtualTerminal vt) {
+ void setInVT(const VirtualTerminal& vt) {
doCall(PRIF_SETINVT, vt.resId());
}
- void setOutVT(VirtualTerminal vt) {
+ void setOutVT(const VirtualTerminal& vt) {
doCall(PRIF_SETOUTVT, vt.resId());
}
bool authenticatePW(String user, String pw) {
diff --git a/Source/Library/Userland/Binding/VirtualTerminal.class.h b/Source/Library/Userland/Binding/VirtualTerminal.class.h
index 70c6b23..2a38abd 100644
--- a/Source/Library/Userland/Binding/VirtualTerminal.class.h
+++ b/Source/Library/Userland/Binding/VirtualTerminal.class.h
@@ -6,10 +6,14 @@
#include <VirtualTerminal.iface.h>
#include <Kbd.iface.h>
-#include <String.class.h>
+#include <OStream.proto.h>
+#include <IStream.proto.h>
#include <WChar.class.h>
-class VirtualTerminal : public RessourceCaller {
+class VirtualTerminal : public RessourceCaller, public OStream, public IStream {
+ private:
+ bool m_eof;
+
public:
static VirtualTerminal getIn() {
u32int id = RessourceCaller::sCall(VTIF_OBJTYPE, VTIF_SGETPRINVT);
@@ -19,22 +23,33 @@ class VirtualTerminal : public RessourceCaller {
u32int id = RessourceCaller::sCall(VTIF_OBJTYPE, VTIF_SGETPROUTVT);
return VirtualTerminal(id);
}
- VirtualTerminal(u32int id) : RessourceCaller(id, VTIF_OBJTYPE) {}
+ VirtualTerminal(u32int id) : RessourceCaller(id, VTIF_OBJTYPE) { m_eof = false; }
- void writeHex(u32int number) {
+ /*void writeHex(u32int number) {
doCall(VTIF_WRITEHEX, number);
}
void writeDec(s64int number) {
doCall(VTIF_WRITEDEC, (number >> 32), number);
- }
- void write(String s) {
+ }*/
+ void write(const String &s) {
doCall(VTIF_WRITE, (u32int)&s);
}
+ String read() {
+ if (m_eof) return "";
+ String ret = String::unserialize(doCall(VTIF_READLINE, 1));
+ if (ret[ret.size() - 1] == WChar(EOF)) {
+ ret = ret.substr(0, ret.size() - 1);
+ if (ret.empty()) return "";
+ m_eof = true;
+ }
+ return ret += "\n";
+ }
keypress_t getKeypress(bool show = true, bool block = true) {
keypress_t* ptr = (keypress_t*)doCall(VTIF_GETKEYPRESS, (show ? 1 : 0) | (block ? 2 : 0));
return *ptr;
}
String readLine(bool show = true) {
+ flush();
return String::unserialize(doCall(VTIF_READLINE, (show ? 1 : 0)));
}
void setColor(u8int fg, u8int bg = 0xFF) {
@@ -64,11 +79,6 @@ class VirtualTerminal : public RessourceCaller {
void put(u8int line, u8int col, WChar c) {
moveCursor(line, col); put(c);
}
-
- inline VirtualTerminal& operator<<(const String& s) { write(s); return *this; }
- inline VirtualTerminal& operator<<(s32int i) { writeDec(i); return *this; }
- inline VirtualTerminal& operator<<(s64int i) { writeDec(i); return *this; }
- inline VirtualTerminal& operator<<(u32int i) { writeHex(i); return *this; }
};
#endif
diff --git a/Source/Library/Userland/Syscall/RessourceCaller.class.h b/Source/Library/Userland/Syscall/RessourceCaller.class.h
index f26216d..39091ed 100644
--- a/Source/Library/Userland/Syscall/RessourceCaller.class.h
+++ b/Source/Library/Userland/Syscall/RessourceCaller.class.h
@@ -28,8 +28,8 @@ class RessourceCaller {
public:
static u32int sCall(u32int type, u8int wat, u32int a = 0, u32int b = 0, u32int c = 0, u32int d = 0);
- u32int resId() { return m_id; }
- u32int resType() { return m_type; }
+ u32int resId() const { return m_id; }
+ u32int resType() const { return m_type; }
bool valid() { return m_type != 0; }
};