Permalink
Browse files

Added support for rudimentary file I/O.

This should be reviewed later with more background, because it
is a bit rough, as is.
  • Loading branch information...
1 parent f826d24 commit 908c1e036874db354b792cc0bfbb1d766786b9e5 @sjrd sjrd committed Jun 14, 2012
Showing with 483 additions and 10 deletions.
  1. +71 −3 boostenv/main/BoostBase.oz
  2. +53 −2 boostenv/main/boostenv-decl.hh
  3. +14 −0 boostenv/main/boostenv.cc
  4. +136 −0 boostenv/main/boostenv.hh
  5. +190 −5 boostenv/main/modos.hh
  6. +19 −0 vm/main/matchdsl.hh
View
@@ -5,8 +5,76 @@ require
prepare
- OS = os(rand: Boot_OS.rand
- srand: Boot_OS.srand
- randLimits: Boot_OS.randLimits)
+ local
+ fun {FlagsToMode Flags}
+ if {Member 'O_WRONLY' Flags} then
+ if {Member 'O_APPEND' Flags} then
+ "ab"
+ else
+ "wb"
+ end
+ elseif {Member 'O_RDWR' Flags} then
+ if {Not {Member 'O_CREAT' Flags}} then
+ "r+b"
+ elseif {Member 'O_APPEND' Flags} then
+ "a+b"
+ else
+ "w+b"
+ end
+ else
+ "rb"
+ end
+ end
+
+ fun {Open FileName Flags CreateMode}
+ {Boot_OS.fopen FileName {FlagsToMode Flags}}
+ end
+
+ fun {FileDesc DescName}
+ case DescName
+ of 'STDIN_FILENO' then {Boot_OS.stdin}
+ [] 'STDOUT_FILENO' then {Boot_OS.stdout}
+ [] 'STDERR_FILENO' then {Boot_OS.stderr}
+ end
+ end
+
+ proc {Read FD Max ?Head Tail ?Count}
+ {Boot_OS.fread FD Max Tail Count Head}
+ end
+
+ fun {Write FD Data}
+ {Boot_OS.fwrite FD Data}
+ end
+
+ proc {LSeek FD Whence Offset ?Where}
+ {Boot_OS.fseek FD Offset Whence Where}
+ end
+
+ proc {Close FD}
+ {Boot_OS.fclose FD}
+ end
+ in
+ OS = os(rand: Boot_OS.rand
+ srand: Boot_OS.srand
+ randLimits: Boot_OS.randLimits
+
+ fopen: Boot_OS.fopen
+ fread: Read
+ fwrite: Boot_OS.fwrite
+ fseek: Boot_OS.fseek
+ fclose: Boot_OS.fclose
+
+ stdin: Boot_OS.stdin
+ stdout: Boot_OS.stdout
+ stderr: Boot_OS.stderr
+
+ % compatibility
+ open: Open
+ fileDesc: FileDesc
+ read: Read
+ write: Write
+ lSeek: LSeek
+ close: Close)
+ end
end
@@ -28,6 +28,8 @@
#include <mozart.hh>
#include <ctime>
+#include <cstdio>
+#include <cerrno>
#include <boost/thread.hpp>
@@ -42,8 +44,11 @@ namespace mozart { namespace boostenv {
class BoostBasedVM: public VirtualMachineEnvironment {
public:
- BoostBasedVM(): virtualMachine(*this), vm(&virtualMachine),
- random_generator(std::time(nullptr)), uuidGenerator(random_generator) {}
+ BoostBasedVM();
+
+ static BoostBasedVM& forVM(VM vm) {
+ return static_cast<BoostBasedVM&>(vm->getEnvironment());
+ }
// Run and preemption
@@ -63,6 +68,24 @@ private:
inline
static std::uint64_t bytes2uint64(const std::uint8_t* bytes);
+// Internal file descriptors management
+
+public:
+ inline
+ nativeint registerFile(std::FILE* file);
+
+ inline
+ void unregisterFile(nativeint fd);
+
+ inline
+ std::FILE* getFile(nativeint fd);
+
+ inline
+ OpResult getFile(nativeint fd, std::FILE*& result);
+
+ inline
+ OpResult getFile(RichNode fd, std::FILE*& result);
+
// Reference to the virtual machine
private:
@@ -74,8 +97,36 @@ public:
random_generator_t random_generator;
private:
boost::uuids::random_generator uuidGenerator;
+private:
+ std::map<nativeint, std::FILE*> openedFiles;
+public:
+ nativeint fdStdin;
+ nativeint fdStdout;
+ nativeint fdStderr;
};
+///////////////
+// Utilities //
+///////////////
+
+inline
+OpResult ozListLength(VM vm, RichNode list, size_t& result);
+
+inline
+OpResult ozStringToBuffer(VM vm, RichNode value, size_t size, char* buffer);
+
+inline
+OpResult ozStringToStdString(VM vm, RichNode value, std::string& result);
+
+inline
+OpResult stdStringToOzString(VM vm, std::string& value, UnstableNode& result);
+
+inline
+OpResult raiseOSError(VM vm, int errnum);
+
+inline
+OpResult raiseLastOSError(VM vm);
+
} }
#endif // __BOOSTENV_DECL_H
View
@@ -26,10 +26,24 @@
namespace mozart { namespace boostenv {
+// Some definitions
+
+namespace builtins {
+ const size_t ModOS::MaxBufferSize;
+}
+
//////////////////
// BoostBasedVM //
//////////////////
+BoostBasedVM::BoostBasedVM(): virtualMachine(*this), vm(&virtualMachine),
+ random_generator(std::time(nullptr)), uuidGenerator(random_generator) {
+
+ fdStdin = registerFile(stdin);
+ fdStdout = registerFile(stdout);
+ fdStderr = registerFile(stderr);
+}
+
void BoostBasedVM::run() {
vm->setReferenceTime(getReferenceTime());
View
@@ -35,6 +35,142 @@ namespace mozart { namespace boostenv {
// BoostBasedVM //
//////////////////
+nativeint BoostBasedVM::registerFile(std::FILE* file) {
+ nativeint result = 0;
+ while (openedFiles.count(result) != 0)
+ result++;
+
+ openedFiles[result] = file;
+ return result;
+}
+
+void BoostBasedVM::unregisterFile(nativeint fd) {
+ openedFiles.erase(fd);
+}
+
+std::FILE* BoostBasedVM::getFile(nativeint fd) {
+ auto iter = openedFiles.find(fd);
+
+ if (iter != openedFiles.end())
+ return iter->second;
+ else
+ return nullptr;
+}
+
+OpResult BoostBasedVM::getFile(nativeint fd, std::FILE*& result) {
+ result = getFile(fd);
+ if (result == nullptr)
+ return raise(vm, u"system", u"invalidfd", fd);
+ return OpResult::proceed();
+}
+
+OpResult BoostBasedVM::getFile(RichNode fd, std::FILE*& result) {
+ nativeint intfd = 0;
+ MOZART_GET_ARG(intfd, fd, u"filedesc");
+
+ return getFile(intfd, result);
+}
+
+///////////////
+// Utilities //
+///////////////
+
+namespace internal {
+ inline
+ OpResult ozListLengthEx(VM vm, RichNode list, size_t& accumulator) {
+ using namespace patternmatching;
+
+ OpResult res = OpResult::proceed();
+ UnstableNode tail;
+
+ if (matchesCons(vm, res, list, wildcard(), capture(tail))) {
+ accumulator++;
+ return ozListLengthEx(vm, tail, accumulator);
+ } else if (matches(vm, res, list, vm->coreatoms.nil)) {
+ return OpResult::proceed();
+ } else {
+ return matchTypeError(vm, res, list, u"list");
+ }
+ }
+
+ template <class T>
+ inline
+ OpResult ozListForEach(VM vm, RichNode list, size_t index,
+ const char16_t* expectedType,
+ std::function<OpResult (VM, size_t, T)> f) {
+ using namespace patternmatching;
+
+ OpResult res = OpResult::proceed();
+ T head;
+ UnstableNode tail;
+
+ if (matchesCons(vm, res, list, capture(head), capture(tail))) {
+ MOZART_CHECK_OPRESULT(f(vm, index, head));
+ return ozListForEach(vm, tail, index+1, expectedType, f);
+ } else if (matches(vm, res, list, vm->coreatoms.nil)) {
+ return OpResult::proceed();
+ } else {
+ return matchTypeError(vm, res, list, expectedType);
+ }
+ }
+}
+
+OpResult ozListLength(VM vm, RichNode list, size_t& result) {
+ result = 0;
+ return internal::ozListLengthEx(vm, list, result);
+}
+
+OpResult ozStringToBuffer(VM vm, RichNode value, size_t size, char* buffer) {
+ MOZART_CHECK_OPRESULT(internal::ozListForEach<char>(
+ vm, value, 0, u"string",
+ [size, buffer] (VM vm, size_t i, char c) -> OpResult {
+ assert(i < size);
+ buffer[i] = c;
+ return OpResult::proceed();
+ }));
+
+ return OpResult::proceed();
+}
+
+OpResult ozStringToStdString(VM vm, RichNode value, std::string& result) {
+ std::stringbuf buffer;
+
+ MOZART_CHECK_OPRESULT(internal::ozListForEach<char>(
+ vm, value, 0, u"string", [&buffer] (VM vm, size_t i, char c) -> OpResult {
+ buffer.sputc(c);
+ return OpResult::proceed();
+ }));
+
+ result = buffer.str();
+ return OpResult::proceed();
+}
+
+OpResult stdStringToOzString(VM vm, std::string& value, UnstableNode& result) {
+ UnstableNode res = trivialBuild(vm, vm->coreatoms.nil);
+
+ for (auto iter = value.rbegin(); iter != value.rend(); ++iter) {
+ res = buildCons(vm, *iter, std::move(res));
+ }
+
+ result = std::move(res);
+ return OpResult::proceed();
+}
+
+OpResult raiseOSError(VM vm, int errnum) {
+ const char* message = std::strerror(errnum);
+ size_t len = std::strlen(message);
+
+ auto umessage = std::unique_ptr<char16_t[]>(new char16_t[len+1]);
+ for (size_t i = 0; i <= len; i++)
+ umessage[i] = (char16_t) message[i];
+
+ return raise(vm, u"system", errnum, umessage.get());
+}
+
+OpResult raiseLastOSError(VM vm) {
+ return raiseOSError(vm, errno);
+}
+
} }
#endif // __BOOSTENV_H
Oops, something went wrong.

0 comments on commit 908c1e0

Please sign in to comment.