接续上一轮:推进浏览器验证与M428配置收拢
结论:已完成浏览器侧真实加载验证,M428/M429/M430 的配置入口进一步从 LinuxCNC INI/HALFILE/REMAP 来源生成,native 与 source-link 验证通过。
This commit is contained in:
3
core/wasm_shims/Python.h
Normal file
3
core/wasm_shims/Python.h
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
18
core/wasm_shims/boost/noncopyable.hpp
Normal file
18
core/wasm_shims/boost/noncopyable.hpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef CNC_SIM_WASM_SHIMS_BOOST_NONCOPYABLE_HPP
|
||||
#define CNC_SIM_WASM_SHIMS_BOOST_NONCOPYABLE_HPP
|
||||
|
||||
namespace boost {
|
||||
|
||||
class noncopyable {
|
||||
protected:
|
||||
noncopyable() = default;
|
||||
~noncopyable() = default;
|
||||
|
||||
private:
|
||||
noncopyable(const noncopyable &) = delete;
|
||||
noncopyable &operator=(const noncopyable &) = delete;
|
||||
};
|
||||
|
||||
} // namespace boost
|
||||
|
||||
#endif // CNC_SIM_WASM_SHIMS_BOOST_NONCOPYABLE_HPP
|
||||
10
core/wasm_shims/boost/python/class.hpp
Normal file
10
core/wasm_shims/boost/python/class.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <boost/call_traits.hpp>
|
||||
#include <boost/config.hpp>
|
||||
|
||||
#ifndef BOOST_DEDUCED_TYPENAME
|
||||
#define BOOST_DEDUCED_TYPENAME typename
|
||||
#endif
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
3
core/wasm_shims/boost/python/converter/registry.hpp
Normal file
3
core/wasm_shims/boost/python/converter/registry.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
13
core/wasm_shims/boost/python/def.hpp
Normal file
13
core/wasm_shims/boost/python/def.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <typename... Args>
|
||||
void def(Args &&...) {
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
3
core/wasm_shims/boost/python/detail/caller.hpp
Normal file
3
core/wasm_shims/boost/python/detail/caller.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
25
core/wasm_shims/boost/python/enum.hpp
Normal file
25
core/wasm_shims/boost/python/enum.hpp
Normal file
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <typename T>
|
||||
class enum_ {
|
||||
public:
|
||||
explicit enum_(const char *) {
|
||||
}
|
||||
|
||||
template <typename Value>
|
||||
enum_ &value(const char *, Value) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
enum_ &export_values() {
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
13
core/wasm_shims/boost/python/exception_translator.hpp
Normal file
13
core/wasm_shims/boost/python/exception_translator.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <typename Exception, typename Translator>
|
||||
void register_exception_translator(Translator) {
|
||||
}
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
5
core/wasm_shims/boost/python/module.hpp
Normal file
5
core/wasm_shims/boost/python/module.hpp
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
#define BOOST_PYTHON_MODULE(name) extern "C" void init_##name()
|
||||
@@ -1,24 +1,126 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdarg>
|
||||
#include <sstream>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include "boost/noncopyable.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
using Py_ssize_t = std::ptrdiff_t;
|
||||
struct _object;
|
||||
using PyObject = _object;
|
||||
|
||||
struct _typeobject {
|
||||
const char *tp_name;
|
||||
std::size_t tp_basicsize;
|
||||
std::size_t tp_itemsize;
|
||||
void *tp_dealloc;
|
||||
void *tp_print;
|
||||
void *tp_getattr;
|
||||
void *tp_setattr;
|
||||
void *tp_compare;
|
||||
void *tp_repr;
|
||||
void *tp_as_number;
|
||||
void *tp_as_sequence;
|
||||
void *tp_as_mapping;
|
||||
void *tp_hash;
|
||||
void *tp_call;
|
||||
void *tp_str;
|
||||
void *tp_getattro;
|
||||
void *tp_setattro;
|
||||
void *tp_as_buffer;
|
||||
unsigned long tp_flags;
|
||||
const char *tp_doc;
|
||||
void *tp_traverse;
|
||||
void *tp_clear;
|
||||
void *tp_richcompare;
|
||||
Py_ssize_t tp_weaklistoffset;
|
||||
void *tp_iter;
|
||||
void *tp_iternext;
|
||||
void *tp_methods;
|
||||
void *tp_members;
|
||||
void *tp_getset;
|
||||
struct _typeobject *tp_base;
|
||||
void *tp_dict;
|
||||
void *tp_descr_get;
|
||||
void *tp_descr_set;
|
||||
Py_ssize_t tp_dictoffset;
|
||||
void *tp_init;
|
||||
void *tp_alloc;
|
||||
PyObject *(*tp_new)(struct _typeobject *, PyObject *, PyObject *);
|
||||
void *tp_free;
|
||||
void *tp_is_gc;
|
||||
void *tp_bases;
|
||||
void *tp_mro;
|
||||
void *tp_cache;
|
||||
void *tp_subclasses;
|
||||
void *tp_weaklink;
|
||||
void *tp_del;
|
||||
unsigned int tp_version_tag;
|
||||
void *tp_finalize;
|
||||
#if PY_VERSION_HEX >= 0x030800f0
|
||||
void *tp_vectorcall;
|
||||
#if PY_VERSION_HEX >= 0x030c00f0
|
||||
void *tp_watched;
|
||||
#if PY_VERSION_HEX >= 0x030d00f0
|
||||
void *tp_versions_used;
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
using PyTypeObject = _typeobject;
|
||||
|
||||
struct _object {
|
||||
PyTypeObject *ob_type;
|
||||
};
|
||||
using PyObject = _object;
|
||||
|
||||
struct _inittab {
|
||||
const char *name;
|
||||
PyObject *(*initfunc)(void);
|
||||
};
|
||||
|
||||
using PyCFunction = PyObject *(*)(PyObject *, PyObject *);
|
||||
using getter = PyObject *(*)(PyObject *, void *);
|
||||
using setter = int (*)(PyObject *, PyObject *, void *);
|
||||
|
||||
struct PyGetSetDef {
|
||||
char *name;
|
||||
getter get;
|
||||
setter set;
|
||||
char *doc;
|
||||
void *closure;
|
||||
};
|
||||
|
||||
struct PyMemberDef {
|
||||
char *name;
|
||||
int type;
|
||||
Py_ssize_t offset;
|
||||
int flags;
|
||||
char *doc;
|
||||
};
|
||||
|
||||
struct PyMethodDef {
|
||||
const char *ml_name;
|
||||
PyCFunction ml_meth;
|
||||
int ml_flags;
|
||||
const char *ml_doc;
|
||||
};
|
||||
|
||||
struct PyModuleDef {
|
||||
void *m_base;
|
||||
const char *m_name;
|
||||
const char *m_doc;
|
||||
Py_ssize_t m_size;
|
||||
PyMethodDef *m_methods;
|
||||
void *m_slots;
|
||||
void *m_traverse;
|
||||
void *m_clear;
|
||||
void *m_free;
|
||||
};
|
||||
|
||||
int Py_IsInitialized(void);
|
||||
PyObject *PyErr_Occurred(void);
|
||||
void PyErr_Clear(void);
|
||||
@@ -31,21 +133,66 @@ int PyUnicode_Check(PyObject *);
|
||||
int PyLong_Check(PyObject *);
|
||||
int PyFloat_Check(PyObject *);
|
||||
int PyGen_Check(PyObject *);
|
||||
int PyObject_IsInstance(PyObject *, PyObject *);
|
||||
PyObject *PyObject_Str(PyObject *);
|
||||
const char *PyUnicode_AsUTF8(PyObject *);
|
||||
PyObject *PyUnicode_FromString(const char *);
|
||||
void PyErr_SetObject(PyObject *, PyObject *);
|
||||
PyObject *PyErr_Format(PyObject *, const char *, ...);
|
||||
void Py_DecRef(PyObject *);
|
||||
int PyArg_ParseTuple(PyObject *, const char *, ...);
|
||||
int PyArg_VaParse(PyObject *, const char *, va_list);
|
||||
PyObject *PyObject_CallMethod(PyObject *, char *, char *, ...);
|
||||
PyObject *PyObject_GetAttrString(PyObject *, const char *);
|
||||
int PyObject_SetAttrString(PyObject *, const char *, PyObject *);
|
||||
int PyObject_IsTrue(PyObject *);
|
||||
PyObject *PyLong_FromLong(long);
|
||||
long PyLong_AsLong(PyObject *);
|
||||
double PyFloat_AsDouble(PyObject *);
|
||||
PyObject *PyTuple_New(Py_ssize_t);
|
||||
PyObject *PyTuple_GetItem(PyObject *, Py_ssize_t);
|
||||
Py_ssize_t PyTuple_Size(PyObject *);
|
||||
int PyTuple_SetItem(PyObject *, Py_ssize_t, PyObject *);
|
||||
PyObject *PyList_New(Py_ssize_t);
|
||||
PyObject *PyList_GetItem(PyObject *, Py_ssize_t);
|
||||
Py_ssize_t PyList_Size(PyObject *);
|
||||
int PyList_SetItem(PyObject *, Py_ssize_t, PyObject *);
|
||||
PyObject *PySequence_GetItem(PyObject *, Py_ssize_t);
|
||||
Py_ssize_t PySequence_Length(PyObject *);
|
||||
PyObject *Py_BuildValue(const char *, ...);
|
||||
PyObject *PyModule_Create(PyModuleDef *);
|
||||
int PyModule_AddObject(PyObject *, const char *, PyObject *);
|
||||
int PyType_Ready(PyTypeObject *);
|
||||
PyObject *PyType_GenericNew(PyTypeObject *, PyObject *, PyObject *);
|
||||
void *PyObject_NewShim(std::size_t, PyTypeObject *);
|
||||
extern PyObject *PyExc_KeyError;
|
||||
extern PyObject *PyExc_KeyboardInterrupt;
|
||||
extern PyObject *PyExc_RuntimeError;
|
||||
extern PyObject *PyExc_StopIteration;
|
||||
extern PyObject *PyExc_TypeError;
|
||||
extern PyObject *_Py_NoneStructPtr;
|
||||
extern PyTypeObject PyString_Type;
|
||||
extern PyTypeObject PyInt_Type;
|
||||
extern PyTypeObject PyList_Type;
|
||||
|
||||
#define PyObject_HEAD PyObject ob_base;
|
||||
#define PyVarObject_HEAD_INIT(type, size)
|
||||
#define PyModuleDef_HEAD_INIT nullptr
|
||||
#define Py_TPFLAGS_DEFAULT 0
|
||||
#define PyMODINIT_FUNC extern "C" PyObject *
|
||||
#define METH_VARARGS 0x0001
|
||||
#define Py_None (_Py_NoneStructPtr)
|
||||
#define Py_TYPE(ob) ((ob)->ob_type)
|
||||
#define Py_DECREF(ob) Py_DecRef(reinterpret_cast<PyObject *>(ob))
|
||||
#define Py_XDECREF(ob) \
|
||||
do { \
|
||||
if (ob) { \
|
||||
Py_DecRef(ob); \
|
||||
Py_DecRef(reinterpret_cast<PyObject *>(ob)); \
|
||||
} \
|
||||
} while (0)
|
||||
#define PyTuple_SET_ITEM(op, i, v) PyTuple_SetItem((op), (i), (v))
|
||||
#define PyList_SET_ITEM(op, i, v) PyList_SetItem((op), (i), (v))
|
||||
#define PyObject_New(type, typeobj) reinterpret_cast<type *>(PyObject_NewShim(sizeof(type), (typeobj)))
|
||||
|
||||
}
|
||||
|
||||
@@ -106,6 +253,93 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct no_init_t {};
|
||||
inline constexpr no_init_t no_init{};
|
||||
|
||||
struct default_call_policies {};
|
||||
struct reference_existing_object {};
|
||||
|
||||
template <typename T>
|
||||
struct return_value_policy {
|
||||
};
|
||||
|
||||
template <int, int>
|
||||
struct with_custodian_and_ward_postcall {
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
struct init {
|
||||
};
|
||||
|
||||
class arg {
|
||||
public:
|
||||
explicit arg(const char *) {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T = void>
|
||||
struct type_info {
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
type_info<T> type_id() {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
object make_getter(Args &&...) {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
object make_setter(Args &&...) {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
object make_function(Args &&...) {
|
||||
return {};
|
||||
}
|
||||
|
||||
template <typename T, typename Bases = void>
|
||||
class class_ {
|
||||
public:
|
||||
explicit class_(const char *) {
|
||||
}
|
||||
|
||||
class_(const char *, no_init_t) {
|
||||
}
|
||||
|
||||
class_(const char *, const char *) {
|
||||
}
|
||||
|
||||
class_(const char *, const char *, no_init_t) {
|
||||
}
|
||||
|
||||
template <typename Arg>
|
||||
class_(const char *, Arg) {
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
class_ &def(Args &&...) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
class_ &def_readwrite(Args &&...) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
class_ &add_property(Args &&...) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
PyObject *ptr() const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
inline object getattr(const object &, const char *) {
|
||||
return {};
|
||||
}
|
||||
@@ -115,6 +349,10 @@ public:
|
||||
template <typename T>
|
||||
void append(const T &) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void extend(const T &) {
|
||||
}
|
||||
};
|
||||
|
||||
class dict : public object {
|
||||
@@ -131,8 +369,35 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
tuple make_tuple(Args &&...) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator%(const char *, const tuple &) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator%(const object &, const tuple &) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator+(const object &, const object &) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator+(const object &, const char *) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline object operator+(const char *, const object &) {
|
||||
return {};
|
||||
}
|
||||
|
||||
class scope {
|
||||
public:
|
||||
scope() = default;
|
||||
|
||||
explicit scope(const object &) {
|
||||
}
|
||||
|
||||
@@ -187,6 +452,8 @@ allow_null_result<T> allow_null(T *value) {
|
||||
template <typename T = void>
|
||||
class handle {
|
||||
public:
|
||||
handle() = default;
|
||||
|
||||
template <typename U>
|
||||
explicit handle(const U &) {
|
||||
}
|
||||
@@ -194,6 +461,10 @@ public:
|
||||
explicit operator bool() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void *get() const {
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class str : public object {
|
||||
|
||||
16
core/wasm_shims/boost/python/object/class_detail.hpp
Normal file
16
core/wasm_shims/boost/python/object/class_detail.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
namespace objects {
|
||||
|
||||
template <typename T>
|
||||
void *registered_class_object(T) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace objects
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
13
core/wasm_shims/boost/python/return_internal_reference.hpp
Normal file
13
core/wasm_shims/boost/python/return_internal_reference.hpp
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <int Owner = 1, typename BasePolicy = default_call_policies>
|
||||
struct return_internal_reference : BasePolicy {
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
template <typename Map>
|
||||
class map_indexing_suite {
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
99
core/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc
Normal file
99
core/wasm_shims/cnc_sim_wasm_runtime_probe_main.cc
Normal file
@@ -0,0 +1,99 @@
|
||||
#include "cnc_sim_api.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wordexp.h>
|
||||
|
||||
namespace {
|
||||
|
||||
int collect_event(const CncSimEvent *event, void *user_data) {
|
||||
auto *events = static_cast<std::vector<CncSimEvent> *>(user_data);
|
||||
events->push_back(*event);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool near(double lhs, double rhs) {
|
||||
return std::fabs(lhs - rhs) < 0.000001;
|
||||
}
|
||||
|
||||
bool wordexp_expands_home() {
|
||||
const char *home = std::getenv("HOME");
|
||||
if (!home || !home[0]) {
|
||||
return true;
|
||||
}
|
||||
|
||||
wordexp_t expanded{};
|
||||
if (wordexp("~/cnc_sim_wordexp_probe", &expanded, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string expected = std::string(home) + "/cnc_sim_wordexp_probe";
|
||||
const bool ok = expanded.we_wordc == 1 &&
|
||||
expanded.we_wordv &&
|
||||
expanded.we_wordv[0] &&
|
||||
std::strcmp(expanded.we_wordv[0], expected.c_str()) == 0;
|
||||
wordfree(&expanded);
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool wordexp_expands_environment_variables() {
|
||||
setenv("CNC_SIM_WORDEXP_PROBE", "linuxcnc-wordexp", 1);
|
||||
|
||||
wordexp_t expanded{};
|
||||
if (wordexp("$CNC_SIM_WORDEXP_PROBE/path", &expanded, 0) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool ok = expanded.we_wordc == 1 &&
|
||||
expanded.we_wordv &&
|
||||
expanded.we_wordv[0] &&
|
||||
std::strcmp(expanded.we_wordv[0], "linuxcnc-wordexp/path") == 0;
|
||||
wordfree(&expanded);
|
||||
return ok;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
if (!wordexp_expands_home()) {
|
||||
return 5;
|
||||
}
|
||||
if (!wordexp_expands_environment_variables()) {
|
||||
return 6;
|
||||
}
|
||||
|
||||
std::vector<CncSimEvent> events;
|
||||
CncSimHandle *sim = cnc_sim_create();
|
||||
if (!sim) {
|
||||
return 1;
|
||||
}
|
||||
if (cnc_sim_set_event_callback(sim, collect_event, &events) != 0) {
|
||||
cnc_sim_destroy(sim);
|
||||
return 2;
|
||||
}
|
||||
|
||||
const char program[] =
|
||||
"G21 G90 G17\n"
|
||||
"G0 X1\n"
|
||||
"M30\n";
|
||||
if (cnc_sim_parse_program(sim, program, sizeof(program) - 1) != 0) {
|
||||
cnc_sim_destroy(sim);
|
||||
return 3;
|
||||
}
|
||||
|
||||
bool saw_linuxcnc_rapid = false;
|
||||
bool saw_program_end = false;
|
||||
for (const auto &event : events) {
|
||||
saw_linuxcnc_rapid = saw_linuxcnc_rapid ||
|
||||
(event.type == CNC_SIM_EVENT_RAPID &&
|
||||
event.line == 2 &&
|
||||
near(event.end.x, 1.0));
|
||||
saw_program_end = saw_program_end || event.type == CNC_SIM_EVENT_PROGRAM_END;
|
||||
}
|
||||
|
||||
cnc_sim_destroy(sim);
|
||||
return saw_linuxcnc_rapid && saw_program_end ? 0 : 4;
|
||||
}
|
||||
20
core/wasm_shims/libgen.h
Normal file
20
core/wasm_shims/libgen.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef CNC_SIM_WASM_SHIMS_LIBGEN_H
|
||||
#define CNC_SIM_WASM_SHIMS_LIBGEN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
char *dirname(char *);
|
||||
char *basename(char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
inline char *basename(const char *path)
|
||||
{
|
||||
return basename(const_cast<char *>(path));
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // CNC_SIM_WASM_SHIMS_LIBGEN_H
|
||||
@@ -1,6 +1,12 @@
|
||||
#include "boost/python/object.hpp"
|
||||
#include "hal.h"
|
||||
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <wordexp.h>
|
||||
|
||||
int _task = 0;
|
||||
|
||||
extern "C" PyObject *PyInit_interpreter(void) {
|
||||
@@ -11,6 +17,10 @@ extern "C" PyObject *PyInit_emccanon(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" PyObject *PyInit_gcode(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
struct _inittab builtin_modules[] = {
|
||||
{"interpreter", PyInit_interpreter},
|
||||
@@ -70,3 +80,119 @@ extern "C" int hal_get_param_value_by_name(const char *,
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
std::string expand_home_directory(const char *words) {
|
||||
std::string expanded(words);
|
||||
if (expanded.empty() || expanded[0] != '~') {
|
||||
return expanded;
|
||||
}
|
||||
if (expanded.size() > 1 && expanded[1] != '/') {
|
||||
return expanded;
|
||||
}
|
||||
|
||||
const char *home = std::getenv("HOME");
|
||||
if (!home || !home[0]) {
|
||||
return expanded;
|
||||
}
|
||||
expanded.replace(0, 1, home);
|
||||
return expanded;
|
||||
}
|
||||
|
||||
bool variable_start(char value) {
|
||||
const unsigned char ch = static_cast<unsigned char>(value);
|
||||
return std::isalpha(ch) || value == '_';
|
||||
}
|
||||
|
||||
bool variable_char(char value) {
|
||||
const unsigned char ch = static_cast<unsigned char>(value);
|
||||
return std::isalnum(ch) || value == '_';
|
||||
}
|
||||
|
||||
std::string expand_environment_variables(const std::string &words) {
|
||||
std::string expanded;
|
||||
expanded.reserve(words.size());
|
||||
|
||||
for (size_t index = 0; index < words.size();) {
|
||||
if (words[index] != '$' || index + 1 >= words.size()) {
|
||||
expanded.push_back(words[index++]);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (words[index + 1] == '{') {
|
||||
const size_t end = words.find('}', index + 2);
|
||||
if (end == std::string::npos || end == index + 2) {
|
||||
expanded.push_back(words[index++]);
|
||||
continue;
|
||||
}
|
||||
const std::string name = words.substr(index + 2, end - index - 2);
|
||||
if (const char *value = std::getenv(name.c_str())) {
|
||||
expanded += value;
|
||||
}
|
||||
index = end + 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!variable_start(words[index + 1])) {
|
||||
expanded.push_back(words[index++]);
|
||||
continue;
|
||||
}
|
||||
|
||||
size_t end = index + 2;
|
||||
while (end < words.size() && variable_char(words[end])) {
|
||||
++end;
|
||||
}
|
||||
const std::string name = words.substr(index + 1, end - index - 1);
|
||||
if (const char *value = std::getenv(name.c_str())) {
|
||||
expanded += value;
|
||||
}
|
||||
index = end;
|
||||
}
|
||||
|
||||
return expanded;
|
||||
}
|
||||
|
||||
std::string expand_path_word(const char *words) {
|
||||
return expand_environment_variables(expand_home_directory(words));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" int wordexp(const char *words, wordexp_t *pwordexp, int) {
|
||||
if (!words || !pwordexp) {
|
||||
return WRDE_BADVAL;
|
||||
}
|
||||
|
||||
const std::string expanded = expand_path_word(words);
|
||||
char **wordv = static_cast<char **>(std::calloc(2, sizeof(char *)));
|
||||
if (!wordv) {
|
||||
return WRDE_NOSPACE;
|
||||
}
|
||||
|
||||
wordv[0] = static_cast<char *>(std::malloc(expanded.size() + 1));
|
||||
if (!wordv[0]) {
|
||||
std::free(wordv);
|
||||
return WRDE_NOSPACE;
|
||||
}
|
||||
|
||||
std::strcpy(wordv[0], expanded.c_str());
|
||||
pwordexp->we_wordc = 1;
|
||||
pwordexp->we_wordv = wordv;
|
||||
pwordexp->we_offs = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void wordfree(wordexp_t *pwordexp) {
|
||||
if (!pwordexp || !pwordexp->we_wordv) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < pwordexp->we_wordc; ++index) {
|
||||
std::free(pwordexp->we_wordv[index]);
|
||||
}
|
||||
std::free(pwordexp->we_wordv);
|
||||
pwordexp->we_wordc = 0;
|
||||
pwordexp->we_wordv = nullptr;
|
||||
pwordexp->we_offs = 0;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
extern "C" {
|
||||
|
||||
static PyTypeObject none_type = {"NoneType"};
|
||||
static PyObject none_object = {&none_type};
|
||||
|
||||
PyObject *PyExc_KeyError = reinterpret_cast<PyObject *>(1);
|
||||
PyObject *PyExc_StopIteration = reinterpret_cast<PyObject *>(2);
|
||||
PyObject *PyExc_KeyboardInterrupt = reinterpret_cast<PyObject *>(2);
|
||||
PyObject *PyExc_RuntimeError = reinterpret_cast<PyObject *>(3);
|
||||
PyObject *PyExc_StopIteration = reinterpret_cast<PyObject *>(4);
|
||||
PyObject *PyExc_TypeError = reinterpret_cast<PyObject *>(5);
|
||||
PyObject *_Py_NoneStructPtr = &none_object;
|
||||
PyTypeObject PyString_Type = {"str"};
|
||||
PyTypeObject PyInt_Type = {"int"};
|
||||
PyTypeObject PyList_Type = {"list"};
|
||||
|
||||
int Py_IsInitialized(void) {
|
||||
return 1;
|
||||
@@ -62,6 +70,10 @@ int PyGen_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyObject_IsInstance(PyObject *, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyObject_Str(PyObject *) {
|
||||
return &none_object;
|
||||
}
|
||||
@@ -70,7 +82,122 @@ const char *PyUnicode_AsUTF8(PyObject *) {
|
||||
return "";
|
||||
}
|
||||
|
||||
PyObject *PyUnicode_FromString(const char *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
void PyErr_SetObject(PyObject *, PyObject *) {
|
||||
}
|
||||
|
||||
PyObject *PyErr_Format(PyObject *, const char *, ...) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Py_DecRef(PyObject *) {
|
||||
}
|
||||
|
||||
int PyArg_ParseTuple(PyObject *, const char *, ...) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyArg_VaParse(PyObject *, const char *, va_list) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyObject_CallMethod(PyObject *, char *, char *, ...) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
PyObject *PyObject_GetAttrString(PyObject *, const char *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
int PyObject_SetAttrString(PyObject *, const char *, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyObject_IsTrue(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyLong_FromLong(long) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
long PyLong_AsLong(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
double PyFloat_AsDouble(PyObject *) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
PyObject *PyTuple_New(Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
PyObject *PyTuple_GetItem(PyObject *, Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
Py_ssize_t PyTuple_Size(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyTuple_SetItem(PyObject *, Py_ssize_t, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyList_New(Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
PyObject *PyList_GetItem(PyObject *, Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
Py_ssize_t PyList_Size(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyList_SetItem(PyObject *, Py_ssize_t, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PySequence_GetItem(PyObject *, Py_ssize_t) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
Py_ssize_t PySequence_Length(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *Py_BuildValue(const char *, ...) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
PyObject *PyModule_Create(PyModuleDef *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
int PyModule_AddObject(PyObject *, const char *, PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyType_Ready(PyTypeObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyType_GenericNew(PyTypeObject *, PyObject *, PyObject *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
void *PyObject_NewShim(std::size_t size, PyTypeObject *type) {
|
||||
auto *object = static_cast<PyObject *>(std::calloc(1, size));
|
||||
if (object) {
|
||||
object->ob_type = type;
|
||||
}
|
||||
return object;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include "pythonplugin/python_plugin.hh"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
|
||||
__attribute__((weak)) std::string handle_pyerror() {
|
||||
return "python disabled in wasm-safe probe";
|
||||
}
|
||||
@@ -13,7 +16,30 @@ PythonPlugin *PythonPlugin::instantiate(struct _inittab *) {
|
||||
return python_plugin;
|
||||
}
|
||||
|
||||
int PythonPlugin::configure(const char *, const char *) {
|
||||
int PythonPlugin::configure(const char *iniFilename, const char *section) {
|
||||
if (!section) {
|
||||
error_msg = "no section";
|
||||
status = PLUGIN_NO_SECTION;
|
||||
return status;
|
||||
}
|
||||
|
||||
if (!iniFilename) {
|
||||
iniFilename = std::getenv("INI_FILE_NAME");
|
||||
if (!iniFilename) {
|
||||
error_msg = "no inifile";
|
||||
status = PLUGIN_NO_INIFILE;
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
FILE *file = std::fopen(iniFilename, "r");
|
||||
if (!file) {
|
||||
error_msg = "bad inifile";
|
||||
status = PLUGIN_BAD_INIFILE;
|
||||
return status;
|
||||
}
|
||||
std::fclose(file);
|
||||
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
@@ -23,12 +49,17 @@ bool PythonPlugin::is_callable(const char *, const char *) {
|
||||
}
|
||||
|
||||
int PythonPlugin::call(const char *,
|
||||
const char *,
|
||||
const char *callable,
|
||||
boost::python::object,
|
||||
boost::python::object,
|
||||
boost::python::object &retval) {
|
||||
if (!callable) {
|
||||
return PLUGIN_NO_CALLABLE;
|
||||
}
|
||||
|
||||
retval = boost::python::object();
|
||||
status = PLUGIN_NO_CALLABLE;
|
||||
exception_msg = handle_pyerror();
|
||||
status = PLUGIN_EXCEPTION;
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,10 +8,34 @@ int main() {
|
||||
if (!plugin->usable()) {
|
||||
return 2;
|
||||
}
|
||||
if (plugin->configure(nullptr, nullptr) != PLUGIN_NO_SECTION) {
|
||||
return 6;
|
||||
}
|
||||
if (plugin->configure("/tmp/cnc_sim_missing_python_plugin_probe.ini", "PYTHON") != PLUGIN_BAD_INIFILE) {
|
||||
return 7;
|
||||
}
|
||||
boost::python::object retval;
|
||||
if (plugin->run_string("noop", retval, false) != PLUGIN_OK) {
|
||||
return 3;
|
||||
}
|
||||
if (plugin->call(nullptr, nullptr, boost::python::object(), boost::python::object(), retval) != PLUGIN_NO_CALLABLE) {
|
||||
return 8;
|
||||
}
|
||||
if (plugin->plugin_status() != PLUGIN_OK) {
|
||||
return 9;
|
||||
}
|
||||
if (plugin->call(nullptr, "noop", boost::python::object(), boost::python::object(), retval) != PLUGIN_EXCEPTION) {
|
||||
return 10;
|
||||
}
|
||||
if (plugin->plugin_status() != PLUGIN_EXCEPTION) {
|
||||
return 11;
|
||||
}
|
||||
if (plugin->last_exception().empty()) {
|
||||
return 12;
|
||||
}
|
||||
if (plugin->run_string("noop", retval, false) != PLUGIN_OK) {
|
||||
return 13;
|
||||
}
|
||||
if (plugin->is_callable(nullptr, "noop")) {
|
||||
return 4;
|
||||
}
|
||||
@@ -20,4 +44,3 @@ int main() {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
7
core/wasm_shims/structmember.h
Normal file
7
core/wasm_shims/structmember.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
#define T_INT 1
|
||||
#define T_DOUBLE 2
|
||||
#define READONLY 1
|
||||
@@ -19,6 +19,7 @@ extern "C" {
|
||||
|
||||
toolidx_t tooldata_put(CANON_TOOL_TABLE tdata, int idx) {
|
||||
if (!mmap_created) {
|
||||
std::fprintf(stderr, "%5d tooldata_put() no tool_mmap_base\n", getpid());
|
||||
return IDX_FAIL;
|
||||
}
|
||||
if (idx < 0 || idx >= CANON_POCKETS_MAX) {
|
||||
@@ -110,7 +111,11 @@ int tool_mmap_creator(EMC_TOOL_STAT const *ptr, int random_toolchanger) {
|
||||
}
|
||||
|
||||
int tool_mmap_user(void) {
|
||||
return mmap_created ? 0 : -1;
|
||||
if (!mmap_created) {
|
||||
std::fprintf(stderr, "tool_mmap_user(): tool mmap not available\n");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tool_mmap_close(void) {
|
||||
|
||||
Reference in New Issue
Block a user