Add string input interrupt from STDIN
This commit is contained in:
@@ -137,5 +137,8 @@ the first argument
|
|||||||
- `2` put value of register A as hexadecimal integer on stdout
|
- `2` put value of register A as hexadecimal integer on stdout
|
||||||
- `3` put the string pointed at by register A for the amount of characters
|
- `3` put the string pointed at by register A for the amount of characters
|
||||||
defined by register B on stdout
|
defined by register B on stdout
|
||||||
- [4..4] Input from STDIN
|
- [4..5] Input from STDIN
|
||||||
- `4` get a single ASCII character from STDIN and store it in register A
|
- `4` get a single ASCII character from STDIN and store it in register A
|
||||||
|
- `5` get a string of a maximum length determined by register B and store it
|
||||||
|
in the address specified by register A. After execution register B will
|
||||||
|
contain the number of characters actually read.
|
||||||
@@ -88,12 +88,22 @@ seti %A $900;
|
|||||||
seti %B $4;
|
seti %B $4;
|
||||||
int $3;
|
int $3;
|
||||||
|
|
||||||
# Jump over the interrupt
|
# Call a function
|
||||||
call noop_function;
|
call noop_function;
|
||||||
|
|
||||||
# Echo a character
|
# Echo a character
|
||||||
int $4;
|
int $4;
|
||||||
int $0;
|
int $0;
|
||||||
|
|
||||||
|
seti %A $10; # newline
|
||||||
|
int $0;
|
||||||
|
|
||||||
|
# Echo a string
|
||||||
|
seti %A $0;
|
||||||
|
seti %B $10;
|
||||||
|
int $5;
|
||||||
|
int $3;
|
||||||
|
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
noop_function:
|
noop_function:
|
||||||
|
|||||||
@@ -39,6 +39,12 @@ namespace Execute
|
|||||||
InterruptIndexOutOfRange(int const index);
|
InterruptIndexOutOfRange(int const index);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OutOfMemory : public RuntimeError
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OutOfMemory(int const memoryLocation, int const memorySize);
|
||||||
|
};
|
||||||
|
|
||||||
namespace Internal
|
namespace Internal
|
||||||
{
|
{
|
||||||
class BadValueType : public RuntimeError
|
class BadValueType : public RuntimeError
|
||||||
|
|||||||
@@ -41,6 +41,15 @@ namespace Execute
|
|||||||
message += " is out of range";
|
message += " is out of range";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
OutOfMemory::OutOfMemory(int const memoryLocation, int const memorySize)
|
||||||
|
{
|
||||||
|
message = "Attempted interaction at memory location ";
|
||||||
|
message += std::to_string(memoryLocation);
|
||||||
|
message += " with size ";
|
||||||
|
message += std::to_string(memorySize);
|
||||||
|
message += " failed";
|
||||||
|
}
|
||||||
|
|
||||||
namespace Internal
|
namespace Internal
|
||||||
{
|
{
|
||||||
BadValueType::BadValueType()
|
BadValueType::BadValueType()
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <execute/error.hpp>
|
||||||
#include <execute/interrupts.hpp>
|
#include <execute/interrupts.hpp>
|
||||||
|
|
||||||
namespace Execute
|
namespace Execute
|
||||||
@@ -18,6 +19,11 @@ namespace Execute
|
|||||||
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory)
|
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory)
|
||||||
{
|
{
|
||||||
unsigned const end = registers.A + registers.B;
|
unsigned const end = registers.A + registers.B;
|
||||||
|
if (end >= memory.size())
|
||||||
|
{
|
||||||
|
throw OutOfMemory(registers.A, registers.B);
|
||||||
|
}
|
||||||
|
|
||||||
for(unsigned i = registers.A; i < end; ++i)
|
for(unsigned i = registers.A; i < end; ++i)
|
||||||
{
|
{
|
||||||
std::putc(memory[i], stdout);
|
std::putc(memory[i], stdout);
|
||||||
@@ -29,7 +35,49 @@ namespace Execute
|
|||||||
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory)
|
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory)
|
||||||
{
|
{
|
||||||
registers.A = std::getchar();
|
registers.A = std::getchar();
|
||||||
|
if (registers.A == '\n')
|
||||||
|
{
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
while(std::getchar() != '\n');
|
||||||
|
},
|
||||||
|
// 11 get string from STDIN
|
||||||
|
[](Execute::Registers & registers, std::vector<std::uint8_t> & memory)
|
||||||
|
{
|
||||||
|
if (registers.B <= 0)
|
||||||
|
{
|
||||||
|
registers.B = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (registers.A < 0 || static_cast<unsigned>(registers.A + registers.B) >= memory.size())
|
||||||
|
{
|
||||||
|
throw OutOfMemory(registers.A, registers.B);
|
||||||
|
}
|
||||||
|
|
||||||
|
int charactersRead = 0;
|
||||||
|
bool newlineRead = false;
|
||||||
|
while(charactersRead < registers.B)
|
||||||
|
{
|
||||||
|
char result = std::getchar();
|
||||||
|
if (result == '\n')
|
||||||
|
{
|
||||||
|
newlineRead = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
memory[registers.A + charactersRead] = result;
|
||||||
|
++charactersRead;
|
||||||
|
}
|
||||||
|
|
||||||
|
registers.B = charactersRead;
|
||||||
|
|
||||||
|
if (!newlineRead)
|
||||||
|
{
|
||||||
|
while(std::getchar() != '\n');
|
||||||
|
}
|
||||||
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user