Harden LinuxCNC wasm and native probe workflows
This commit is contained in:
4
core/wasm_shims/boost/python/dict.hpp
Normal file
4
core/wasm_shims/boost/python/dict.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
4
core/wasm_shims/boost/python/extract.hpp
Normal file
4
core/wasm_shims/boost/python/extract.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
4
core/wasm_shims/boost/python/import.hpp
Normal file
4
core/wasm_shims/boost/python/import.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
4
core/wasm_shims/boost/python/list.hpp
Normal file
4
core/wasm_shims/boost/python/list.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
211
core/wasm_shims/boost/python/object.hpp
Normal file
211
core/wasm_shims/boost/python/object.hpp
Normal file
@@ -0,0 +1,211 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
extern "C" {
|
||||
|
||||
struct _typeobject {
|
||||
const char *tp_name;
|
||||
};
|
||||
using PyTypeObject = _typeobject;
|
||||
|
||||
struct _object {
|
||||
PyTypeObject *ob_type;
|
||||
};
|
||||
using PyObject = _object;
|
||||
|
||||
struct _inittab {
|
||||
const char *name;
|
||||
PyObject *(*initfunc)(void);
|
||||
};
|
||||
|
||||
int Py_IsInitialized(void);
|
||||
PyObject *PyErr_Occurred(void);
|
||||
void PyErr_Clear(void);
|
||||
int PyErr_ExceptionMatches(PyObject *);
|
||||
int PyCallable_Check(PyObject *);
|
||||
void PyErr_Fetch(PyObject **, PyObject **, PyObject **);
|
||||
void PyErr_NormalizeException(PyObject **, PyObject **, PyObject **);
|
||||
void PyErr_Print(void);
|
||||
int PyUnicode_Check(PyObject *);
|
||||
int PyLong_Check(PyObject *);
|
||||
int PyFloat_Check(PyObject *);
|
||||
int PyGen_Check(PyObject *);
|
||||
PyObject *PyObject_Str(PyObject *);
|
||||
const char *PyUnicode_AsUTF8(PyObject *);
|
||||
void Py_DecRef(PyObject *);
|
||||
extern PyObject *PyExc_KeyError;
|
||||
extern PyObject *PyExc_StopIteration;
|
||||
extern PyObject *_Py_NoneStructPtr;
|
||||
|
||||
#define Py_None (_Py_NoneStructPtr)
|
||||
#define Py_TYPE(ob) ((ob)->ob_type)
|
||||
#define Py_XDECREF(ob) \
|
||||
do { \
|
||||
if (ob) { \
|
||||
Py_DecRef(ob); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
}
|
||||
|
||||
namespace boost {
|
||||
|
||||
template <typename T>
|
||||
const T &cref(const T &value) {
|
||||
return value;
|
||||
}
|
||||
|
||||
namespace python {
|
||||
|
||||
class error_already_set {};
|
||||
|
||||
class object {
|
||||
public:
|
||||
object() = default;
|
||||
template <typename T>
|
||||
object(const T &) {
|
||||
}
|
||||
~object() = default;
|
||||
|
||||
class attr_proxy {
|
||||
public:
|
||||
template <typename T>
|
||||
attr_proxy &operator=(const T &) {
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator object() const {
|
||||
return object();
|
||||
}
|
||||
};
|
||||
|
||||
attr_proxy attr(const char *) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
object operator[](const char *) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
object operator[](const std::string &) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
object operator[](int) const {
|
||||
return {};
|
||||
}
|
||||
|
||||
PyObject *ptr() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
object operator()(Args &&...) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
inline object getattr(const object &, const char *) {
|
||||
return {};
|
||||
}
|
||||
|
||||
class list : public object {
|
||||
public:
|
||||
template <typename T>
|
||||
void append(const T &) {
|
||||
}
|
||||
};
|
||||
|
||||
class dict : public object {
|
||||
public:
|
||||
list keys() const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
class tuple : public object {
|
||||
public:
|
||||
tuple() = default;
|
||||
tuple(const list &) {
|
||||
}
|
||||
};
|
||||
|
||||
class scope {
|
||||
public:
|
||||
explicit scope(const object &) {
|
||||
}
|
||||
|
||||
object::attr_proxy attr(const char *) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct extract {
|
||||
explicit extract(const object &) {
|
||||
}
|
||||
|
||||
operator T() const {
|
||||
return T();
|
||||
}
|
||||
};
|
||||
|
||||
inline object import(const char *) {
|
||||
return {};
|
||||
}
|
||||
|
||||
inline int len(const list &) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline void handle_exception() {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
struct borrowed_result {
|
||||
explicit borrowed_result(T *) {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct allow_null_result {
|
||||
explicit allow_null_result(T *) {
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
borrowed_result<T> borrowed(T *value) {
|
||||
return borrowed_result<T>(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
allow_null_result<T> allow_null(T *value) {
|
||||
return allow_null_result<T>(value);
|
||||
}
|
||||
|
||||
template <typename T = void>
|
||||
class handle {
|
||||
public:
|
||||
template <typename U>
|
||||
explicit handle(const U &) {
|
||||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
class str : public object {
|
||||
public:
|
||||
template <typename T>
|
||||
explicit str(const T &) {
|
||||
}
|
||||
|
||||
object join(const object &) const {
|
||||
return {};
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
10
core/wasm_shims/boost/python/object_fwd.hpp
Normal file
10
core/wasm_shims/boost/python/object_fwd.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
namespace boost {
|
||||
namespace python {
|
||||
|
||||
class object;
|
||||
|
||||
} // namespace python
|
||||
} // namespace boost
|
||||
|
||||
4
core/wasm_shims/boost/python/scope.hpp
Normal file
4
core/wasm_shims/boost/python/scope.hpp
Normal file
@@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
3
core/wasm_shims/boost/python/str.hpp
Normal file
3
core/wasm_shims/boost/python/str.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
3
core/wasm_shims/boost/python/tuple.hpp
Normal file
3
core/wasm_shims/boost/python/tuple.hpp
Normal file
@@ -0,0 +1,3 @@
|
||||
#pragma once
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
30
core/wasm_shims/dlfcn.cc
Normal file
30
core/wasm_shims/dlfcn.cc
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "dlfcn.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace {
|
||||
|
||||
thread_local char last_error[128] = "dynamic loading is unavailable in wasm-safe probe";
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
void *dlopen(const char *, int) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void *dlsym(void *, const char *) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
char *dlerror(void) {
|
||||
return last_error;
|
||||
}
|
||||
|
||||
int dlclose(void *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
18
core/wasm_shims/dlfcn.h
Normal file
18
core/wasm_shims/dlfcn.h
Normal file
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define RTLD_GLOBAL 0x00100
|
||||
#define RTLD_NOW 0x00002
|
||||
|
||||
void *dlopen(const char *filename, int flags);
|
||||
void *dlsym(void *handle, const char *symbol);
|
||||
char *dlerror(void);
|
||||
int dlclose(void *handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
4
core/wasm_shims/emc_status_shim.cc
Normal file
4
core/wasm_shims/emc_status_shim.cc
Normal file
@@ -0,0 +1,4 @@
|
||||
#include "nml_intf/emc_nml.hh"
|
||||
|
||||
EMC_STAT *emcStatus = nullptr;
|
||||
|
||||
6
core/wasm_shims/gettext_shim.cc
Normal file
6
core/wasm_shims/gettext_shim.cc
Normal file
@@ -0,0 +1,6 @@
|
||||
#include <cstddef>
|
||||
|
||||
extern "C" char *gettext(const char *msgid) {
|
||||
return const_cast<char *>(msgid ? msgid : "");
|
||||
}
|
||||
|
||||
7
core/wasm_shims/interp_base_probe_main.cc
Normal file
7
core/wasm_shims/interp_base_probe_main.cc
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "interp_base.hh"
|
||||
|
||||
int main() {
|
||||
InterpBase *interp = interp_from_shlib("nonexistent-interpreter.so");
|
||||
return interp == nullptr ? 0 : 1;
|
||||
}
|
||||
|
||||
40
core/wasm_shims/interp_find_probe_main.cc
Normal file
40
core/wasm_shims/interp_find_probe_main.cc
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "tooldata/tooldata.hh"
|
||||
#include "rs274ngc/rs274ngc_interp.hh"
|
||||
|
||||
int main() {
|
||||
if (tool_mmap_creator(nullptr, 1) != 0) {
|
||||
return 7;
|
||||
}
|
||||
tooldata_reset();
|
||||
|
||||
CANON_TOOL_TABLE spindle = tooldata_entry_init();
|
||||
spindle.toolno = 0;
|
||||
spindle.pocketno = 0;
|
||||
if (tooldata_put(spindle, 0) != IDX_OK) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
CANON_TOOL_TABLE tool = tooldata_entry_init();
|
||||
tool.toolno = 7;
|
||||
tool.pocketno = 12;
|
||||
if (tooldata_put(tool, 12) != IDX_NEW) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
int idx = -1;
|
||||
int pocket = -1;
|
||||
auto *interp = reinterpret_cast<Interp *>(0x1);
|
||||
if (interp->find_tool_index(nullptr, 7, &idx) != INTERP_OK) {
|
||||
return 3;
|
||||
}
|
||||
if (idx != 12) {
|
||||
return 4;
|
||||
}
|
||||
if (interp->find_tool_pocket(nullptr, 7, &pocket) != INTERP_OK) {
|
||||
return 5;
|
||||
}
|
||||
if (pocket != 12) {
|
||||
return 6;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
7
core/wasm_shims/interp_find_probe_stubs.cc
Normal file
7
core/wasm_shims/interp_find_probe_stubs.cc
Normal file
@@ -0,0 +1,7 @@
|
||||
#include "rs274ngc/rs274ngc_interp.hh"
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
void Interp::setError(const char *, ...) {
|
||||
}
|
||||
|
||||
72
core/wasm_shims/linuxcnc_runtime_shim.cc
Normal file
72
core/wasm_shims/linuxcnc_runtime_shim.cc
Normal file
@@ -0,0 +1,72 @@
|
||||
#include "boost/python/object.hpp"
|
||||
#include "hal.h"
|
||||
|
||||
int _task = 0;
|
||||
|
||||
extern "C" PyObject *PyInit_interpreter(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" PyObject *PyInit_emccanon(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
struct _inittab builtin_modules[] = {
|
||||
{"interpreter", PyInit_interpreter},
|
||||
{"emccanon", PyInit_emccanon},
|
||||
{nullptr, nullptr},
|
||||
};
|
||||
}
|
||||
|
||||
extern "C" int hal_init(const char *) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" int hal_ready(int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int hal_get_pin_value_by_name(const char *,
|
||||
hal_type_t *type,
|
||||
hal_data_u **data,
|
||||
bool *connected) {
|
||||
if (type) {
|
||||
*type = HAL_TYPE_UNINITIALIZED;
|
||||
}
|
||||
if (data) {
|
||||
*data = nullptr;
|
||||
}
|
||||
if (connected) {
|
||||
*connected = false;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int hal_get_signal_value_by_name(const char *,
|
||||
hal_type_t *type,
|
||||
hal_data_u **data,
|
||||
bool *has_writers) {
|
||||
if (type) {
|
||||
*type = HAL_TYPE_UNINITIALIZED;
|
||||
}
|
||||
if (data) {
|
||||
*data = nullptr;
|
||||
}
|
||||
if (has_writers) {
|
||||
*has_writers = false;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" int hal_get_param_value_by_name(const char *,
|
||||
hal_type_t *type,
|
||||
hal_data_u **data) {
|
||||
if (type) {
|
||||
*type = HAL_TYPE_UNINITIALIZED;
|
||||
}
|
||||
if (data) {
|
||||
*data = nullptr;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
76
core/wasm_shims/python_c_api_shim.cc
Normal file
76
core/wasm_shims/python_c_api_shim.cc
Normal file
@@ -0,0 +1,76 @@
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
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 *_Py_NoneStructPtr = &none_object;
|
||||
|
||||
int Py_IsInitialized(void) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
PyObject *PyErr_Occurred(void) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void PyErr_Clear(void) {
|
||||
}
|
||||
|
||||
int PyErr_ExceptionMatches(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyCallable_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void PyErr_Fetch(PyObject **exc, PyObject **val, PyObject **tb) {
|
||||
if (exc) {
|
||||
*exc = nullptr;
|
||||
}
|
||||
if (val) {
|
||||
*val = nullptr;
|
||||
}
|
||||
if (tb) {
|
||||
*tb = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void PyErr_NormalizeException(PyObject **, PyObject **, PyObject **) {
|
||||
}
|
||||
|
||||
void PyErr_Print(void) {
|
||||
}
|
||||
|
||||
int PyUnicode_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyLong_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyFloat_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int PyGen_Check(PyObject *) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyObject_Str(PyObject *) {
|
||||
return &none_object;
|
||||
}
|
||||
|
||||
const char *PyUnicode_AsUTF8(PyObject *) {
|
||||
return "";
|
||||
}
|
||||
|
||||
void Py_DecRef(PyObject *) {
|
||||
}
|
||||
|
||||
}
|
||||
50
core/wasm_shims/pythonplugin/python_plugin.cc
Normal file
50
core/wasm_shims/pythonplugin/python_plugin.cc
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "pythonplugin/python_plugin.hh"
|
||||
|
||||
__attribute__((weak)) std::string handle_pyerror() {
|
||||
return "python disabled in wasm-safe probe";
|
||||
}
|
||||
|
||||
PythonPlugin *python_plugin = nullptr;
|
||||
|
||||
PythonPlugin *PythonPlugin::instantiate(struct _inittab *) {
|
||||
static PythonPlugin plugin;
|
||||
python_plugin = &plugin;
|
||||
python_plugin->status = PLUGIN_OK;
|
||||
return python_plugin;
|
||||
}
|
||||
|
||||
int PythonPlugin::configure(const char *, const char *) {
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
bool PythonPlugin::is_callable(const char *, const char *) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int PythonPlugin::call(const char *,
|
||||
const char *,
|
||||
boost::python::object,
|
||||
boost::python::object,
|
||||
boost::python::object &retval) {
|
||||
retval = boost::python::object();
|
||||
status = PLUGIN_NO_CALLABLE;
|
||||
return status;
|
||||
}
|
||||
|
||||
int PythonPlugin::run_string(const char *, boost::python::object &retval, bool) {
|
||||
retval = boost::python::object();
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
int PythonPlugin::call_method(boost::python::object, boost::python::object &retval) {
|
||||
retval = boost::python::object();
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
int PythonPlugin::initialize() {
|
||||
status = PLUGIN_OK;
|
||||
return status;
|
||||
}
|
||||
60
core/wasm_shims/pythonplugin/python_plugin.hh
Normal file
60
core/wasm_shims/pythonplugin/python_plugin.hh
Normal file
@@ -0,0 +1,60 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "boost/python/object.hpp"
|
||||
|
||||
extern std::string handle_pyerror();
|
||||
|
||||
enum pp_status {
|
||||
PLUGIN_NO_SECTION = -1,
|
||||
PLUGIN_NO_INIFILE = -2,
|
||||
PLUGIN_BAD_INIFILE = -3,
|
||||
PLUGIN_NO_TOPLEVEL = -4,
|
||||
PLUGIN_BAD_PATH = -5,
|
||||
PLUGIN_STAT_FAILED = -6,
|
||||
PLUGIN_INITTAB_FAILED = -7,
|
||||
PLUGIN_PYTHON_ALREADY_INITIALIZED = -8,
|
||||
PLUGIN_EXCEPTION_DURING_PATH_PREPEND = -9,
|
||||
PLUGIN_EXCEPTION_DURING_PATH_APPEND = -10,
|
||||
PLUGIN_INIT_EXCEPTION = -11,
|
||||
PLUGIN_PYTHON_NOT_INITIALIZED = -12,
|
||||
PLUGIN_PATH_TOO_LONG = -13,
|
||||
PLUGIN_OK = 0,
|
||||
PLUGIN_NO_CALLABLE = 1,
|
||||
PLUGIN_EXCEPTION = 2
|
||||
};
|
||||
|
||||
class PythonPlugin {
|
||||
public:
|
||||
static PythonPlugin *instantiate(struct _inittab *inittab = nullptr);
|
||||
int configure(const char *iniFilename = nullptr, const char *section = nullptr);
|
||||
bool is_callable(const char *module, const char *funcname);
|
||||
int call(const char *module,
|
||||
const char *callable,
|
||||
boost::python::object tupleargs,
|
||||
boost::python::object kwargs,
|
||||
boost::python::object &retval);
|
||||
int run_string(const char *cmd, boost::python::object &retval, bool as_file = false);
|
||||
int call_method(boost::python::object method, boost::python::object &retval);
|
||||
|
||||
int plugin_status() { return status; }
|
||||
bool usable() { return status >= PLUGIN_OK; }
|
||||
int initialize();
|
||||
const std::string &last_exception() { return exception_msg; }
|
||||
const std::string &last_errmsg() { return error_msg; }
|
||||
boost::python::object main_namespace;
|
||||
|
||||
private:
|
||||
PythonPlugin() = default;
|
||||
|
||||
int status = PLUGIN_OK;
|
||||
std::string exception_msg;
|
||||
std::string error_msg;
|
||||
int log_level = 0;
|
||||
};
|
||||
|
||||
extern PythonPlugin *python_plugin;
|
||||
|
||||
23
core/wasm_shims/pythonplugin/python_plugin_probe_main.cc
Normal file
23
core/wasm_shims/pythonplugin/python_plugin_probe_main.cc
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "pythonplugin/python_plugin.hh"
|
||||
|
||||
int main() {
|
||||
auto *plugin = PythonPlugin::instantiate(nullptr);
|
||||
if (!plugin) {
|
||||
return 1;
|
||||
}
|
||||
if (!plugin->usable()) {
|
||||
return 2;
|
||||
}
|
||||
boost::python::object retval;
|
||||
if (plugin->run_string("noop", retval, false) != PLUGIN_OK) {
|
||||
return 3;
|
||||
}
|
||||
if (plugin->is_callable(nullptr, "noop")) {
|
||||
return 4;
|
||||
}
|
||||
if (handle_pyerror().empty()) {
|
||||
return 5;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
33
core/wasm_shims/rs274ngc_pre_probe_main.cc
Normal file
33
core/wasm_shims/rs274ngc_pre_probe_main.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
#include "canon_event_sink.h"
|
||||
#include "linuxcnc_canon_bridge.h"
|
||||
#include "linuxcnc_tooldata_fixture.h"
|
||||
#include "rs274ngc_interp.hh"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
int main() {
|
||||
cnc_sim_init_minimal_linuxcnc_tooldata();
|
||||
|
||||
CanonEventSink sink;
|
||||
cnc_sim_linuxcnc_set_canon_sink(&sink);
|
||||
|
||||
Interp interp;
|
||||
if (interp.init() != INTERP_OK) {
|
||||
return 1;
|
||||
}
|
||||
if (interp.sequence_number() != 0) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
const double start_x = sink.position().x;
|
||||
cnc_sim_linuxcnc_set_current_line(1);
|
||||
const int read_rc = interp.read("G91 G0 X1");
|
||||
if (read_rc != INTERP_OK) {
|
||||
return 3;
|
||||
}
|
||||
const int execute_rc = interp.execute();
|
||||
if (execute_rc != INTERP_OK && execute_rc != INTERP_EXECUTE_FINISH) {
|
||||
return 4;
|
||||
}
|
||||
return std::fabs(sink.position().x - (start_x + 1.0)) < 1e-9 ? 0 : 5;
|
||||
}
|
||||
11
core/wasm_shims/rtapi_compat.cc
Normal file
11
core/wasm_shims/rtapi_compat.cc
Normal file
@@ -0,0 +1,11 @@
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
extern "C" int rtapi_snprintf(char *buf, unsigned long size, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
const int rc = std::vsnprintf(buf, static_cast<std::size_t>(size), fmt, ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
58
core/wasm_shims/tooldata/tooldata.hh
Normal file
58
core/wasm_shims/tooldata/tooldata.hh
Normal file
@@ -0,0 +1,58 @@
|
||||
#pragma once
|
||||
|
||||
#include "nml_intf/canon.hh"
|
||||
#include "nml_intf/emc_nml.hh"
|
||||
|
||||
extern "C" {
|
||||
|
||||
typedef enum {
|
||||
IDX_OK = 0,
|
||||
IDX_NEW,
|
||||
IDX_FAIL,
|
||||
} toolidx_t;
|
||||
|
||||
typedef enum {
|
||||
DB_NOTUSED = 0,
|
||||
DB_ACTIVE,
|
||||
} tooldb_t;
|
||||
|
||||
typedef enum {
|
||||
SPINDLE_LOAD,
|
||||
SPINDLE_UNLOAD,
|
||||
TOOL_OFFSET,
|
||||
} tool_notify_t;
|
||||
|
||||
struct CANON_TOOL_TABLE tooldata_entry_init(void);
|
||||
toolidx_t tooldata_put(struct CANON_TOOL_TABLE tdata, int idx);
|
||||
toolidx_t tooldata_get(CANON_TOOL_TABLE *pdata, int idx);
|
||||
|
||||
void tooldata_init(bool random_tool_changer);
|
||||
void tooldata_reset(void);
|
||||
void tooldata_last_index_set(int idx);
|
||||
int tooldata_last_index_get(void);
|
||||
int tooldata_find_index_for_tool(int toolno);
|
||||
|
||||
void tooldata_format_toolline(int idx,
|
||||
bool ignore_zero_values,
|
||||
CANON_TOOL_TABLE tdata,
|
||||
char formatted_line[CANON_TOOL_ENTRY_LEN]);
|
||||
|
||||
void tooldata_add_init(int nonrandom_start_idx);
|
||||
int tooldata_read_entry(const char *input_line);
|
||||
|
||||
void tooldata_set_db(tooldb_t mode);
|
||||
int tooldata_load(const char *filename);
|
||||
int tooldata_save(const char *filename);
|
||||
int tool_mmap_creator(EMC_TOOL_STAT const *ptr, int random_toolchanger);
|
||||
int tool_mmap_user(void);
|
||||
void tool_mmap_close(void);
|
||||
bool tool_mmap_is_random_toolchanger(void);
|
||||
int tool_nml_register(CANON_TOOL_TABLE *tblptr);
|
||||
int tooldata_db_init(char progname_plus_args[], int random_toolchanger);
|
||||
int tooldata_db_notify(tool_notify_t ntype,
|
||||
int toolno,
|
||||
int pocketno,
|
||||
CANON_TOOL_TABLE tdata);
|
||||
int tooldata_db_getall(void);
|
||||
|
||||
} // extern "C"
|
||||
101
core/wasm_shims/tooldata/tooldata_common_probe_main.cc
Normal file
101
core/wasm_shims/tooldata/tooldata_common_probe_main.cc
Normal file
@@ -0,0 +1,101 @@
|
||||
#include "tooldata.hh"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
|
||||
std::string make_temp_template(const char *name) {
|
||||
const char *tmpdir = std::getenv("TMPDIR");
|
||||
std::string tmpl = std::string(tmpdir ? tmpdir : "/tmp") + "/" + name;
|
||||
return tmpl;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
if (tool_mmap_user() != -1) {
|
||||
return 11;
|
||||
}
|
||||
if (tool_mmap_creator(nullptr, 1) != 0) {
|
||||
return 12;
|
||||
}
|
||||
if (tool_mmap_user() != 0) {
|
||||
return 13;
|
||||
}
|
||||
if (!tool_mmap_is_random_toolchanger()) {
|
||||
return 14;
|
||||
}
|
||||
|
||||
tooldata_init(true);
|
||||
tooldata_reset();
|
||||
tooldata_add_init(0);
|
||||
|
||||
if (tooldata_read_entry("T7 P12 Z3.5 D8 ;probe\n") != 12) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
CANON_TOOL_TABLE loaded = tooldata_entry_init();
|
||||
if (tooldata_get(&loaded, 12) != IDX_OK) {
|
||||
return 2;
|
||||
}
|
||||
if (loaded.toolno != 7 || loaded.pocketno != 12 ||
|
||||
loaded.offset.tran.z != 3.5 || loaded.diameter != 8.0 ||
|
||||
std::strcmp(loaded.comment, "probe") != 0) {
|
||||
return 3;
|
||||
}
|
||||
|
||||
char line[CANON_TOOL_ENTRY_LEN] = {};
|
||||
tooldata_format_toolline(12, true, loaded, line);
|
||||
if (!std::strstr(line, "T7") || !std::strstr(line, "P12") ||
|
||||
!std::strstr(line, "D+8.000000") || !std::strstr(line, ";probe")) {
|
||||
return 4;
|
||||
}
|
||||
|
||||
std::string path_template = make_temp_template("cnc_tooldata_common_probe_XXXXXX");
|
||||
std::vector<char> path(path_template.begin(), path_template.end());
|
||||
path.push_back('\0');
|
||||
const int fd = mkstemp(path.data());
|
||||
if (fd < 0) {
|
||||
return 5;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (tooldata_save(path.data()) != 0) {
|
||||
std::remove(path.data());
|
||||
return 6;
|
||||
}
|
||||
|
||||
tooldata_reset();
|
||||
if (tooldata_find_index_for_tool(7) != -1) {
|
||||
std::remove(path.data());
|
||||
return 7;
|
||||
}
|
||||
if (tooldata_load(path.data()) != 0) {
|
||||
std::remove(path.data());
|
||||
return 8;
|
||||
}
|
||||
std::remove(path.data());
|
||||
|
||||
if (tooldata_get(&loaded, 12) != IDX_OK || loaded.toolno != 7 ||
|
||||
loaded.pocketno != 12 || loaded.offset.tran.z != 3.5 ||
|
||||
loaded.diameter != 8.0) {
|
||||
return 9;
|
||||
}
|
||||
|
||||
tooldata_set_db(DB_ACTIVE);
|
||||
if (tooldata_load(path.data()) != -1) {
|
||||
return 10;
|
||||
}
|
||||
|
||||
tool_mmap_close();
|
||||
if (tool_mmap_user() != -1) {
|
||||
return 15;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
127
core/wasm_shims/tooldata/tooldata_mmap_backend.cc
Normal file
127
core/wasm_shims/tooldata/tooldata_mmap_backend.cc
Normal file
@@ -0,0 +1,127 @@
|
||||
#include "tooldata.hh"
|
||||
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
|
||||
CANON_TOOL_TABLE tool_table[CANON_POCKETS_MAX];
|
||||
EMC_TOOL_STAT const *toolstat = nullptr;
|
||||
int last_index = 0;
|
||||
bool mmap_created = false;
|
||||
bool mmap_random_toolchanger = false;
|
||||
bool mmap_creator_called = false;
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
toolidx_t tooldata_put(CANON_TOOL_TABLE tdata, int idx) {
|
||||
if (!mmap_created) {
|
||||
return IDX_FAIL;
|
||||
}
|
||||
if (idx < 0 || idx >= CANON_POCKETS_MAX) {
|
||||
return IDX_FAIL;
|
||||
}
|
||||
|
||||
const toolidx_t result = idx > last_index ? IDX_NEW : IDX_OK;
|
||||
tool_table[idx] = tdata;
|
||||
if (idx > last_index) {
|
||||
last_index = idx;
|
||||
}
|
||||
if (idx == 0 && toolstat) {
|
||||
*(CANON_TOOL_TABLE *)(&toolstat->toolTableCurrent) = tdata;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
toolidx_t tooldata_get(CANON_TOOL_TABLE *pdata, int idx) {
|
||||
if (!mmap_created) {
|
||||
std::fprintf(stderr, "%5d tooldata_get() not mmapped BYE\n", getpid());
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
if (!pdata || idx < 0 || idx >= CANON_POCKETS_MAX) {
|
||||
return IDX_FAIL;
|
||||
}
|
||||
*pdata = tool_table[idx];
|
||||
return IDX_OK;
|
||||
}
|
||||
|
||||
void tooldata_reset(void) {
|
||||
if (!mmap_created) {
|
||||
return;
|
||||
}
|
||||
|
||||
const CANON_TOOL_TABLE empty = tooldata_entry_init();
|
||||
for (int idx = 0; idx < CANON_POCKETS_MAX; ++idx) {
|
||||
tool_table[idx] = empty;
|
||||
}
|
||||
}
|
||||
|
||||
void tooldata_last_index_set(int idx) {
|
||||
if (!mmap_created) {
|
||||
return;
|
||||
}
|
||||
if (idx < 0 || idx >= CANON_POCKETS_MAX) {
|
||||
idx = 0;
|
||||
}
|
||||
last_index = idx;
|
||||
}
|
||||
|
||||
int tooldata_last_index_get(void) {
|
||||
if (!mmap_created) {
|
||||
return -1;
|
||||
}
|
||||
return last_index;
|
||||
}
|
||||
|
||||
int tooldata_find_index_for_tool(int toolno) {
|
||||
if (!mmap_created || toolno == -1) {
|
||||
return -1;
|
||||
}
|
||||
if (!mmap_random_toolchanger && toolno == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int found = -1;
|
||||
for (int idx = 0; idx <= last_index && idx < CANON_POCKETS_MAX; ++idx) {
|
||||
if (tool_table[idx].toolno == toolno) {
|
||||
found = idx;
|
||||
if (idx != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
int tool_mmap_creator(EMC_TOOL_STAT const *ptr, int random_toolchanger) {
|
||||
if (mmap_creator_called) {
|
||||
std::fprintf(stderr, "Error: tool_mmap_creator already called BYE\n");
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
toolstat = ptr;
|
||||
mmap_creator_called = true;
|
||||
mmap_created = true;
|
||||
mmap_random_toolchanger = random_toolchanger;
|
||||
last_index = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tool_mmap_user(void) {
|
||||
return mmap_created ? 0 : -1;
|
||||
}
|
||||
|
||||
void tool_mmap_close(void) {
|
||||
mmap_created = false;
|
||||
mmap_random_toolchanger = false;
|
||||
toolstat = nullptr;
|
||||
last_index = 0;
|
||||
}
|
||||
|
||||
bool tool_mmap_is_random_toolchanger(void) {
|
||||
return mmap_random_toolchanger;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
340
core/wasm_shims/tooldata/tooldata_probe_main.cc
Normal file
340
core/wasm_shims/tooldata/tooldata_probe_main.cc
Normal file
@@ -0,0 +1,340 @@
|
||||
#include "tooldata/tooldata.hh"
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#include <vector>
|
||||
|
||||
namespace {
|
||||
|
||||
std::string make_temp_path(const char *name) {
|
||||
const char *tmpdir = std::getenv("TMPDIR");
|
||||
return std::string(tmpdir ? tmpdir : "/tmp") + "/" + name;
|
||||
}
|
||||
|
||||
class ScopedTempWorkdir {
|
||||
public:
|
||||
explicit ScopedTempWorkdir(const char *name_template) {
|
||||
cwd_fd_ = open(".", O_RDONLY);
|
||||
if (cwd_fd_ < 0) {
|
||||
return;
|
||||
}
|
||||
std::string path_template = make_temp_path(name_template);
|
||||
dir_buffer_.assign(path_template.begin(), path_template.end());
|
||||
dir_buffer_.push_back('\0');
|
||||
dir_ = mkdtemp(dir_buffer_.data());
|
||||
if (!dir_) {
|
||||
return;
|
||||
}
|
||||
if (chdir(dir_) != 0) {
|
||||
dir_ = nullptr;
|
||||
return;
|
||||
}
|
||||
ok_ = true;
|
||||
}
|
||||
|
||||
~ScopedTempWorkdir() {
|
||||
if (cwd_fd_ >= 0) {
|
||||
if (ok_) {
|
||||
fchdir(cwd_fd_);
|
||||
}
|
||||
close(cwd_fd_);
|
||||
}
|
||||
if (dir_) {
|
||||
rmdir(dir_);
|
||||
}
|
||||
}
|
||||
|
||||
bool ok() const {
|
||||
return ok_;
|
||||
}
|
||||
|
||||
private:
|
||||
int cwd_fd_ = -1;
|
||||
std::vector<char> dir_buffer_;
|
||||
char *dir_ = nullptr;
|
||||
bool ok_ = false;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
int main() {
|
||||
const pid_t creator_child = fork();
|
||||
if (creator_child < 0) {
|
||||
return 41;
|
||||
}
|
||||
if (creator_child == 0) {
|
||||
if (tool_mmap_creator(nullptr, 1) != 0) {
|
||||
_exit(42);
|
||||
}
|
||||
tool_mmap_creator(nullptr, 0);
|
||||
_exit(43);
|
||||
}
|
||||
int creator_status = 0;
|
||||
if (waitpid(creator_child, &creator_status, 0) != creator_child) {
|
||||
return 44;
|
||||
}
|
||||
if (!WIFEXITED(creator_status) || WEXITSTATUS(creator_status) == 0) {
|
||||
return 45;
|
||||
}
|
||||
|
||||
if (tool_mmap_user() != -1) {
|
||||
return 25;
|
||||
}
|
||||
CANON_TOOL_TABLE uncreated_tool = tooldata_entry_init();
|
||||
if (tooldata_put(uncreated_tool, 0) != IDX_FAIL) {
|
||||
return 27;
|
||||
}
|
||||
|
||||
const pid_t get_child = fork();
|
||||
if (get_child < 0) {
|
||||
return 46;
|
||||
}
|
||||
if (get_child == 0) {
|
||||
tooldata_get(&uncreated_tool, 0);
|
||||
_exit(47);
|
||||
}
|
||||
int get_status = 0;
|
||||
if (waitpid(get_child, &get_status, 0) != get_child) {
|
||||
return 48;
|
||||
}
|
||||
if (!WIFEXITED(get_status) || WEXITSTATUS(get_status) == 0) {
|
||||
return 38;
|
||||
}
|
||||
if (tooldata_last_index_get() != -1) {
|
||||
return 40;
|
||||
}
|
||||
if (tooldata_db_getall() != -1) {
|
||||
return 28;
|
||||
}
|
||||
std::string missing_db_program_with_arg_string =
|
||||
make_temp_path("cnc_tooldata_probe_missing_db_program arg");
|
||||
std::vector<char> missing_db_program_with_arg(
|
||||
missing_db_program_with_arg_string.begin(),
|
||||
missing_db_program_with_arg_string.end());
|
||||
missing_db_program_with_arg.push_back('\0');
|
||||
if (tooldata_db_init(missing_db_program_with_arg.data(), 1) != -1) {
|
||||
return 55;
|
||||
}
|
||||
const auto separator = missing_db_program_with_arg_string.find(' ');
|
||||
if (separator == std::string::npos || missing_db_program_with_arg[separator] != 0) {
|
||||
return 56;
|
||||
}
|
||||
std::string missing_db_program_string = make_temp_path("cnc_tooldata_probe_missing_db_program");
|
||||
std::vector<char> missing_db_program(
|
||||
missing_db_program_string.begin(),
|
||||
missing_db_program_string.end());
|
||||
missing_db_program.push_back('\0');
|
||||
if (tooldata_db_init(missing_db_program.data(), 1) != -1) {
|
||||
return 31;
|
||||
}
|
||||
char too_many_db_args[] = "/bin/true a b c d e f g h i";
|
||||
if (tooldata_db_init(too_many_db_args, 1) != -1) {
|
||||
return 32;
|
||||
}
|
||||
char non_db_program[] = "/bin/true";
|
||||
if (tooldata_db_init(non_db_program, 1) != -1) {
|
||||
return 33;
|
||||
}
|
||||
if (tool_nml_register(nullptr) != -1) {
|
||||
return 29;
|
||||
}
|
||||
alignas(EMC_TOOL_STAT) unsigned char toolstat_storage[sizeof(EMC_TOOL_STAT)] = {};
|
||||
auto *toolstat = reinterpret_cast<EMC_TOOL_STAT *>(toolstat_storage);
|
||||
if (tool_mmap_creator(toolstat, 1) != 0) {
|
||||
return 15;
|
||||
}
|
||||
if (tool_mmap_user() != 0) {
|
||||
return 26;
|
||||
}
|
||||
if (!tool_mmap_is_random_toolchanger()) {
|
||||
return 16;
|
||||
}
|
||||
tooldata_set_db(DB_ACTIVE);
|
||||
const std::string unavailable_db_path = make_temp_path("cnc_tooldata_probe_db_unavailable.tbl");
|
||||
if (tooldata_load(unavailable_db_path.c_str()) != -1) {
|
||||
return 30;
|
||||
}
|
||||
tooldata_set_db(DB_ACTIVE);
|
||||
tooldata_init(false);
|
||||
if (tooldata_save(nullptr) != 0) {
|
||||
return 34;
|
||||
}
|
||||
tooldata_set_db(DB_NOTUSED);
|
||||
tooldata_init(true);
|
||||
tooldata_reset();
|
||||
|
||||
CANON_TOOL_TABLE spindle = tooldata_entry_init();
|
||||
spindle.toolno = 0;
|
||||
spindle.pocketno = 0;
|
||||
if (tooldata_put(spindle, 0) != IDX_OK) {
|
||||
return 1;
|
||||
}
|
||||
if (toolstat->toolTableCurrent.toolno != 0 || toolstat->toolTableCurrent.pocketno != 0) {
|
||||
return 49;
|
||||
}
|
||||
|
||||
CANON_TOOL_TABLE tool = tooldata_entry_init();
|
||||
tool.toolno = 7;
|
||||
tool.pocketno = 12;
|
||||
tool.offset.tran.z = 3.5;
|
||||
tool.diameter = 8.0;
|
||||
std::strncpy(tool.comment, "probe", CANON_TOOL_COMMENT_SIZE - 1);
|
||||
if (tooldata_put(tool, 12) != IDX_NEW) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
CANON_TOOL_TABLE loaded = tooldata_entry_init();
|
||||
if (tooldata_get(&loaded, 12) != IDX_OK) {
|
||||
return 3;
|
||||
}
|
||||
if (loaded.toolno != 7 || loaded.pocketno != 12 || loaded.offset.tran.z != 3.5 || loaded.diameter != 8.0) {
|
||||
return 4;
|
||||
}
|
||||
char db_spindle_line[CANON_TOOL_ENTRY_LEN] = {};
|
||||
{
|
||||
ScopedTempWorkdir db_spindle_workdir("cnc_tooldata_probe_workdir.XXXXXX");
|
||||
if (!db_spindle_workdir.ok()) {
|
||||
return 35;
|
||||
}
|
||||
std::remove("./db_spindle.tbl");
|
||||
tooldata_set_db(DB_ACTIVE);
|
||||
if (tooldata_save(nullptr) != 0) {
|
||||
return 36;
|
||||
}
|
||||
FILE *db_spindle_fp = std::fopen("./db_spindle.tbl", "r");
|
||||
if (!db_spindle_fp) {
|
||||
return 37;
|
||||
}
|
||||
std::fread(db_spindle_line, 1, sizeof(db_spindle_line) - 1, db_spindle_fp);
|
||||
std::fclose(db_spindle_fp);
|
||||
std::remove("./db_spindle.tbl");
|
||||
tooldata_set_db(DB_NOTUSED);
|
||||
}
|
||||
if (!std::strstr(db_spindle_line, "T0") || std::strstr(db_spindle_line, "T7")) {
|
||||
return 38;
|
||||
}
|
||||
if (tooldata_find_index_for_tool(7) != 12) {
|
||||
return 5;
|
||||
}
|
||||
if (tooldata_find_index_for_tool(0) != 0) {
|
||||
return 6;
|
||||
}
|
||||
if (tooldata_find_index_for_tool(-1) != -1) {
|
||||
return 17;
|
||||
}
|
||||
|
||||
tooldata_init(false);
|
||||
if (tooldata_find_index_for_tool(0) != 0) {
|
||||
return 18;
|
||||
}
|
||||
tooldata_init(true);
|
||||
|
||||
tooldata_last_index_set(12);
|
||||
if (tooldata_last_index_get() != 12) {
|
||||
return 7;
|
||||
}
|
||||
if (tooldata_put(tool, -1) != IDX_FAIL) {
|
||||
return 50;
|
||||
}
|
||||
if (tooldata_put(tool, CANON_POCKETS_MAX) != IDX_FAIL) {
|
||||
return 51;
|
||||
}
|
||||
if (tooldata_last_index_get() != 12) {
|
||||
return 52;
|
||||
}
|
||||
if (tooldata_get(&loaded, -1) != IDX_FAIL) {
|
||||
return 53;
|
||||
}
|
||||
if (tooldata_get(&loaded, CANON_POCKETS_MAX) != IDX_FAIL) {
|
||||
return 54;
|
||||
}
|
||||
tooldata_last_index_set(CANON_POCKETS_MAX);
|
||||
if (tooldata_last_index_get() != 0) {
|
||||
return 24;
|
||||
}
|
||||
tooldata_last_index_set(12);
|
||||
|
||||
char line[CANON_TOOL_ENTRY_LEN] = {};
|
||||
tooldata_format_toolline(12, true, loaded, line);
|
||||
if (!std::strstr(line, "T7") || !std::strstr(line, "P12") || !std::strstr(line, "D+8.000000")) {
|
||||
return 8;
|
||||
}
|
||||
|
||||
std::string path_template = make_temp_path("cnc_tooldata_probe_XXXXXX");
|
||||
std::vector<char> path(path_template.begin(), path_template.end());
|
||||
path.push_back('\0');
|
||||
const int fd = mkstemp(path.data());
|
||||
if (fd < 0) {
|
||||
return 9;
|
||||
}
|
||||
close(fd);
|
||||
tooldata_last_index_set(0);
|
||||
if (tooldata_save(path.data()) != 0) {
|
||||
std::remove(path.data());
|
||||
return 10;
|
||||
}
|
||||
|
||||
tooldata_reset();
|
||||
if (tooldata_find_index_for_tool(7) != -1) {
|
||||
std::remove(path.data());
|
||||
return 11;
|
||||
}
|
||||
if (tooldata_load(path.data()) != 0) {
|
||||
std::remove(path.data());
|
||||
return 12;
|
||||
}
|
||||
std::remove(path.data());
|
||||
|
||||
CANON_TOOL_TABLE reloaded = tooldata_entry_init();
|
||||
if (tooldata_get(&reloaded, 12) != IDX_OK) {
|
||||
return 13;
|
||||
}
|
||||
if (reloaded.toolno != 7 || reloaded.pocketno != 12 ||
|
||||
reloaded.offset.tran.z != 3.5 || reloaded.diameter != 8.0) {
|
||||
return 14;
|
||||
}
|
||||
|
||||
tooldata_init(false);
|
||||
std::string nonrandom_path_template = make_temp_path("cnc_tooldata_nonrandom_probe_XXXXXX");
|
||||
std::vector<char> nonrandom_path(nonrandom_path_template.begin(), nonrandom_path_template.end());
|
||||
nonrandom_path.push_back('\0');
|
||||
const int nonrandom_fd = mkstemp(nonrandom_path.data());
|
||||
if (nonrandom_fd < 0) {
|
||||
return 19;
|
||||
}
|
||||
FILE *nonrandom_fp = fdopen(nonrandom_fd, "w");
|
||||
if (!nonrandom_fp) {
|
||||
close(nonrandom_fd);
|
||||
std::remove(nonrandom_path.data());
|
||||
return 20;
|
||||
}
|
||||
std::fputs("T-1 P5 Z4.25\n", nonrandom_fp);
|
||||
std::fclose(nonrandom_fp);
|
||||
|
||||
if (tooldata_load(nonrandom_path.data()) != 0) {
|
||||
std::remove(nonrandom_path.data());
|
||||
return 21;
|
||||
}
|
||||
std::remove(nonrandom_path.data());
|
||||
|
||||
CANON_TOOL_TABLE nonrandom_spindle = tooldata_entry_init();
|
||||
if (tooldata_get(&nonrandom_spindle, 0) != IDX_OK) {
|
||||
return 22;
|
||||
}
|
||||
if (nonrandom_spindle.toolno != -1 || nonrandom_spindle.pocketno != 5 ||
|
||||
nonrandom_spindle.offset.tran.z != 4.25) {
|
||||
return 23;
|
||||
}
|
||||
|
||||
tool_mmap_close();
|
||||
if (tool_mmap_user() != -1) {
|
||||
return 39;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
47
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc
Normal file
47
core/wasm_shims/tooldata/tooldata_runtime_stubs.cc
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "tooldata.hh"
|
||||
|
||||
#include <cstring>
|
||||
#include <unistd.h>
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int MAX_DB_PROGRAM_ARGS = 10;
|
||||
bool db_live = false;
|
||||
|
||||
} // namespace
|
||||
|
||||
extern "C" {
|
||||
|
||||
int tool_nml_register(CANON_TOOL_TABLE *tblptr) {
|
||||
return tblptr ? 0 : -1;
|
||||
}
|
||||
|
||||
int tooldata_db_init(char progname_plus_args[], int) {
|
||||
if (!progname_plus_args) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *saveptr = nullptr;
|
||||
char *program = strtok_r(progname_plus_args, " ", &saveptr);
|
||||
int argc = 0;
|
||||
for (char *token = program; token; token = strtok_r(nullptr, " ", &saveptr)) {
|
||||
++argc;
|
||||
if (argc >= MAX_DB_PROGRAM_ARGS) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (!program || access(program, X_OK) != 0) {
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
int tooldata_db_notify(tool_notify_t, int, int, CANON_TOOL_TABLE) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tooldata_db_getall(void) {
|
||||
return db_live ? 0 : -1;
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
Reference in New Issue
Block a user