MXVM 1.8.1
Virtual Machine, Compiler, and Pascal Frontend
Loading...
Searching...
No Matches
io.cpp
Go to the documentation of this file.
1
6#include <chrono>
7#include <cstdint>
8#include <cstdlib>
9#include <ctime>
10#include <mxvm/icode.hpp>
11#include <mxvm/instruct.hpp>
12#include <string>
13#include <vector>
14
15extern "C" void mxvm_io_fopen(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
16 if (operand.size() == 2) {
17 std::string &filename = operand[0].op;
18 std::string &mode = operand[1].op;
19 if (program->isVariable(filename)) {
20 mxvm::Variable &v = program->getVariable(filename);
22 throw mx::Exception("Requires string variable type for fopen.\n");
23 }
24 filename = v.var_value.str_value;
25 } else {
26 throw mx::Exception("Variable required for fopen.");
27 }
28 if (program->isVariable(mode)) {
29 mxvm::Variable &v = program->getVariable(mode);
31 throw mx::Exception("Requires string variable type for fopen.\n");
32 }
33 mode = v.var_value.str_value;
34 } else {
35 throw mx::Exception("Variable required for fopen.");
36 }
37 program->vars["%rax"].type = mxvm::VarType::VAR_POINTER;
38 program->vars["%rax"].var_name = "%rax";
39 program->vars["%rax"].var_value.ptr_value = (void *)fopen(filename.c_str(), mode.c_str());
40 } else {
41 throw mx::Exception("Error invalid types for fopen.\n");
42 }
43}
44
45extern "C" void mxvm_io_fprintf(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
46 if (operand.size() < 2) {
47 throw mx::Exception("Requires at least two arguments for fprintf.");
48 }
49 if (program->isVariable(operand[0].op)) {
50 std::vector<mxvm::Variable *> v;
51 for (size_t i = 2; i < operand.size(); ++i) {
52 if (program->isVariable(operand[i].op)) {
53 mxvm::Variable &varval = program->getVariable(operand[i].op);
54 v.push_back(&varval);
55 } else {
56 if (operand[i].type == mxvm::OperandType::OP_CONSTANT) {
58 v.push_back(&val);
59 }
60 }
61 }
62 if (program->isVariable(operand[1].op)) {
63 mxvm::Variable &fmtv = program->getVariable(operand[1].op);
64 if (fmtv.type != mxvm::VarType::VAR_STRING) {
65 throw mx::Exception("fprintf requires format to be a string.");
66 }
67 std::string value = program->printFormatted(fmtv.var_value.str_value, v, false);
68 mxvm::Variable &vx = program->getVariable(operand[0].op);
70 FILE *fptr = reinterpret_cast<FILE *>(vx.var_value.ptr_value);
71 fprintf(fptr, "%s", value.c_str());
72 }
73 } else {
74 throw mx::Exception("fprintf requires format to be a variable");
75 }
76 } else {
77 throw mx::Exception("fprintf requires first argument to be valid variable found: " + operand[0].op);
78 }
79}
80
81extern "C" void mxvm_io_fclose(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
82 if (operand.size() != 1) {
83 throw mx::Exception("fclose requires a single file pointer argument.");
84 }
85 std::string &file_var = operand[0].op;
86 if (!program->isVariable(file_var)) {
87 throw mx::Exception("fclose argument must be a variable (file pointer).");
88 }
89 mxvm::Variable &file_v = program->getVariable(file_var);
90 if (file_v.type != mxvm::VarType::VAR_POINTER) {
91 throw mx::Exception("fclose argument must be a pointer variable.");
92 }
93 FILE *fp = reinterpret_cast<FILE *>(file_v.var_value.ptr_value);
94 int result = fclose(fp);
95 program->vars["%rax"].type = mxvm::VarType::VAR_INTEGER;
96 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_INTEGER;
97 program->vars["%rax"].var_value.int_value = result;
98}
99
100extern "C" void mxvm_io_fsize(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
101 if (operand.size() != 1) {
102 throw mx::Exception("fsize requires a single file pointer argument.");
103 }
104 std::string &file_var = operand[0].op;
105 if (!program->isVariable(file_var)) {
106 throw mx::Exception("fsize argument must be a variable pointer.");
107 }
108 mxvm::Variable &file_v = program->getVariable(file_var);
109 if (file_v.type != mxvm::VarType::VAR_POINTER) {
110 throw mx::Exception("fsize argument must be a pointer variable.");
111 }
112 FILE *fptr = reinterpret_cast<FILE *>(file_v.var_value.ptr_value);
113 if (fptr == NULL) {
114 throw mx::Exception("Error pointer handle must not be null");
115 }
116 fseek(fptr, 0, SEEK_END);
117 size_t result = ftell(fptr);
118 fseek(fptr, 0, SEEK_SET);
119 program->vars["%rax"].type = mxvm::VarType::VAR_INTEGER;
120 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_INTEGER;
121 program->vars["%rax"].var_value.int_value = result;
122}
123
124extern "C" void mxvm_io_fread(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
125 if (operand.size() != 4) {
126 throw mx::Exception("fread requires four arguments.");
127 }
128 std::string &buf_var = operand[0].op;
129 if (!program->isVariable(buf_var)) {
130 throw mx::Exception("fread argument must be a variable pointer.");
131 }
132 mxvm::Variable &buf_v = program->getVariable(buf_var);
133 if (buf_v.type != mxvm::VarType::VAR_POINTER) {
134 throw mx::Exception("fread argument must be a pointer variable.");
135 }
136
137 mxvm::Variable vsize, vcount, file_ptr;
138 vsize = program->variableFromOperand(operand[1]);
139 vcount = program->variableFromOperand(operand[2]);
140 file_ptr = program->variableFromOperand(operand[3]);
141
143 throw mx::Exception("Argument type mismatch expected integer for fread");
144 }
145 if (file_ptr.type != mxvm::VarType::VAR_POINTER && file_ptr.type != mxvm::VarType::VAR_EXTERN) {
146 throw mx::Exception("Final argument for fread requires pointer");
147 }
148 FILE *fptr = reinterpret_cast<FILE *>(file_ptr.var_value.ptr_value);
149 size_t result = fread(buf_v.var_value.ptr_value, vsize.var_value.int_value, vcount.var_value.int_value, fptr);
150 program->vars["%rax"].type = mxvm::VarType::VAR_INTEGER;
151 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_INTEGER;
152 program->vars["%rax"].var_value.int_value = result;
153}
154
155extern "C" void mxvm_io_fwrite(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
156 if (operand.size() != 4) {
157 throw mx::Exception("fwrite requires four arguments.");
158 }
159 std::string &buf_var = operand[0].op;
160 if (!program->isVariable(buf_var)) {
161 throw mx::Exception("fwrite argument must be a variable pointer.");
162 }
163 mxvm::Variable &buf_v = program->getVariable(buf_var);
164 if (buf_v.type != mxvm::VarType::VAR_POINTER) {
165 throw mx::Exception("fwrite argument must be a pointer variable.");
166 }
167
168 mxvm::Variable vsize, vcount, file_ptr;
169 vsize = program->variableFromOperand(operand[1]);
170 vcount = program->variableFromOperand(operand[2]);
171 file_ptr = program->variableFromOperand(operand[3]);
172
174 throw mx::Exception("Argument type mismatch expected integer for fwrite");
175 }
176 if (file_ptr.type != mxvm::VarType::VAR_POINTER && file_ptr.type != mxvm::VarType::VAR_EXTERN) {
177 throw mx::Exception("Final argument for fwrite requires pointer");
178 }
179 FILE *fptr = reinterpret_cast<FILE *>(file_ptr.var_value.ptr_value);
180 size_t result = fwrite(buf_v.var_value.ptr_value, vsize.var_value.int_value, vcount.var_value.int_value, fptr);
181 program->vars["%rax"].type = mxvm::VarType::VAR_INTEGER;
182 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_INTEGER;
183 program->vars["%rax"].var_value.int_value = result;
184}
185
186extern "C" void mxvm_io_fseek(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
187 if (operand.size() != 3) {
188 throw mx::Exception("fseek requires three arguments got: " + std::to_string(operand.size()));
189 }
190 std::string &buf_var = operand[0].op;
191 if (!program->isVariable(buf_var)) {
192 throw mx::Exception("fseek argument must be a variable found: " + buf_var);
193 }
194 mxvm::Variable &buf_v = program->getVariable(buf_var);
195 if (buf_v.type != mxvm::VarType::VAR_POINTER) {
196 throw mx::Exception("fseek argument must be a pointer variable.");
197 }
198
199 mxvm::Variable vsize, vcount, file_ptr;
200 file_ptr = program->variableFromOperand(operand[0]);
201 vsize = program->variableFromOperand(operand[1]);
202 vcount = program->variableFromOperand(operand[2]);
203
205 throw mx::Exception("Argument type mismatch expec ted integer for fread");
206 }
207 if (file_ptr.type != mxvm::VarType::VAR_POINTER && file_ptr.type != mxvm::VarType::VAR_EXTERN) {
208 throw mx::Exception("Final argument for fread requires pointer");
209 }
210 FILE *fptr = reinterpret_cast<FILE *>(file_ptr.var_value.ptr_value);
211 int result = fseek(fptr, vsize.var_value.int_value, vcount.var_value.int_value);
212 program->vars["%rax"].type = mxvm::VarType::VAR_INTEGER;
213 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_INTEGER;
214 program->vars["%rax"].var_value.int_value = result;
215}
216
217extern "C" void mxvm_io_rand_number(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
218 if (operand.size() != 1) {
219 throw mx::Exception("rand_number requires one argument (size).");
220 }
221 int64_t rsize = 1;
222 if (program->isVariable(operand[0].op)) {
223 mxvm::Variable &vsize = program->getVariable(operand[0].op);
224 if (vsize.type != mxvm::VarType::VAR_INTEGER) {
225 throw mx::Exception("rand_number argument must be integer (size).");
226 }
227 rsize = vsize.var_value.int_value;
228 } else {
229
230 if (operand[0].type == mxvm::OperandType::OP_CONSTANT)
231 rsize = std::stoll(operand[0].op, nullptr, 0);
232 else
233 throw mx::Exception("rand_number expected variable or constant: " + operand[0].op);
234 }
235 if (rsize <= 0) {
236 throw mx::Exception("rand_number: size must be positive, got " + std::to_string(rsize));
237 }
238 int result = std::rand() % rsize;
239 program->vars["%rax"].type = mxvm::VarType::VAR_INTEGER;
240 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_INTEGER;
241 program->vars["%rax"].var_value.int_value = result;
242}
243
244extern "C" void mxvm_io_seed_random(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
245 auto now = std::chrono::high_resolution_clock::now().time_since_epoch().count();
246 uint64_t mixed = static_cast<uint64_t>(now);
247 mixed ^= static_cast<uint64_t>(reinterpret_cast<std::uintptr_t>(program));
248 mixed ^= (mixed >> 33);
249 mixed *= 0xff51afd7ed558ccdULL;
250 mixed ^= (mixed >> 33);
251 mixed *= 0xc4ceb9fe1a85ec53ULL;
252 mixed ^= (mixed >> 33);
253 std::srand(static_cast<unsigned int>(mixed));
254 program->vars["%rax"].type = mxvm::VarType::VAR_INTEGER;
255 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_INTEGER;
256 program->vars["%rax"].var_value.int_value = 0;
257
258}
259
260extern "C" void mxvm_io_feof(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
261 if (operand.size() != 1) {
262 throw mx::Exception("feof requires one file pointer argument.");
263 }
264 std::string &file_var = operand[0].op;
265 if (!program->isVariable(file_var)) {
266 throw mx::Exception("feof argument must be a variable (file pointer).");
267 }
268 mxvm::Variable &file_v = program->getVariable(file_var);
269 if (file_v.type != mxvm::VarType::VAR_POINTER) {
270 throw mx::Exception("feof argument must be a pointer variable.");
271 }
272 FILE *fp = reinterpret_cast<FILE *>(file_v.var_value.ptr_value);
273 int result = feof(fp) ? 1 : 0;
274 program->vars["%rax"].type = mxvm::VarType::VAR_INTEGER;
275 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_INTEGER;
276 program->vars["%rax"].var_value.int_value = result;
277}
278
279extern "C" void mxvm_io_mxvm_fgets(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
280 if (operand.size() != 1) {
281 throw mx::Exception("mxvm_fgets requires one file pointer argument.");
282 }
283 std::string &file_var = operand[0].op;
284 if (!program->isVariable(file_var)) {
285 throw mx::Exception("fgets argument must be a variable (file pointer).");
286 }
287 mxvm::Variable &file_v = program->getVariable(file_var);
288 if (file_v.type != mxvm::VarType::VAR_POINTER) {
289 throw mx::Exception("fgets argument must be a pointer variable.");
290 }
291 FILE *fp = reinterpret_cast<FILE *>(file_v.var_value.ptr_value);
292 char buf[4096];
293 char *res = fgets(buf, sizeof(buf), fp);
294 if (res) {
295 size_t len = strlen(buf);
296 if (len > 0 && buf[len - 1] == '\n')
297 buf[len - 1] = '\0';
298 char *str = strdup(buf);
299 program->vars["%rax"].type = mxvm::VarType::VAR_STRING;
300 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_STRING;
301 program->vars["%rax"].var_value.str_value = str;
302 } else {
303 program->vars["%rax"].type = mxvm::VarType::VAR_STRING;
304 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_STRING;
305 program->vars["%rax"].var_value.str_value = strdup("");
306 }
307}
308
309extern "C" void mxvm_io_fputs(mxvm::Program *program, std::vector<mxvm::Operand> &operand) {
310 if (operand.size() != 2) {
311 throw mx::Exception("fputs requires two arguments (string, file).");
312 }
313 std::string str_val;
314 if (program->isVariable(operand[0].op)) {
315 mxvm::Variable &v = program->getVariable(operand[0].op);
317 str_val = v.var_value.str_value;
318 } else {
319 throw mx::Exception("fputs first argument must be a string variable.");
320 }
321 } else {
322 throw mx::Exception("fputs first argument must be a variable.");
323 }
324 std::string &file_var = operand[1].op;
325 if (!program->isVariable(file_var)) {
326 throw mx::Exception("fputs second argument must be a variable (file pointer).");
327 }
328 mxvm::Variable &file_v = program->getVariable(file_var);
329 if (file_v.type != mxvm::VarType::VAR_POINTER) {
330 throw mx::Exception("fputs second argument must be a pointer variable.");
331 }
332 FILE *fp = reinterpret_cast<FILE *>(file_v.var_value.ptr_value);
333 int result = fputs(str_val.c_str(), fp);
334 program->vars["%rax"].type = mxvm::VarType::VAR_INTEGER;
335 program->vars["%rax"].var_value.type = mxvm::VarType::VAR_INTEGER;
336 program->vars["%rax"].var_value.int_value = result;
337}
General-purpose exception with errno-aware factory method.
Definition exception.hpp:38
std::unordered_map< std::string, Variable > vars
variable symbol table
Definition icode.hpp:193
Complete MXVM program: instruction interpreter and native x64 code generator.
Definition icode.hpp:212
Variable createTempVariable(VarType type, const std::string &value)
Create a temporary unnamed variable with the given type and value.
Variable & getVariable(const std::string &name)
Look up a variable by name, searching local scope then global.
bool isVariable(const std::string &name)
Check whether a variable exists in local or global scope.
Variable variableFromOperand(const Operand &op)
Resolve an Operand to its corresponding Variable.
std::string printFormatted(const std::string &format, const std::vector< Variable * > &args, bool output=true)
Format and optionally print a printf-style format string with variable arguments.
Intermediate code representation, execution engine, and native x64 code generation (SysV + Win64).
Instruction set enum, operand/instruction structs, variable types, and Variable/Variable_Value defini...
void mxvm_io_seed_random(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:244
void mxvm_io_fsize(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:100
void mxvm_io_feof(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:260
void mxvm_io_fwrite(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:155
void mxvm_io_fopen(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:15
void mxvm_io_rand_number(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:217
void mxvm_io_fread(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:124
void mxvm_io_fprintf(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:45
void mxvm_io_fputs(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:309
void mxvm_io_fclose(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:81
void mxvm_io_mxvm_fgets(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:279
void mxvm_io_fseek(mxvm::Program *program, std::vector< mxvm::Operand > &operand)
Definition io.cpp:186
std::string str_value
Definition instruct.hpp:211
A named variable with type, value, and optional object association.
Definition instruct.hpp:292
Variable_Value var_value
Definition instruct.hpp:295