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#include <phsint.hpp>
11
12#include "core/system.h"
13
14#if defined(_WIN32)
15#include <windows.h>
16#else
17#include <unistd.h>
18#endif
19
20bool consentAskedCLI{false};
22
23bool consentAskedEnv{false};
25
26namespace Phasor
27{
28
29#ifdef _MSC_VER
30#pragma warning(push)
31#pragma warning(disable: 4996)
32#endif
33
35{
36#ifndef SANDBOXED
42 vm->registerNativeFunction("sys_fork_detached", StdLib::sys_fork_detached);
49#else
50 auto stub = [](const std::vector<Value> &, VM *) -> Value { return Value(); };
51 vm->registerNativeFunction("sys_os", [](const std::vector<Value> &, VM *) { return "sandbox"; });
52 vm->registerNativeFunction("sys_get_memory", stub);
53 vm->registerNativeFunction("sys_pid", stub);
54 vm->registerNativeFunction("isatty", stub);
55 if (!std::getenv("PHASOR_NO_ENV")) {
56 vm->registerNativeFunction("sys_env", [] (const std::vector<Value> &v, VM *vm) -> Value {
58 return sys_env(v, vm);
59 }
60 if (!consentAskedEnv) {
61 [[unlikely]]
62 consentGrantedEnv = prompt_consent("Standard library", EConsentVolition::Wants, "use", "environment variables");
63 consentAskedEnv = true;
64 }
65 return Value();
66 });
67 vm->registerNativeFunction("sys_args", [] (const std::vector<Value> &v, VM *vm) {
69 return sys_argc(v, vm);
70 }
71 if (!consentAskedCLI) {
72 [[unlikely]]
73 consentGrantedCLI = prompt_consent("Standard library", EConsentVolition::Wants, "use", "command line arguments");
74 consentAskedCLI = true;
75 }
76 return Value();
77 });
78 }
79#endif
84}
85
86#ifdef _MSC_VER
87#pragma warning(pop)
88#endif
89
90f64 StdLib::sys_time(const std::vector<Value> &args, VM *)
91{
92 checkArgCount(args, 0, "time");
93 auto now = std::chrono::steady_clock::now();
94 auto duration = now.time_since_epoch();
95 f64 millis = std::chrono::duration<f64, std::milli>(duration).count();
96 return millis;
97}
98
99Value StdLib::sys_time_formatted(const std::vector<Value> &args, VM *)
100{
101 checkArgCount(args, 1, "timef");
102 PhsString format = args[0].asString();
103
104 auto now = std::chrono::system_clock::now();
105 std::time_t t = std::chrono::system_clock::to_time_t(now);
106
107 std::tm tm{};
108#if defined(_WIN32)
109 localtime_s(&tm, &t);
110#else
111 localtime_r(&t, &tm);
112#endif
113
114 char buffer[256];
115 if (std::strftime(buffer, sizeof(buffer), format.c_str(), &tm) == 0)
116 {
117 return Value(" ");
118 }
119
120 return PhsString(buffer);
121}
122
123Value StdLib::sys_sleep(const std::vector<Value> &args, VM *)
124{
125 checkArgCount(args, 1, "sleep");
126 i64 ms = args[0].asInt();
127 std::this_thread::sleep_for(std::chrono::milliseconds(ms));
128 return Value(" ");
129}
130
131Value StdLib::sys_env(const std::vector<Value> &args, VM *)
132{
133 checkArgCount(args, 1, "sys_env");
134 PhsString key = args[0].asString();
135 PhsString value;
136 dupenv_ret result = dupenv(value, key.c_str());
137 if (result == dupenv_ret::NotFound) return false;
138 else if (result == dupenv_ret::Success) return value;
139 else return Value();
140}
141
142i64 StdLib::sys_argc(const std::vector<Value> &args, VM *)
143{
144 checkArgCount(args, 0, "sys_args");
145 return static_cast<i64>(argc);
146}
147
148Value StdLib::sys_argv(const std::vector<Value> &args, VM *)
149{
150 checkArgCount(args, 1, "sys_argv");
151 i64 index = args[0].asInt();
152 if (index < 0 || index >= argc) return Value();
153 return argv[index];
154}
155
156Value StdLib::sys_args(const std::vector<Value> &args, VM *)
157{
158 checkArgCount(args, 0, "sys_args");
159 std::vector<Value> arguments;
160 for (int i = 0; i < argc; ++i)
161 {
162 arguments.push_back(Value(argv[i]));
163 }
164 return Value::createArray(std::move(arguments));
165}
166
167Value StdLib::sys_shutdown(const std::vector<Value> &args, VM *vm)
168{
169 checkArgCount(args, 1, "shutdown");
170 int ret = static_cast<int>(args[0].asInt());
171 vm->setStatus(ret);
172 throw VM::Halt();
173}
174
175#ifndef SANDBOXED
176
177PhsString StdLib::sys_os(const std::vector<Value> &args, VM *)
178{
179 checkArgCount(args, 0, "sys_os");
180#if defined(_WIN32)
181 return "win32";
182#elif defined(__linux__)
183 return "Linux";
184#elif defined(__APPLE__)
185 return "Darwin";
186#elif defined(__FreeBSD__)
187 return "FreeBSD";
188#elif defined(__unix__)
189 return "UNIX";
190#else
191 return "Unknown";
192#endif
193}
194
195i64 StdLib::sys_get_free_memory(const std::vector<Value> &args, VM *)
196{
197 checkArgCount(args, 0, "sys_get_memory");
198 return static_cast<i64>(PHASORstd_sys_getAvailableMemory());
199}
200
201Value StdLib::sys_wait_for_input(const std::vector<Value> &args, VM *vm)
202{
203 checkArgCount(args, 0, "wait_for_input");
204 io_gets({}, vm);
205 return Value("");
206}
207
208Value StdLib::sys_shell(const std::vector<Value> &args, VM *vm)
209{
210 checkArgCount(args, 1, "sys_shell");
211 return vm->regRun(OpCode::SYSTEM_R, args[0]);
212}
213
214i64 StdLib::sys_fork(const std::vector<Value> &args, VM *)
215{
216 checkArgCount(args, 1, "sys_fork", true);
217 const char *executable = args[0].c_str();
218 int argc = (int)args.size() - 1;
219 std::vector<char *> v_argv(argc);
220 for (int i = 0; i < argc; ++i)
221 {
222 v_argv[i] = const_cast<char *>(args[i + 1].c_str());
223 }
224 return static_cast<i64>(PHASORstd_sys_run(executable, argc, v_argv.data()));
225}
226
227i64 StdLib::sys_fork_detached(const std::vector<Value> &args, VM *)
228{
229 checkArgCount(args, 1, "sys_fork_detached", true);
230 const char *executable = args[0].c_str();
231 int argc = (int)args.size() - 1;
232 std::vector<char *> v_argv(argc);
233 for (int i = 0; i < argc; ++i)
234 {
235 v_argv[i] = const_cast<char *>(args[i + 1].c_str());
236 }
237 return static_cast<i64>(PHASORstd_sys_run_detached(executable, argc, v_argv.data()));
238}
239
240Value StdLib::sys_crash(const std::vector<Value> &args, VM *vm)
241{
242 checkArgCount(args, 1, "error", true);
243 vm->reset();
244 vm->setStatus(-1);
245 throw std::runtime_error(args[0].asString());
246}
247
248Value StdLib::sys_reset(const std::vector<Value> &args, VM *vm)
249{
250 checkArgCount(args, 0, "reset");
251 vm->reset();
252 return Value();
253}
254
255i64 StdLib::sys_pid(const std::vector<Value> &args, VM *)
256{
257 checkArgCount(args, 0, "sys_pid");
258#if defined(_WIN32)
259 return static_cast<i64>(GetCurrentProcessId());
260#else
261 return static_cast<i64>(getpid());
262#endif
263}
264
265Value StdLib::sys_isatty(const std::vector<Value> &args, VM *)
266{
267 checkArgCount(args, 0, "isatty");
268#ifdef _WIN32
269 return _isatty(_fileno(stdin));
270#else
271 return isatty(fileno(stdin));
272#endif
273}
274
275#endif
276} // namespace Phasor
const char * c_str() const noexcept
static Value sys_env(const std::vector< Value > &args, VM *vm)
Get the current environment variables.
Definition system.cpp:131
static Value sys_reset(const std::vector< Value > &args, VM *vm)
Reset the VM.
Definition system.cpp:248
static PhsString sys_os(const std::vector< Value > &args, VM *vm)
Get the current OS.
Definition system.cpp:177
static i64 sys_pid(const std::vector< Value > &args, VM *vm)
Get the current process ID.
Definition system.cpp:255
static char ** argv
Command line arguments.
Definition StdLib.hpp:48
static Value sys_crash(const std::vector< Value > &args, VM *vm)
Crash the VM / Program.
Definition system.cpp:240
static i64 sys_fork_detached(const std::vector< Value > &args, VM *vm)
Run a native program detached.
Definition system.cpp:227
static void checkArgCount(const std::vector< Value > &args, size_t minimumArguments, const std::string &name, bool allowMoreArguments=false)
Definition StdLib.cpp:44
static Value sys_argv(const std::vector< Value > &args, VM *vm)
Get the current command line arguments – deprecated, use sys_args() instead.
Definition system.cpp:148
static int argc
Number of command line arguments.
Definition StdLib.hpp:49
static Value sys_wait_for_input(const std::vector< Value > &args, VM *vm)
Wait for input.
Definition system.cpp:201
static void registerSysFunctions(VM *vm)
Definition system.cpp:34
static Value sys_shutdown(const std::vector< Value > &args, VM *vm)
Shutdown the VM.
Definition system.cpp:167
static Value sys_shell(const std::vector< Value > &args, VM *vm)
Run a shell command.
Definition system.cpp:208
static Value sys_sleep(const std::vector< Value > &args, VM *vm)
Sleep for a specified amount of time.
Definition system.cpp:123
static Value sys_args(const std::vector< Value > &args, VM *vm)
Get args array.
Definition system.cpp:156
static i64 sys_argc(const std::vector< Value > &args, VM *vm)
Get the current number of command line arguments – deprecated, use len(sys_args()) instead.
Definition system.cpp:142
static i64 sys_get_free_memory(const std::vector< Value > &args, VM *vm)
Get current free memory.
Definition system.cpp:195
static Value sys_isatty(const std::vector< Value > &args, VM *vm)
Check if the current output is a terminal.
Definition system.cpp:265
static Value sys_time_formatted(const std::vector< Value > &args, VM *vm)
Current time formatted.
Definition system.cpp:99
static dupenv_ret dupenv(PhsString &out, const char *name)
Definition StdLib.cpp:15
static f64 sys_time(const std::vector< Value > &args, VM *vm)
Current time.
Definition system.cpp:90
static Value io_gets(const std::vector< Value > &args, VM *vm)
Get string.
Definition io.cpp:80
static i64 sys_fork(const std::vector< Value > &args, VM *vm)
Run a native program.
Definition system.cpp:214
Throws when the HALT opcode is reached.
Definition VM.hpp:52
Virtual Machine.
Definition VM.hpp:36
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:39
Value regRun(OpCode opcode, Args &&...args)
Run an opcode with arguments pre-loaded into registers.
Definition VM.hpp:212
void reset(const bool &resetStack=true, const bool &resetFunctions=true, const bool &resetVariables=true)
Reset the virtual machine.
Definition Utility.cpp:191
A value in the Phasor VM.
Definition Value.hpp:59
static Value createArray(std::vector< Value > elements={})
Definition Value.hpp:572
The Phasor Programming Language and Runtime.
Definition AST.hpp:13
int64_t i64
Definition phsint.hpp:16
double f64
Definition phsint.hpp:7
@ 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 consentAskedEnv
Definition system.cpp:23
bool consentGrantedEnv
Definition system.cpp:24
bool consentAskedCLI
Definition system.cpp:20
bool consentGrantedCLI
Definition system.cpp:21
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