aboutsummaryrefslogtreecommitdiff
path: root/interpreter/ElymasSys.pm
diff options
context:
space:
mode:
Diffstat (limited to 'interpreter/ElymasSys.pm')
-rw-r--r--interpreter/ElymasSys.pm165
1 files changed, 121 insertions, 44 deletions
diff --git a/interpreter/ElymasSys.pm b/interpreter/ElymasSys.pm
index 1718060..50b2ad7 100644
--- a/interpreter/ElymasSys.pm
+++ b/interpreter/ElymasSys.pm
@@ -1,58 +1,135 @@
-package ElymasLinux;
+package ElymasSys;
use strict;
use warnings;
use Elymas;
+use POSIX;
-use POSIX ();
-
-our $linux = {
- 'open' => [sub {
- my ($data, $scope) = @_;
-
- my $mode = popInt($data);
- my $flags = popInt($data);
- my $pathname = popString($data);
-
- my $fd = POSIX::open($pathname, $flags, $mode);
- $fd = -1 unless defined $fd;
-
- push @$data, [$fd, 'int'];
- }, ['func', 'linux .open'], 'active'],
- 'close' => [sub {
- my ($data, $scope) = @_;
-
- my $fd = popInt($data);
-
- my $ret = POSIX::close($fd);
- $ret = -1 unless defined $ret;
-
- push @$data, [$ret, 'int'];
- }, ['func', 'linux .close'], 'active'],
-# 'read' => [sub {
-# my ($data, $scope) = @_;
-#
-# my $count = popInt($data);
-# my $buf = popArray($data);
-# my $fd = popInt($data);
-#
-# my $ret = POSIX::close($fd);
-# $ret = -1 unless defined $ret;
-#
-# push @$data, [$ret, 'int'];
-# }, ['func', 'linux .read'], 'active'],
+my $rwmask = &POSIX::O_RDONLY | &POSIX::O_WRONLY | &POSIX::O_RDWR;
+
+our $sys = {
+ 'file' => [sub {
+ my ($data) = @_;
+
+ my $file = createFile(-1, &POSIX::O_RDONLY);
+ push @$data, [enstruct($file)];
+ }, ['func', 'sys .file'], 'active'],
+ 'in' => [enstruct(createFile(0, &POSIX::O_RDONLY)), 'passive'],
+ 'out' => [enstruct(createFile(1, &POSIX::O_WRONLY)), 'passive'],
+ 'err' => [enstruct(createFile(2, &POSIX::O_WRONLY)), 'passive'],
};
-map { installIntConstant($_) } qw(O_RDONLY O_RDWR O_WRONLY);
+sub createFile {
+ my ($fd, $flags) = @_;
+
+ my $scope;
+ $scope = \{
+ ' fd' => [$fd, 'int', 'passive'],
+ ' flags' => [$flags, 'int', 'passive'],
+ ' mode' => [0777, 'int', 'passive'],
+ 'readonly' => [sub {
+ $$scope->{' flags'}->[0] = ($$scope->{' flags'}->[0] & ~($rwmask)) | &POSIX::O_RDONLY;
+ }, ['func', 'sys .file .readonly'], 'active'],
+ 'writeonly' => [sub {
+ $$scope->{' flags'}->[0] = ($$scope->{' flags'}->[0] & ~($rwmask)) | &POSIX::O_WRONLY;
+ }, ['func', 'sys .file .readonly'], 'active'],
+ 'readwrite' => [sub {
+ $$scope->{' flags'}->[0] = ($$scope->{' flags'}->[0] & ~($rwmask)) | &POSIX::O_RDWR;
+ }, ['func', 'sys .file .readonly'], 'active'],
+ 'open' => [sub {
+ my ($data) = @_;
+
+ die "file already open" unless $$scope->{' fd'}->[0] == -1;
+
+ my $path = popString($data);
+
+ my $fd = POSIX::open($path, $$scope->{' flags'}->[0], $$scope->{' mode'}->[0]);
+ die "cannot open $path: $!" unless defined $fd;
+
+ $$scope->{' fd'}->[0] = $fd;
+ }, ['func', 'sys .file .open'], 'active'],
+ 'close' => [sub {
+ die "file not open" if $$scope->{' fd'}->[0] == -1;
+
+ my $ret = POSIX::close($$scope->{' fd'}->[0]);
+ die "close failed: $!" unless defined $ret;
+
+ $$scope->{' fd'}->[0] = -1;
+ }, ['func', 'sys .file .close'], 'active'],
+ 'read' => [sub {
+ my ($data) = @_;
+
+ die "file not open" if $$scope->{' fd'}->[0] == -1;
+
+ my $count = popInt($data);
+
+ my $buf;
+ my $ret = POSIX::read($$scope->{' fd'}->[0], $buf, $count);
+ die "read failed: $!" unless defined $ret;
+
+ $buf = [map { [ord, 'int'] } split //, $buf];
-sub installIntConstant {
- my ($name) = @_;
+ push @$data, [$buf, ['array', '[]', [['range', 0, $#{$buf}]], ['int']]];
+ }, ['func', 'sys .file .read'], 'active'],
+ 'readall' => [sub {
+ my ($data) = @_;
- my $elymasName = $name;
- $elymasName =~ s/_//g;
+ die "file not open" if $$scope->{' fd'}->[0] == -1;
- $linux->{$elymasName} = [${$POSIX::{$name}}, 'int', 'passive'];
+ my $count = popInt($data);
+
+ my $buf = [];
+ while($count) {
+ my $readbuf;
+ my $ret = POSIX::read($$scope->{' fd'}->[0], $readbuf, $count);
+ die "read failed: $!" unless defined $ret;
+
+ $buf = [@$buf, map { [ord, 'int'] } split //, $readbuf];
+ $count -= $ret;
+ }
+
+ push @$data, [$buf, ['array', '[]', [['range', 0, $#{$buf}]], ['int']]];
+ }, ['func', 'sys .file .read'], 'active'],
+ 'write' => [sub {
+ my ($data) = @_;
+
+ die "file not open" if $$scope->{' fd'}->[0] == -1;
+
+ my $buf = popArray($data);
+ $buf = join '', map { chr($_->[0]) } @$buf;
+
+ my $ret = POSIX::write($$scope->{' fd'}->[0], $buf, length $buf);
+ die "write failed: $!" unless defined $ret;
+
+ push @$data, [$ret, 'int'];
+ }, ['func', 'sys .file .write'], 'active'],
+ 'writeall' => [sub {
+ my ($data) = @_;
+
+ die "file not open" if $$scope->{' fd'}->[0] == -1;
+
+ my $buf = popArray($data);
+ $buf = join '', map { chr($_->[0]) } @$buf;
+
+ while($buf) {
+ my $ret = POSIX::write($$scope->{' fd'}->[0], $buf, length $buf);
+ die "write failed: $!" unless defined $ret;
+ $buf = substr($buf, $ret);
+ }
+ }, ['func', 'sys .file .write'], 'active'],
+ };
+
+ return $$scope;
}
+# sub installIntConstant {
+# my ($name) = @_;
+#
+# my $elymasName = $name;
+# $elymasName =~ s/_//g;
+#
+# $linux->{$elymasName} = [${$POSIX::{$name}}, 'int', 'passive'];
+# }
+
1;