diff options
41 files changed, 648 insertions, 67 deletions
@@ -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 @@ -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 Binary files differnew file mode 100644 index 0000000..069ba9e --- /dev/null +++ b/Media/Screenshots/2009-12-20-193041_1032x794_scrot.png 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 Binary files differnew file mode 100755 index 0000000..c10df80 --- /dev/null +++ b/Mount/boot/stage1 diff --git a/Mount/boot/stage2 b/Mount/boot/stage2 Binary files differnew file mode 100755 index 0000000..8b578cf --- /dev/null +++ b/Mount/boot/stage2 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 Binary files differnew file mode 100755 index 0000000..0399a6f --- /dev/null +++ b/Source/Applications/Shell/Applets/rot13 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; } }; |