aboutsummaryrefslogtreecommitdiff
path: root/interpreter/ElymasSys.pm
blob: ad79b02bc6814c814a02e2d8478e4434e14c3c80 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package ElymasSys;

use strict;
use warnings;

use Elymas;
use ElymasAsm;
use POSIX;

my $rwmask = &POSIX::O_RDONLY | &POSIX::O_WRONLY | &POSIX::O_RDWR;

our $sys = {
  'file' => [sub {
      my ($data, $scope) = @_;

      my $file = createFile(-1, &POSIX::O_RDONLY);
      push @$data, [$file, ['struct']];
    }, ['func', 'sys .file'], 'active'],
  'in' => [createFile(0, &POSIX::O_RDONLY), ['struct'], 'passive'],
  'out' => [createFile(1, &POSIX::O_WRONLY), ['struct'], 'passive'],
  'err' => [createFile(2, &POSIX::O_WRONLY), ['struct'], 'passive'],
  'argv' => [[map { [$_, 'string'] } @ARGV[1 .. $#ARGV]], ['array', 'sys .argv', ['range', 0, $#ARGV - 1], ['string']], 'passive'],
  'asm' => [$ElymasAsm::asm, ['struct'], 'passive'],
};

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;

        push @$data, [$buf, 'string'];
      }, ['func', 'sys .file .read'], '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 .writeall'], 'active'],
    'write' => [sub {
        my ($data) = @_;

        die "file not open" if $$scope->{' fd'}->[0] == -1;

        my $buf = popString($data);

        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 .writestr'], 'active'],
  };

  return $$scope;
}

# sub installIntConstant {
#   my ($name) = @_;
# 
#   my $elymasName = $name;
#   $elymasName =~ s/_//g;
# 
#   $linux->{$elymasName} = [${$POSIX::{$name}}, 'int', 'passive'];
# }

1;