Phasor 3.3.0
Stack VM based Programming Language
Loading...
Searching...
No Matches
system.cpp
Go to the documentation of this file.
1#include "StdLib.hpp"
2#include <atomic>
3#include <chrono>
4#include <thread>
5#include <print>
6#include <userconsent.h>
7#if defined(_MSC_VER)
8#include <vcruntime_startup.h>
9#endif
10
11#include "core/system.h"
12
13#if defined(_WIN32)
14#include <windows.h>
15#else
16#include <unistd.h>
17#endif
18
19namespace Phasor
20{
21
22#ifdef _MSC_VER
23#pragma warning(push)
24#pragma warning(disable: 4996)
25#endif
26
28{
29#ifndef SANDBOXED
35 vm->registerNativeFunction("sys_fork_detached", StdLib::sys_fork_detached);
43#else
44 auto stub = [](const std::vector<Value> &, VM *) { return Value(); };
45 vm->registerNativeFunction("sys_os", [](const std::vector<Value> &, VM *) { return "sandbox"; });
46 vm->registerNativeFunction("sys_get_memory", stub);
47 vm->registerNativeFunction("sys_pid", stub);
48 vm->registerNativeFunction("isatty", stub);
49 if (!std::getenv("PHASOR_NO_ENV")) {
50 if (prompt_consent("Standard library", EConsentVolition::Might, "use", "system environment variables")) {
54 } else {
55 vm->registerNativeFunction("sys_env", stub);
56 vm->registerNativeFunction("sys_argv", stub);
57 vm->registerNativeFunction("sys_argc", stub);
58 }
59 }
60#endif
65}
66
67#ifdef _MSC_VER
68#pragma warning(pop)
69#endif
70
71double StdLib::sys_time(const std::vector<Value> &args, VM *)
72{
73 checkArgCount(args, 0, "time");
74 auto now = std::chrono::steady_clock::now();
75 auto duration = now.time_since_epoch();
76 double millis = std::chrono::duration<double, std::milli>(duration).count();
77 return millis;
78}
79
80Value StdLib::sys_time_formatted(const std::vector<Value> &args, VM *)
81{
82 checkArgCount(args, 1, "timef");
83 std::string format = args[0].asString();
84
85 auto now = std::chrono::system_clock::now();
86 std::time_t t = std::chrono::system_clock::to_time_t(now);
87
88 std::tm tm{};
89#if defined(_WIN32)
90 localtime_s(&tm, &t);
91#else
92 localtime_r(&t, &tm);
93#endif
94
95 char buffer[256];
96 if (std::strftime(buffer, sizeof(buffer), format.c_str(), &tm) == 0)
97 {
98 return Value(" ");
99 }
100
101 return std::string(buffer);
102}
103
104Value StdLib::sys_sleep(const std::vector<Value> &args, VM *)
105{
106 checkArgCount(args, 1, "sleep");
107 int64_t ms = args[0].asInt();
108 std::this_thread::sleep_for(std::chrono::milliseconds(ms));
109 return Value(" ");
110}
111
112Value StdLib::sys_env(const std::vector<Value> &args, VM *)
113{
114 checkArgCount(args, 1, "sys_env");
115 std::string key = args[0].asString();
116 std::string value;
117 dupenv_ret result = dupenv(value, key.c_str());
118 if (result == dupenv_ret::NotFound) return false;
119 else if (result == dupenv_ret::Success) return value;
120 else return Value();
121}
122
123Value StdLib::sys_argv(const std::vector<Value> &args, VM *)
124{
125 checkArgCount(args, 1, "sys_argv");
126 int64_t index = args[0].asInt();
127 if (argv)
128 if (argc > index && index >= 0)
129 return argv[index];
130 else
131 throw std::runtime_error("sys_argv: Index out of bounds: " + std::to_string(index));
132 else
133 return Value();
134}
135
136int64_t StdLib::sys_argc(const std::vector<Value> &args, VM *)
137{
138 checkArgCount(args, 0, "sys_argc");
139 return static_cast<int64_t>(argc);
140}
141
142Value StdLib::sys_shutdown(const std::vector<Value> &args, VM *vm)
143{
144 checkArgCount(args, 1, "shutdown");
145 int ret = static_cast<int>(args[0].asInt());
146 vm->setStatus(ret);
147 throw VM::Halt();
148}
149
150#ifndef SANDBOXED
151
152std::string StdLib::sys_os(const std::vector<Value> &args, VM *)
153{
154 checkArgCount(args, 0, "sys_os");
155#if defined(_WIN32)
156 return "win32";
157#elif defined(__linux__)
158 return "Linux";
159#elif defined(__APPLE__)
160 return "Darwin";
161#elif defined(__FreeBSD__)
162 return "FreeBSD";
163#elif defined(__unix__)
164 return "UNIX";
165#else
166 return "Unknown";
167#endif
168}
169
170int64_t StdLib::sys_get_free_memory(const std::vector<Value> &args, VM *)
171{
172 checkArgCount(args, 0, "sys_get_memory");
173 return static_cast<int64_t>(PHASORstd_sys_getAvailableMemory());
174}
175
176Value StdLib::sys_wait_for_input(const std::vector<Value> &args, VM *vm)
177{
178 checkArgCount(args, 0, "wait_for_input");
179 io_gets({}, vm);
180 return Value("");
181}
182
183Value StdLib::sys_shell(const std::vector<Value> &args, VM *vm)
184{
185 checkArgCount(args, 1, "sys_shell");
186 return vm->regRun(OpCode::SYSTEM_R, args[0]);
187}
188
189int64_t StdLib::sys_fork(const std::vector<Value> &args, VM *)
190{
191 checkArgCount(args, 1, "sys_fork", true);
192 const char *executable = args[0].c_str();
193 int argc = (int)args.size() - 1;
194 std::vector<char *> v_argv(argc);
195 for (int i = 0; i < argc; ++i)
196 {
197 v_argv[i] = const_cast<char *>(args[i + 1].c_str());
198 }
199 return static_cast<int64_t>(PHASORstd_sys_run(executable, argc, v_argv.data()));
200}
201
202int64_t StdLib::sys_fork_detached(const std::vector<Value> &args, VM *)
203{
204 checkArgCount(args, 1, "sys_fork_detached", true);
205 const char *executable = args[0].c_str();
206 int argc = (int)args.size() - 1;
207 std::vector<char *> v_argv(argc);
208 for (int i = 0; i < argc; ++i)
209 {
210 v_argv[i] = const_cast<char *>(args[i + 1].c_str());
211 }
212 return static_cast<int64_t>(PHASORstd_sys_run_detached(executable, argc, v_argv.data()));
213}
214
215Value StdLib::sys_crash(const std::vector<Value> &args, VM *vm)
216{
217 checkArgCount(args, 1, "error", true);
218 vm->reset();
219 vm->setStatus(-1);
220 throw std::runtime_error(args[0].asString());
221}
222
223Value StdLib::sys_reset(const std::vector<Value> &args, VM *vm)
224{
225 checkArgCount(args, 0, "reset");
226 vm->reset();
227 return Value();
228}
229
230int64_t StdLib::sys_pid(const std::vector<Value> &args, VM *)
231{
232 checkArgCount(args, 0, "sys_pid");
233#if defined(_WIN32)
234 return static_cast<int64_t>(GetCurrentProcessId());
235#else
236 return static_cast<int64_t>(getpid());
237#endif
238}
239
240Value StdLib::sys_isatty(const std::vector<Value> &args, VM *)
241{
242 checkArgCount(args, 0, "isatty");
243#ifdef _WIN32
244 return _isatty(_fileno(stdin));
245#else
246 return isatty(fileno(stdin));
247#endif
248}
249
250#endif
251} // namespace Phasor
static Value sys_env(const std::vector< Value > &args, VM *vm)
Get the current environment variables.
Definition system.cpp:112
static Value sys_reset(const std::vector< Value > &args, VM *vm)
Reset the VM.
Definition system.cpp:223
static char ** argv
Command line arguments.
Definition StdLib.hpp:47
static Value sys_crash(const std::vector< Value > &args, VM *vm)
Crash the VM / Program.
Definition system.cpp:215
static void checkArgCount(const std::vector< Value > &args, size_t minimumArguments, const std::string &name, bool allowMoreArguments=false)
Definition StdLib.cpp:44
static int64_t sys_pid(const std::vector< Value > &args, VM *vm)
Get the current process ID.
Definition system.cpp:230
static Value sys_argv(const std::vector< Value > &args, VM *vm)
Get the current command line arguments.
Definition system.cpp:123
static int argc
Number of command line arguments.
Definition StdLib.hpp:48
static int64_t sys_argc(const std::vector< Value > &args, VM *vm)
Get the current number of command line arguments.
Definition system.cpp:136
static Value sys_wait_for_input(const std::vector< Value > &args, VM *vm)
Wait for input.
Definition system.cpp:176
static void registerSysFunctions(VM *vm)
Definition system.cpp:27
static Value sys_shutdown(const std::vector< Value > &args, VM *vm)
Shutdown the VM.
Definition system.cpp:142
static int64_t sys_get_free_memory(const std::vector< Value > &args, VM *vm)
Get current free memory.
Definition system.cpp:170
static Value sys_shell(const std::vector< Value > &args, VM *vm)
Run a shell command.
Definition system.cpp:183
static Value sys_sleep(const std::vector< Value > &args, VM *vm)
Sleep for a specified amount of time.
Definition system.cpp:104
static dupenv_ret dupenv(std::string &out, const char *name)
Definition StdLib.cpp:15
static int64_t sys_fork(const std::vector< Value > &args, VM *vm)
Run a native program.
Definition system.cpp:189
static std::string sys_os(const std::vector< Value > &args, VM *vm)
Get the current OS.
Definition system.cpp:152
static Value sys_isatty(const std::vector< Value > &args, VM *vm)
Check if the current output is a terminal.
Definition system.cpp:240
static int64_t sys_fork_detached(const std::vector< Value > &args, VM *vm)
Run a native program detached.
Definition system.cpp:202
static Value sys_time_formatted(const std::vector< Value > &args, VM *vm)
Current time formatted.
Definition system.cpp:80
static double sys_time(const std::vector< Value > &args, VM *vm)
Current time.
Definition system.cpp:71
static Value io_gets(const std::vector< Value > &args, VM *vm)
Get string.
Definition io.cpp:121
Throws when the HALT opcode is reached.
Definition VM.hpp:49
Virtual Machine.
Definition VM.hpp:33
void registerNativeFunction(const std::string &name, NativeFunction fn)
Register a native function.
Definition Native.cpp:5
void setStatus(int newStatus)
Set VM exit code.
Definition Utility.cpp:38
Value regRun(OpCode opcode, Args &&...args)
Run an opcode with arguments pre-loaded into registers.
Definition VM.hpp:208
void reset(const bool &resetStack=true, const bool &resetFunctions=true, const bool &resetVariables=true)
Reset the virtual machine.
Definition Utility.cpp:181
A value in the Phasor VM.
Definition Value.hpp:58
The Phasor Programming Language and Runtime.
Definition AST.hpp:12
@ SYSTEM_R
Run an operating system shell command: system(R[rA]).
Definition ISA.hpp:157
size_t PHASORstd_sys_getAvailableMemory(void)
Definition system.c:3
int PHASORstd_sys_run_detached(const char *name, int argc, char **argv)
Definition system.c:90
int PHASORstd_sys_run(const char *name, int argc, char **argv)
Definition system.c:56
bool prompt_consent(const char(&subsystem)[N1], EConsentVolition volition, const char(&verb)[N2], const char(&noun)[N3], bool default_val=false)
Prompt the user for consent.
Definition userconsent.h:56