Showing the changes to src/vm/sys/Sysmod.cpp (1 of 6 files). Show all
Unified · Split
| @@ -188,6 +188,15 @@ namespace · 187 unmodified lines | |||
| 188 | throw vm_user_exception{ "Write operation error" }; | 188 | throw vm_user_exception{ "Write operation error" }; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | big_t seek(const std::ios::seekdir start, const big_t offset) | ||
| 192 | { | ||
| 193 | if (_stream == nullptr) | ||
| 194 | throw vm_user_exception{ "Unable to seek on a fifo file descriptor (e.g. stdin, stdout, stderr)" }; | ||
| 195 | |||
| 196 | auto new_offset = _stream->rdbuf()->pubseekoff(static_cast<std::streamoff>(offset), start, _fd_mode); | ||
| 197 | return static_cast<big_t>(new_offset); | ||
| 198 | } | ||
| 199 | |||
| 191 | private: | 200 | private: |
| 192 | const word_t _fd_mode; | 201 | const word_t _fd_mode; |
| 193 | vm_string_t *_fd_path; | 202 | vm_string_t *_fd_path; |
| @@ -218,6 +227,21 @@ namespace · 24 unmodified lines | |||
| 218 | 227 | ||
| 219 | return om; | 228 | return om; |
| 220 | } | 229 | } |
| 230 | |||
| 231 | std::ios::seekdir convert_to_seekdir(const word_t start) | ||
| 232 | { | ||
| 233 | switch (start) | ||
| 234 | { | ||
| 235 | case Sys_SEEKSTART: | ||
| 236 | return std::ios::beg; | ||
| 237 | case Sys_SEEKRELA: | ||
| 238 | return std::ios::cur; | ||
| 239 | case Sys_SEEKEND: | ||
| 240 | return std::ios::end; | ||
| 241 | default: | ||
| 242 | throw vm_user_exception{ "Invalid seek mode" }; | ||
| 243 | } | ||
| 244 | } | ||
| 221 | } | 245 | } |
| 222 | 246 | ||
| 223 | void | 247 | void |
| @@ -612,7 +636,6 @@ Sys_read(vm_registers_t &r, vm_t &vm) · 388 unmodified lines | |||
| 612 | auto &fp = r.stack.peek_frame()->base<F_Sys_read>(); | 636 | auto &fp = r.stack.peek_frame()->base<F_Sys_read>(); |
| 613 | 637 | ||
| 614 | const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf); | 638 | const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf); |
| 615 | assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes); | ||
| 616 | 639 | ||
| 617 | auto n = fp.n; | 640 | auto n = fp.n; |
| 618 | if (buffer == nullptr || n <= 0) | 641 | if (buffer == nullptr || n <= 0) |
| @@ -621,11 +644,16 @@ Sys_read(vm_registers_t &r, vm_t &vm) · 2 unmodified lines | |||
| 621 | return; | 644 | return; |
| 622 | } | 645 | } |
| 623 | 646 | ||
| 647 | assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes); | ||
| 648 | |||
| 624 | // [SPEC] Supplying a size greater than the buffer length is | 649 | // [SPEC] Supplying a size greater than the buffer length is |
| 625 | // equivalent to indicating the entire buffer should be filled. | 650 | // equivalent to indicating the entire buffer should be filled. |
| 626 | n = std::min(n, buffer->get_length()); | 651 | n = std::min(n, buffer->get_length()); |
| 627 | 652 | ||
| 628 | auto fd_alloc = vm_alloc_t::from_allocation(fp.fd); | 653 | auto fd_alloc = vm_alloc_t::from_allocation(fp.fd); |
| 654 | if (fd_alloc == nullptr) | ||
| 655 | throw dereference_nil{ "Read from file descriptor" }; | ||
| 656 | |||
| 629 | assert(fd_alloc->alloc_type == T_FD); | 657 | assert(fd_alloc->alloc_type == T_FD); |
| 630 | 658 | ||
| 631 | auto fd = fd_alloc->get_allocation<vm_fd_t>(); | 659 | auto fd = fd_alloc->get_allocation<vm_fd_t>(); |
| @@ -650,7 +678,16 @@ void · 18 unmodified lines | |||
| 650 | Sys_seek(vm_registers_t &r, vm_t &vm) | 678 | Sys_seek(vm_registers_t &r, vm_t &vm) |
| 651 | { | 679 | { |
| 652 | auto &fp = r.stack.peek_frame()->base<F_Sys_seek>(); | 680 | auto &fp = r.stack.peek_frame()->base<F_Sys_seek>(); |
| 653 | throw vm_system_exception{ "Instruction not implemented" }; | 681 | |
| 682 | auto fd_alloc = vm_alloc_t::from_allocation(fp.fd); | ||
| 683 | if (fd_alloc == nullptr) | ||
| 684 | throw dereference_nil{ "Seek in file descriptor" }; | ||
| 685 | |||
| 686 | assert(fd_alloc->alloc_type == T_FD); | ||
| 687 | auto fd = fd_alloc->get_allocation<vm_fd_t>(); | ||
| 688 | |||
| 689 | const auto start = convert_to_seekdir(fp.start); | ||
| 690 | *fp.ret = fd->seek(start, fp.off); | ||
| 654 | } | 691 | } |
| 655 | 692 | ||
| 656 | void | 693 | void |
| @@ -814,7 +851,19 @@ void · 157 unmodified lines | |||
| 814 | Sys_utfbytes(vm_registers_t &r, vm_t &vm) | 851 | Sys_utfbytes(vm_registers_t &r, vm_t &vm) |
| 815 | { | 852 | { |
| 816 | auto &fp = r.stack.peek_frame()->base<F_Sys_utfbytes>(); | 853 | auto &fp = r.stack.peek_frame()->base<F_Sys_utfbytes>(); |
| 817 | throw vm_system_exception{ "Instruction not implemented" }; | 854 | const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf); |
| 855 | |||
| 856 | const auto n = fp.n; | ||
| 857 | if (buffer == nullptr || n > buffer->get_length()) | ||
| 858 | throw out_of_range_memory{}; | ||
| 859 | |||
| 860 | assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes); | ||
| 861 | |||
| 862 | auto raw_buffer = reinterpret_cast<uint8_t *>(buffer->at(0)); | ||
| 863 | |||
| 864 | const auto len = utf8::count_codepoints(raw_buffer, n); | ||
| 865 | *fp.ret = static_cast<word_t>(len.byte_count); | ||
| 866 | assert(*fp.ret <= n && "Code points should not exceed number of bytes processed"); | ||
| 818 | } | 867 | } |
| 819 | 868 | ||
| 820 | void | 869 | void |
| @@ -830,7 +879,6 @@ Sys_write(vm_registers_t &r, vm_t &vm) · 9 unmodified lines | |||
| 830 | auto &fp = r.stack.peek_frame()->base<F_Sys_write>(); | 879 | auto &fp = r.stack.peek_frame()->base<F_Sys_write>(); |
| 831 | 880 | ||
| 832 | const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf); | 881 | const auto buffer = vm_alloc_t::from_allocation<vm_array_t>(fp.buf); |
| 833 | assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes); | ||
| 834 | 882 | ||
| 835 | auto n = fp.n; | 883 | auto n = fp.n; |
| 836 | if (buffer == nullptr || n <= 0) | 884 | if (buffer == nullptr || n <= 0) |
| @@ -839,11 +887,16 @@ Sys_write(vm_registers_t &r, vm_t &vm) · 2 unmodified lines | |||
| 839 | return; | 887 | return; |
| 840 | } | 888 | } |
| 841 | 889 | ||
| 890 | assert(buffer->get_element_type()->size_in_bytes == intrinsic_type_desc::type<byte_t>()->size_in_bytes); | ||
| 891 | |||
| 842 | // [SPEC] Supplying a size greater than the buffer length is | 892 | // [SPEC] Supplying a size greater than the buffer length is |
| 843 | // equivalent to indicating the entire buffer should be written. | 893 | // equivalent to indicating the entire buffer should be written. |
| 844 | n = std::min(n, buffer->get_length()); | 894 | n = std::min(n, buffer->get_length()); |
| 845 | 895 | ||
| 846 | auto fd_alloc = vm_alloc_t::from_allocation(fp.fd); | 896 | auto fd_alloc = vm_alloc_t::from_allocation(fp.fd); |
| 897 | if (fd_alloc == nullptr) | ||
| 898 | throw dereference_nil{ "Write to file descriptor" }; | ||
| 899 | |||
| 847 | assert(fd_alloc->alloc_type == T_FD); | 900 | assert(fd_alloc->alloc_type == T_FD); |
| 848 | 901 | ||
| 849 | auto fd = fd_alloc->get_allocation<vm_fd_t>(); | 902 | auto fd = fd_alloc->get_allocation<vm_fd_t>(); |