diff --git a/src/emc/canterp/canterp.cc b/src/emc/canterp/canterp.cc index cb95320cf91..8cf41d17d5f 100644 --- a/src/emc/canterp/canterp.cc +++ b/src/emc/canterp/canterp.cc @@ -66,11 +66,11 @@ static char the_command_args[LINELEN] = { 0 }; // just the args part class Canterp : public InterpBase { public: - Canterp () : f(NULL), filename{} {} - char *error_text(int errcode, char *buf, size_t buflen) override; - char *stack_name(int index, char *buf, size_t buflen) override; - char *line_text(char *buf, size_t buflen) override; - char *file_name(char *buf, size_t buflen) override; + Canterp () : f(NULL) {} + std::string error_text(int errcode) override; + std::string stack_name(int index) override; + std::string line_text() override; + std::string file_name() override; size_t line_length() override; int sequence_number() override; int ini_load(const char *inifile) override; @@ -87,8 +87,8 @@ class Canterp : public InterpBase { int reset() override; int line() override; int call_level() override; - char *command(char *buf, size_t buflen) override; - char *file(char *buf, size_t buflen) override; + std::string command() override; + std::string file() override; int on_abort(int reason, const char *message) override; void active_g_codes(int active_gcodes[ACTIVE_G_CODES]) override; void active_m_codes(int active_mcodes[ACTIVE_M_CODES]) override; @@ -103,18 +103,16 @@ class Canterp : public InterpBase { void set_loop_on_main_m99(bool state) override; FILE* get_stdout() override { return NULL; }; FILE *f; - char filename[PATH_MAX]; + std::string filename; }; -char *Canterp::error_text(int errcode, char *buf, size_t buflen) { - if(errcode < INTERP_MIN_ERROR) snprintf(buf, buflen, "OK %d", errcode); - else snprintf(buf, buflen, "ERROR %d", errcode); - return buf; +std::string Canterp::error_text(int errcode) { + return (errcode < INTERP_MIN_ERROR ? "OK " : "ERROR ") + std::to_string(errcode); } -char *Canterp::stack_name(int index, char *buf, size_t buflen) { - snprintf(buf, buflen, "", index); - return buf; +// canterp has no call stack; an empty name ends the caller's loop +std::string Canterp::stack_name(int /*index*/) { + return {}; } int Canterp::ini_load(const char * /*inifile*/) { @@ -697,7 +695,7 @@ int Canterp::execute() { int Canterp::open(const char *newfilename) { if(f) fclose(f); f = fopen(newfilename, "r"); - if(f) snprintf(filename, sizeof(filename), "%s", newfilename); + if(f) filename = newfilename; return f ? INTERP_OK : INTERP_ERROR; } @@ -715,17 +713,14 @@ int Canterp::reset() { return 0; } int Canterp::line() { return 0; } int Canterp::call_level() { return 0; } -char *Canterp::line_text(char *buf, size_t bufsize) { - snprintf(buf, bufsize, ""); - return buf; +std::string Canterp::line_text() { + return ""; } -char *Canterp::file_name(char *buf, size_t bufsize) { - snprintf(buf, bufsize, "%s", filename); - return buf; +std::string Canterp::file_name() { + return filename; } -char *Canterp::file(char *buf, size_t bufsize) { - snprintf(buf, bufsize, "%s", filename); - return buf; +std::string Canterp::file() { + return filename; } int Canterp::on_abort(int reason, const char *message) { @@ -733,9 +728,8 @@ int Canterp::on_abort(int reason, const char *message) reset(); return INTERP_OK; } -char *Canterp::command(char *buf, size_t bufsize) { - snprintf(buf, bufsize, ""); - return buf; +std::string Canterp::command() { + return ""; } size_t Canterp::line_length() { return 0; diff --git a/src/emc/nml_intf/canon.hh b/src/emc/nml_intf/canon.hh index 9a0a4de911c..0ccddf78b4a 100644 --- a/src/emc/nml_intf/canon.hh +++ b/src/emc/nml_intf/canon.hh @@ -14,6 +14,8 @@ #define CANON_HH #include // FILE +#include +#include #include #include @@ -522,80 +524,6 @@ extern void STRAIGHT_FEED(int lineno, double a, double b, double c, double u, double v, double w); -/* Additional functions needed to calculate nurbs G5 points */ - -extern std::vector nurbs_G5_knot_vector_creator(unsigned int n, unsigned int k); - -extern double nurbs_G5_Nmix(unsigned int i, unsigned int k, double u, const std::vector& knot_vector); - -extern double nurbs_G5_Rden(double u, unsigned int k, - const std::vector& nurbs_control_points, - const std::vector& knot_vector); - -extern NURBS_PLANE_POINT nurbs_G5_point(double u, unsigned int k, - const std::vector& nurbs_control_points, - const std::vector& knot_vector); - -extern NURBS_PLANE_POINT nurbs_G5_tangent(double u, unsigned int k, - const std::vector& nurbs_control_points, - const std::vector& knot_vector); - -/* Additional functions needed to calculate nurbs points G_6_2*/ - -extern std::vector nurbs_g6_knot_vector_creator(unsigned int n, unsigned int k, const std::vector& nurbs_control_points); - -std::vector nurbs_interval_span_knot_vector_creator(unsigned int n, unsigned int k, const std::vector& knot_vector_); - -extern double nurbs_lderv(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); - -extern double nurbs_Sa1_b1_length_(double a1, double b1, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); - -extern std::vector nurbs_lenght_vector_creator(unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector& span_knot_vector); - -extern double nurbs_lenght_tot(int j, const std::vector& span_knot_vector, const std::vector& lenght_vector); - -extern double nurbs_lenght_l_u(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector& span_knot_vector, const std::vector& lenght_vector); - -extern std::vector nurbs_Du_span_knot_vector_creator(unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector& span_knot_vector); - -extern std::vector nurbs_costant_crator(const std::vector& span_knot_vector, const std::vector& lenght_vector, const std::vector& Du_span_knot_vector); - -extern double nurbs_uj_l(double l, const std::vector& span_knot_vector, const std::vector& lenght_vector, const std::vector& nurbs_costant); - -/* Funzioni di supporto all'algoritmo di suddivisione */ -extern std::vector nurbs_G6_new_control_point_nurbs1(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_ ); - -extern std::vector nurbs_G6_new_control_point_nurbs2(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_ ); - -extern std::vector nurbs_G6_knot_vector_new_creator_sgment(unsigned int k, const std::vector& nurbs_control_points); -/* ... */ - -extern double nurbs_G6_Nmix(unsigned int i, unsigned int k, double u, const std::vector& knot_vector_); - -extern std::vector< std::vector > nurbs_G6_Nmix_creator(double u, unsigned int k, double n, const std::vector& knot_vector_); - -extern double nurbs_G6_Rden(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); - -extern NURBS_PLANE_POINT nurbs_G6_point(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); - -extern double nurbs_G6_Rdenx(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector< std::vector >& A6); - -extern NURBS_PLANE_POINT nurbs_G6_pointx(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector< std::vector >& A6); - -extern NURBS_PLANE_POINT nurbs_G6_point_x(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); - -extern NURBS_PLANE_POINT nurbs_G6_tangent_x(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); - -/*Funzioni di supporto all'algoritmo di suddivisione********************************************************************/ -extern std::vector nurbs_G6_new_control_point_nurbs1(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_ ); - -extern std::vector nurbs_G6_new_control_point_nurbs2(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_ ); - -extern std::vector nurbs_G6_knot_vector_new_creator_sgment(unsigned int k, const std::vector& nurbs_control_points); - -/* End of NURBS functions*/ - - /* Canon calls */ extern void NURBS_G5_FEED(int lineno, const std::vector& nurbs_control_points, unsigned int nurbs_order, CANON_PLANE plane); @@ -606,8 +534,6 @@ extern void NURBS_G5_FEED(int lineno, const std::vector& nu extern void NURBS_G6_FEED(int lineno, const std::vector& nurbs_control_points, unsigned int k, double feedrate, int l, CANON_PLANE plane); // this is for G6xx -extern double alpha_finder(double dx, double dy); - /********************************************************************************************************************/ @@ -737,7 +663,7 @@ controller. An attempt to move an axis while it is clamped should result in an error condition in the controller. */ -extern void COMMENT(const char *s); +extern void COMMENT(std::string_view s); /* This function has no physical effect. If commands are being printed or logged, the comment command is printed or logged, including the string @@ -768,11 +694,11 @@ extern void FLOOD_OFF(); extern void FLOOD_ON(); /* Turn flood coolant on. */ -extern void MESSAGE(char *s); +extern void MESSAGE(std::string_view s); -extern void LOG(char *s); -extern void LOGOPEN(char *s); -extern void LOGAPPEND(char *s); +extern void LOG(std::string_view s); +extern void LOGOPEN(std::string_view filename); +extern void LOGAPPEND(std::string_view filename); extern void LOGCLOSE(); extern void MIST_OFF(); @@ -969,55 +895,22 @@ extern double GET_EXTERNAL_ORIGIN_Z(); */ -// returns nothing but copies the name of the parameter file into -// the filename array, stopping at max_size if the name is longer -// An empty string may be placed in filename. -extern void GET_EXTERNAL_PARAMETER_FILE_NAME(char *filename, int max_size); +// returns the name of the parameter file, or an empty string if none is set +extern std::string GET_EXTERNAL_PARAMETER_FILE_NAME(); -extern void SET_PARAMETER_FILE_NAME(const char *name); +extern void SET_PARAMETER_FILE_NAME(std::string_view name); // returns the currently active plane extern CANON_PLANE GET_EXTERNAL_PLANE(); -// returns the current a-axis position -extern double GET_EXTERNAL_POSITION_A(); - -// returns the current b-axis position -extern double GET_EXTERNAL_POSITION_B(); - -// returns the current c-axis position -extern double GET_EXTERNAL_POSITION_C(); - -// returns the current x-axis position -extern double GET_EXTERNAL_POSITION_X(); - -// returns the current y-axis position -extern double GET_EXTERNAL_POSITION_Y(); - -// returns the current z-axis position -extern double GET_EXTERNAL_POSITION_Z(); - -// returns the current u-axis position -extern double GET_EXTERNAL_POSITION_U(); - -// returns the current v-axis position -extern double GET_EXTERNAL_POSITION_V(); - -// returns the current w-axis position -extern double GET_EXTERNAL_POSITION_W(); +// returns the current position of all nine axes, in program units +// and the current work coordinate system +extern CANON_POSITION GET_EXTERNAL_POSITION(); -// Returns the position of the specified axis at the last probe trip, +// Returns the position of all axes at the last probe trip, // in the current work coordinate system. -extern double GET_EXTERNAL_PROBE_POSITION_A(); -extern double GET_EXTERNAL_PROBE_POSITION_B(); -extern double GET_EXTERNAL_PROBE_POSITION_C(); -extern double GET_EXTERNAL_PROBE_POSITION_X(); -extern double GET_EXTERNAL_PROBE_POSITION_Y(); -extern double GET_EXTERNAL_PROBE_POSITION_Z(); -extern double GET_EXTERNAL_PROBE_POSITION_U(); -extern double GET_EXTERNAL_PROBE_POSITION_V(); -extern double GET_EXTERNAL_PROBE_POSITION_W(); +extern CANON_POSITION GET_EXTERNAL_PROBE_POSITION(); // Returns the value for any analog non-contact probing. extern double GET_EXTERNAL_PROBE_VALUE(); @@ -1035,16 +928,8 @@ extern double GET_EXTERNAL_SPEED(int spindle); // Returns the system value for direction of spindle turning extern CANON_DIRECTION GET_EXTERNAL_SPINDLE(int spindle); -// returns current tool length offset -extern double GET_EXTERNAL_TOOL_LENGTH_XOFFSET(); -extern double GET_EXTERNAL_TOOL_LENGTH_YOFFSET(); -extern double GET_EXTERNAL_TOOL_LENGTH_ZOFFSET(); -extern double GET_EXTERNAL_TOOL_LENGTH_AOFFSET(); -extern double GET_EXTERNAL_TOOL_LENGTH_BOFFSET(); -extern double GET_EXTERNAL_TOOL_LENGTH_COFFSET(); -extern double GET_EXTERNAL_TOOL_LENGTH_UOFFSET(); -extern double GET_EXTERNAL_TOOL_LENGTH_VOFFSET(); -extern double GET_EXTERNAL_TOOL_LENGTH_WOFFSET(); +// returns current tool length offset, in program units +extern EmcPose GET_EXTERNAL_TOOL_LENGTH_OFFSET(); // Returns the system value for the carousel slot in which the tool // currently in the spindle belongs. Return value zero means there is no @@ -1089,7 +974,6 @@ extern double GET_EXTERNAL_ANALOG_INPUT(int index, double def); extern int GET_EXTERNAL_AXIS_MASK(); -#define PARAMETER_FILE_NAME_LENGTH 100 #define USER_DEFINED_FUNCTION_NUM 100 typedef void (*USER_DEFINED_FUNCTION_TYPE) (int num, double arg1, @@ -1108,7 +992,7 @@ extern void FINISH(void); extern void ON_RESET(void); // expose CANON_ERROR -extern void CANON_ERROR(const char *fmt, ...) __attribute__((format(printf,1,2))); +extern void CANON_ERROR(std::string_view message); extern int GET_EXTERNAL_OFFSET_APPLIED(); extern EmcPose GET_EXTERNAL_OFFSETS(); diff --git a/src/emc/nml_intf/nurbs_math.hh b/src/emc/nml_intf/nurbs_math.hh new file mode 100644 index 00000000000..659f8566ecc --- /dev/null +++ b/src/emc/nml_intf/nurbs_math.hh @@ -0,0 +1,80 @@ +/******************************************************************** +* Description: nurbs_math.hh +* Math helpers for evaluating the NURBS curves of G5.2 and G6.2. +* They are plain functions, not canonical commands; the canon +* implementations use them to turn NURBS_G5_FEED/NURBS_G6_FEED +* into line segments. +* +* License: GPL Version 2 +********************************************************************/ +#ifndef NURBS_MATH_HH +#define NURBS_MATH_HH + +#include +#include "canon.hh" // NURBS_CONTROL_POINT, NURBS_G6_CONTROL_POINT, NURBS_PLANE_POINT + +/* Additional functions needed to calculate nurbs G5 points */ + +std::vector nurbs_G5_knot_vector_creator(unsigned int n, unsigned int k); + +double nurbs_G5_Nmix(unsigned int i, unsigned int k, double u, const std::vector& knot_vector); + +double nurbs_G5_Rden(double u, unsigned int k, + const std::vector& nurbs_control_points, + const std::vector& knot_vector); + +NURBS_PLANE_POINT nurbs_G5_point(double u, unsigned int k, + const std::vector& nurbs_control_points, + const std::vector& knot_vector); + +NURBS_PLANE_POINT nurbs_G5_tangent(double u, unsigned int k, + const std::vector& nurbs_control_points, + const std::vector& knot_vector); + +/* Additional functions needed to calculate nurbs points G_6_2*/ + +std::vector nurbs_g6_knot_vector_creator(unsigned int n, unsigned int k, const std::vector& nurbs_control_points); + +std::vector nurbs_interval_span_knot_vector_creator(unsigned int n, unsigned int k, const std::vector& knot_vector_); + +double nurbs_lderv(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); + +double nurbs_Sa1_b1_length_(double a1, double b1, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); + +std::vector nurbs_lenght_vector_creator(unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector& span_knot_vector); + +double nurbs_lenght_tot(int j, const std::vector& span_knot_vector, const std::vector& lenght_vector); + +double nurbs_lenght_l_u(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector& span_knot_vector, const std::vector& lenght_vector); + +std::vector nurbs_Du_span_knot_vector_creator(unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector& span_knot_vector); + +std::vector nurbs_costant_crator(const std::vector& span_knot_vector, const std::vector& lenght_vector, const std::vector& Du_span_knot_vector); + +double nurbs_uj_l(double l, const std::vector& span_knot_vector, const std::vector& lenght_vector, const std::vector& nurbs_costant); + +/* Funzioni di supporto all'algoritmo di suddivisione */ +std::vector nurbs_G6_new_control_point_nurbs1(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_ ); + +std::vector nurbs_G6_new_control_point_nurbs2(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_ ); + +std::vector nurbs_G6_knot_vector_new_creator_sgment(unsigned int k, const std::vector& nurbs_control_points); +/* ... */ + +double nurbs_G6_Nmix(unsigned int i, unsigned int k, double u, const std::vector& knot_vector_); + +std::vector< std::vector > nurbs_G6_Nmix_creator(double u, unsigned int k, double n, const std::vector& knot_vector_); + +double nurbs_G6_Rden(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); + +NURBS_PLANE_POINT nurbs_G6_point(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); + +double nurbs_G6_Rdenx(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector< std::vector >& A6); + +NURBS_PLANE_POINT nurbs_G6_pointx(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_, const std::vector< std::vector >& A6); + +NURBS_PLANE_POINT nurbs_G6_point_x(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); + +NURBS_PLANE_POINT nurbs_G6_tangent_x(double u, unsigned int k, const std::vector& nurbs_control_points, const std::vector& knot_vector_); + +#endif diff --git a/src/emc/rs274ngc/canonmodule.cc b/src/emc/rs274ngc/canonmodule.cc index 66138b48bfb..169c77d913a 100644 --- a/src/emc/rs274ngc/canonmodule.cc +++ b/src/emc/rs274ngc/canonmodule.cc @@ -28,14 +28,18 @@ namespace bp = boost::python; #include "rs274ngc_interp.hh" #include "interp_queue.hh" -static void wrap_canon_error(const char *s) +static void wrap_canon_error(const std::string &s) { - if ((s == NULL) || (strlen(s) == 0)) { + if (s.empty()) { return; } - CANON_ERROR("%s", s); + CANON_ERROR(s); } +// Boost.Python has no std::string_view converter. +template +static void wrap_text(const std::string &s) { F(s); } + #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant" @@ -109,7 +113,7 @@ BOOST_PYTHON_MODULE(emccanon) { def("CLAMP_AXIS",&CLAMP_AXIS); def("CLEAR_AUX_OUTPUT_BIT",&CLEAR_AUX_OUTPUT_BIT); def("CLEAR_MOTION_OUTPUT_BIT",&CLEAR_MOTION_OUTPUT_BIT); - def("COMMENT",&COMMENT); + def("COMMENT",&wrap_text); def("DISABLE_ADAPTIVE_FEED",&DISABLE_ADAPTIVE_FEED); def("DISABLE_FEED_HOLD",&DISABLE_FEED_HOLD); def("DISABLE_FEED_OVERRIDE",&DISABLE_FEED_OVERRIDE); @@ -138,29 +142,39 @@ BOOST_PYTHON_MODULE(emccanon) { def("GET_EXTERNAL_MIST",&GET_EXTERNAL_MIST); def("GET_EXTERNAL_MOTION_CONTROL_MODE",&GET_EXTERNAL_MOTION_CONTROL_MODE); def("GET_EXTERNAL_MOTION_CONTROL_TOLERANCE",&GET_EXTERNAL_MOTION_CONTROL_TOLERANCE); - def("SET_PARAMETER_FILE_NAME",&SET_PARAMETER_FILE_NAME); + def("SET_PARAMETER_FILE_NAME",&wrap_text); def("GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE", &GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE); def("GET_EXTERNAL_PARAMETER_FILE_NAME",&GET_EXTERNAL_PARAMETER_FILE_NAME); def("GET_EXTERNAL_PLANE",&GET_EXTERNAL_PLANE); - def("GET_EXTERNAL_POSITION_A",&GET_EXTERNAL_POSITION_A); - def("GET_EXTERNAL_POSITION_B",&GET_EXTERNAL_POSITION_B); - def("GET_EXTERNAL_POSITION_C",&GET_EXTERNAL_POSITION_C); - def("GET_EXTERNAL_POSITION_U",&GET_EXTERNAL_POSITION_U); - def("GET_EXTERNAL_POSITION_V",&GET_EXTERNAL_POSITION_V); - def("GET_EXTERNAL_POSITION_W",&GET_EXTERNAL_POSITION_W); - def("GET_EXTERNAL_POSITION_X",&GET_EXTERNAL_POSITION_X); - def("GET_EXTERNAL_POSITION_Y",&GET_EXTERNAL_POSITION_Y); - def("GET_EXTERNAL_POSITION_Z",&GET_EXTERNAL_POSITION_Z); - def("GET_EXTERNAL_PROBE_POSITION_A",&GET_EXTERNAL_PROBE_POSITION_A); - def("GET_EXTERNAL_PROBE_POSITION_B",&GET_EXTERNAL_PROBE_POSITION_B); - def("GET_EXTERNAL_PROBE_POSITION_C",&GET_EXTERNAL_PROBE_POSITION_C); - def("GET_EXTERNAL_PROBE_POSITION_U",&GET_EXTERNAL_PROBE_POSITION_U); - def("GET_EXTERNAL_PROBE_POSITION_V",&GET_EXTERNAL_PROBE_POSITION_V); - def("GET_EXTERNAL_PROBE_POSITION_W",&GET_EXTERNAL_PROBE_POSITION_W); - def("GET_EXTERNAL_PROBE_POSITION_X",&GET_EXTERNAL_PROBE_POSITION_X); - def("GET_EXTERNAL_PROBE_POSITION_Y",&GET_EXTERNAL_PROBE_POSITION_Y); - def("GET_EXTERNAL_PROBE_POSITION_Z",&GET_EXTERNAL_PROBE_POSITION_Z); + // The canon interface returns whole poses; Python keeps the per-axis names. + def("GET_EXTERNAL_POSITION_X", +[]() { return GET_EXTERNAL_POSITION().x; }); + def("GET_EXTERNAL_POSITION_Y", +[]() { return GET_EXTERNAL_POSITION().y; }); + def("GET_EXTERNAL_POSITION_Z", +[]() { return GET_EXTERNAL_POSITION().z; }); + def("GET_EXTERNAL_POSITION_A", +[]() { return GET_EXTERNAL_POSITION().a; }); + def("GET_EXTERNAL_POSITION_B", +[]() { return GET_EXTERNAL_POSITION().b; }); + def("GET_EXTERNAL_POSITION_C", +[]() { return GET_EXTERNAL_POSITION().c; }); + def("GET_EXTERNAL_POSITION_U", +[]() { return GET_EXTERNAL_POSITION().u; }); + def("GET_EXTERNAL_POSITION_V", +[]() { return GET_EXTERNAL_POSITION().v; }); + def("GET_EXTERNAL_POSITION_W", +[]() { return GET_EXTERNAL_POSITION().w; }); + def("GET_EXTERNAL_PROBE_POSITION_X", +[]() { return GET_EXTERNAL_PROBE_POSITION().x; }); + def("GET_EXTERNAL_PROBE_POSITION_Y", +[]() { return GET_EXTERNAL_PROBE_POSITION().y; }); + def("GET_EXTERNAL_PROBE_POSITION_Z", +[]() { return GET_EXTERNAL_PROBE_POSITION().z; }); + def("GET_EXTERNAL_PROBE_POSITION_A", +[]() { return GET_EXTERNAL_PROBE_POSITION().a; }); + def("GET_EXTERNAL_PROBE_POSITION_B", +[]() { return GET_EXTERNAL_PROBE_POSITION().b; }); + def("GET_EXTERNAL_PROBE_POSITION_C", +[]() { return GET_EXTERNAL_PROBE_POSITION().c; }); + def("GET_EXTERNAL_PROBE_POSITION_U", +[]() { return GET_EXTERNAL_PROBE_POSITION().u; }); + def("GET_EXTERNAL_PROBE_POSITION_V", +[]() { return GET_EXTERNAL_PROBE_POSITION().v; }); + def("GET_EXTERNAL_PROBE_POSITION_W", +[]() { return GET_EXTERNAL_PROBE_POSITION().w; }); + def("GET_EXTERNAL_TOOL_LENGTH_XOFFSET", +[]() { return GET_EXTERNAL_TOOL_LENGTH_OFFSET().tran.x; }); + def("GET_EXTERNAL_TOOL_LENGTH_YOFFSET", +[]() { return GET_EXTERNAL_TOOL_LENGTH_OFFSET().tran.y; }); + def("GET_EXTERNAL_TOOL_LENGTH_ZOFFSET", +[]() { return GET_EXTERNAL_TOOL_LENGTH_OFFSET().tran.z; }); + def("GET_EXTERNAL_TOOL_LENGTH_AOFFSET", +[]() { return GET_EXTERNAL_TOOL_LENGTH_OFFSET().a; }); + def("GET_EXTERNAL_TOOL_LENGTH_BOFFSET", +[]() { return GET_EXTERNAL_TOOL_LENGTH_OFFSET().b; }); + def("GET_EXTERNAL_TOOL_LENGTH_COFFSET", +[]() { return GET_EXTERNAL_TOOL_LENGTH_OFFSET().c; }); + def("GET_EXTERNAL_TOOL_LENGTH_UOFFSET", +[]() { return GET_EXTERNAL_TOOL_LENGTH_OFFSET().u; }); + def("GET_EXTERNAL_TOOL_LENGTH_VOFFSET", +[]() { return GET_EXTERNAL_TOOL_LENGTH_OFFSET().v; }); + def("GET_EXTERNAL_TOOL_LENGTH_WOFFSET", +[]() { return GET_EXTERNAL_TOOL_LENGTH_OFFSET().w; }); def("GET_EXTERNAL_PROBE_TRIPPED_VALUE",&GET_EXTERNAL_PROBE_TRIPPED_VALUE); def("GET_EXTERNAL_PROBE_VALUE",&GET_EXTERNAL_PROBE_VALUE); def("GET_EXTERNAL_QUEUE_EMPTY",&GET_EXTERNAL_QUEUE_EMPTY); @@ -169,15 +183,6 @@ BOOST_PYTHON_MODULE(emccanon) { def("GET_EXTERNAL_SPINDLE",&GET_EXTERNAL_SPINDLE); def("GET_EXTERNAL_SPINDLE_OVERRIDE_ENABLE",&GET_EXTERNAL_SPINDLE_OVERRIDE_ENABLE); def("GET_EXTERNAL_TC_FAULT",&GET_EXTERNAL_TC_FAULT); - def("GET_EXTERNAL_TOOL_LENGTH_AOFFSET",&GET_EXTERNAL_TOOL_LENGTH_AOFFSET); - def("GET_EXTERNAL_TOOL_LENGTH_BOFFSET",&GET_EXTERNAL_TOOL_LENGTH_BOFFSET); - def("GET_EXTERNAL_TOOL_LENGTH_COFFSET",&GET_EXTERNAL_TOOL_LENGTH_COFFSET); - def("GET_EXTERNAL_TOOL_LENGTH_UOFFSET",&GET_EXTERNAL_TOOL_LENGTH_UOFFSET); - def("GET_EXTERNAL_TOOL_LENGTH_VOFFSET",&GET_EXTERNAL_TOOL_LENGTH_VOFFSET); - def("GET_EXTERNAL_TOOL_LENGTH_WOFFSET",&GET_EXTERNAL_TOOL_LENGTH_WOFFSET); - def("GET_EXTERNAL_TOOL_LENGTH_XOFFSET",&GET_EXTERNAL_TOOL_LENGTH_XOFFSET); - def("GET_EXTERNAL_TOOL_LENGTH_YOFFSET",&GET_EXTERNAL_TOOL_LENGTH_YOFFSET); - def("GET_EXTERNAL_TOOL_LENGTH_ZOFFSET",&GET_EXTERNAL_TOOL_LENGTH_ZOFFSET); def("GET_EXTERNAL_TOOL_SLOT",&GET_EXTERNAL_TOOL_SLOT); def("GET_EXTERNAL_TOOL_TABLE",&GET_EXTERNAL_TOOL_TABLE); def("GET_EXTERNAL_AXIS_MAX_VELOCITY",&GET_EXTERNAL_AXIS_MAX_VELOCITY); @@ -187,11 +192,11 @@ BOOST_PYTHON_MODULE(emccanon) { def("INIT_CANON",&INIT_CANON); def("LOCK_ROTARY",&LOCK_ROTARY); // def("LOCK_SPINDLE_Z",&LOCK_SPINDLE_Z); - def("LOGAPPEND",&LOGAPPEND); + def("LOGAPPEND",&wrap_text); def("LOGCLOSE",&LOGCLOSE); - def("LOG",&LOG); - def("LOGOPEN",&LOGOPEN); - def("MESSAGE",&MESSAGE); + def("LOG",&wrap_text); + def("LOGOPEN",&wrap_text); + def("MESSAGE",&wrap_text); def("MIST_OFF",&MIST_OFF); def("MIST_ON",&MIST_ON); // def("NURB_CONTROL_POINT",&NURB_CONTROL_POINT); diff --git a/src/emc/rs274ngc/gcode_renderer.cc b/src/emc/rs274ngc/gcode_renderer.cc index 801a4364ba7..816ad639011 100644 --- a/src/emc/rs274ngc/gcode_renderer.cc +++ b/src/emc/rs274ngc/gcode_renderer.cc @@ -867,16 +867,15 @@ GCodeRenderer::~GCodeRenderer() { // fill depends on, counted as a depth so nested spans close in order. The rest // of the vocabulary - `stop`, `notify`, the foam Z levels - is the canon's own // and reached it through the forward that precedes this call. -void GCodeRenderer::comment(const char *text) { - const char *rest; - if(!strncmp(text, "AXIS,", 5)) rest = text + 5; - else if(!strncmp(text, "PREVIEW,", 8)) rest = text + 8; +void GCodeRenderer::comment(std::string_view text) { + std::string_view rest; + if(text.starts_with("AXIS,")) rest = text.substr(5); + else if(text.starts_with("PREVIEW,")) rest = text.substr(8); else return; // The word up to the next comma, as `arg.split(",")[1]` took it. - size_t n = strcspn(rest, ","); - if(n != 4) return; - if(!strncmp(rest, "hide", 4)) suppress_ ++; - else if(!strncmp(rest, "show", 4)) suppress_ --; + rest = rest.substr(0, rest.find(',')); + if(rest == "hide") suppress_ ++; + else if(rest == "show") suppress_ --; } void GCodeRenderer::publish_line() { diff --git a/src/emc/rs274ngc/gcode_renderer.hh b/src/emc/rs274ngc/gcode_renderer.hh index e5131e80cb1..01aa92d7887 100644 --- a/src/emc/rs274ngc/gcode_renderer.hh +++ b/src/emc/rs274ngc/gcode_renderer.hh @@ -436,7 +436,7 @@ public: } // A comment, after the canon has had it: the `(AXIS,hide)`/`(AXIS,show)` // depth is the renderer's own. - void comment(const char *text) override; + void comment(std::string_view text) override; bool transform_points(const Point9 *in, size_t n, double *machine, double *display) const override; diff --git a/src/emc/rs274ngc/gcodemodule.cc b/src/emc/rs274ngc/gcodemodule.cc index f725a708dff..bf571937b5a 100644 --- a/src/emc/rs274ngc/gcodemodule.cc +++ b/src/emc/rs274ngc/gcodemodule.cc @@ -57,11 +57,11 @@ #include "rs274ngc_interp.hh" #include "nml_intf/interp_return.hh" #include "nml_intf/canon.hh" +#include "nml_intf/nurbs_math.hh" #include int _task = 0; // control preview behaviour when remapping -char _parameter_file_name[LINELEN]; extern "C" PyObject* PyInit_interpreter(void); extern "C" PyObject* PyInit_emccanon(void); @@ -609,17 +609,17 @@ void DWELL(double time) { parse_state.canon->dwell(time); } -void MESSAGE(char *comment) { +void MESSAGE(std::string_view comment) { maybe_new_line(); forward("message", comment); } -void LOG(char * /*s*/) {} -void LOGOPEN(char * /*f*/) {} -void LOGAPPEND(char * /*f*/) {} +void LOG(std::string_view /*s*/) {} +void LOGOPEN(std::string_view /*f*/) {} +void LOGAPPEND(std::string_view /*f*/) {} void LOGCLOSE() {} -void COMMENT(const char *comment) { +void COMMENT(std::string_view comment) { maybe_new_line(); forward("comment", comment); if(parse_state.interp_error) return; @@ -684,7 +684,7 @@ extern bool GET_BLOCK_DELETE(void) { return bd; } -void CANON_ERROR(const char * /*fmt*/, ...) {}; +void CANON_ERROR(std::string_view /*message*/) {} void CLAMP_AXIS(CANON_AXIS /*axis*/) {} bool GET_OPTIONAL_PROGRAM_STOP() { return false;} void SET_OPTIONAL_PROGRAM_STOP(bool /*state*/) {} @@ -733,45 +733,36 @@ void RIGID_TAP(int line_number, } double GET_EXTERNAL_MOTION_CONTROL_TOLERANCE() { return 0.1; } double GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE() { return 0.1; } -double GET_EXTERNAL_PROBE_POSITION_X() { return parse_state.pos[P9_X]; } -double GET_EXTERNAL_PROBE_POSITION_Y() { return parse_state.pos[P9_Y]; } -double GET_EXTERNAL_PROBE_POSITION_Z() { return parse_state.pos[P9_Z]; } -double GET_EXTERNAL_PROBE_POSITION_A() { return parse_state.pos[P9_A]; } -double GET_EXTERNAL_PROBE_POSITION_B() { return parse_state.pos[P9_B]; } -double GET_EXTERNAL_PROBE_POSITION_C() { return parse_state.pos[P9_C]; } -double GET_EXTERNAL_PROBE_POSITION_U() { return parse_state.pos[P9_U]; } -double GET_EXTERNAL_PROBE_POSITION_V() { return parse_state.pos[P9_V]; } -double GET_EXTERNAL_PROBE_POSITION_W() { return parse_state.pos[P9_W]; } double GET_EXTERNAL_PROBE_VALUE() { return 0.0; } int GET_EXTERNAL_PROBE_TRIPPED_VALUE() { return 0; } -double GET_EXTERNAL_POSITION_X() { return parse_state.pos[P9_X]; } -double GET_EXTERNAL_POSITION_Y() { return parse_state.pos[P9_Y]; } -double GET_EXTERNAL_POSITION_Z() { return parse_state.pos[P9_Z]; } -double GET_EXTERNAL_POSITION_A() { return parse_state.pos[P9_A]; } -double GET_EXTERNAL_POSITION_B() { return parse_state.pos[P9_B]; } -double GET_EXTERNAL_POSITION_C() { return parse_state.pos[P9_C]; } -double GET_EXTERNAL_POSITION_U() { return parse_state.pos[P9_U]; } -double GET_EXTERNAL_POSITION_V() { return parse_state.pos[P9_V]; } -double GET_EXTERNAL_POSITION_W() { return parse_state.pos[P9_W]; } +CANON_POSITION GET_EXTERNAL_POSITION() { + CANON_POSITION pos; + pos.x = parse_state.pos[P9_X]; + pos.y = parse_state.pos[P9_Y]; + pos.z = parse_state.pos[P9_Z]; + pos.a = parse_state.pos[P9_A]; + pos.b = parse_state.pos[P9_B]; + pos.c = parse_state.pos[P9_C]; + pos.u = parse_state.pos[P9_U]; + pos.v = parse_state.pos[P9_V]; + pos.w = parse_state.pos[P9_W]; + return pos; +} +CANON_POSITION GET_EXTERNAL_PROBE_POSITION() { return GET_EXTERNAL_POSITION(); } void INIT_CANON() {} -void SET_PARAMETER_FILE_NAME(const char *name) -{ - strncpy(_parameter_file_name, name, PARAMETER_FILE_NAME_LENGTH); -} +void SET_PARAMETER_FILE_NAME(std::string_view /*name*/) {} -void GET_EXTERNAL_PARAMETER_FILE_NAME(char *name, int max_size) { - name[0] = 0; +std::string GET_EXTERNAL_PARAMETER_FILE_NAME() { // Not on the interp_error protocol: a canon without the attribute has // always just left the name empty, with the error still on the indicator. try { - std::string file = py::cast( + return py::cast( py::handle(parse_state.callback).attr("parameter_file")); - memset(name, 0, max_size); - strncpy(name, file.c_str(), max_size - 1); } catch(py::error_already_set &e) { e.restore(); } + return {}; } CANON_UNITS GET_EXTERNAL_LENGTH_UNIT_TYPE() { return CANON_UNITS_INCHES; } CANON_TOOL_TABLE GET_EXTERNAL_TOOL_TABLE(int pocket) { @@ -847,32 +838,8 @@ int GET_EXTERNAL_AXIS_MASK() { return mask; } -double GET_EXTERNAL_TOOL_LENGTH_XOFFSET() { - return parse_state.tool_offset.tran.x; -} -double GET_EXTERNAL_TOOL_LENGTH_YOFFSET() { - return parse_state.tool_offset.tran.y; -} -double GET_EXTERNAL_TOOL_LENGTH_ZOFFSET() { - return parse_state.tool_offset.tran.z; -} -double GET_EXTERNAL_TOOL_LENGTH_AOFFSET() { - return parse_state.tool_offset.a; -} -double GET_EXTERNAL_TOOL_LENGTH_BOFFSET() { - return parse_state.tool_offset.b; -} -double GET_EXTERNAL_TOOL_LENGTH_COFFSET() { - return parse_state.tool_offset.c; -} -double GET_EXTERNAL_TOOL_LENGTH_UOFFSET() { - return parse_state.tool_offset.u; -} -double GET_EXTERNAL_TOOL_LENGTH_VOFFSET() { - return parse_state.tool_offset.v; -} -double GET_EXTERNAL_TOOL_LENGTH_WOFFSET() { - return parse_state.tool_offset.w; +EmcPose GET_EXTERNAL_TOOL_LENGTH_OFFSET() { + return parse_state.tool_offset; } // The unit constants, answered by the parse's protocol: the callback protocol @@ -1112,15 +1079,13 @@ static py::object parse_file(const char *f, py::handle canon, static int maxerror = -1; -static char savedError[LINELEN+1]; static py::str rs274_strerror(int err) { // The text belongs to the interpreter the last parse built; without one // there is nothing to ask, and dereferencing it would end the process. if(!parse_state.pinterp) throw std::runtime_error("gcode.strerror: no interpreter yet - " "call gcode.parse first"); - parse_state.pinterp->error_text(err, savedError, LINELEN); - return py::str(savedError); + return py::str(parse_state.pinterp->error_text(err)); } // One (min, max) box over every point of every move handed in, plus the box diff --git a/src/emc/rs274ngc/gcodemodule.hh b/src/emc/rs274ngc/gcodemodule.hh index db21a558a0a..3dd53e3c39a 100644 --- a/src/emc/rs274ngc/gcodemodule.hh +++ b/src/emc/rs274ngc/gcodemodule.hh @@ -200,7 +200,7 @@ public: // `(AXIS,stop)` still stops the parse before the word after it could open // a hidden span. Only the renderer listens, for its own `(AXIS,hide)` // depth. - virtual void comment(const char * /*text*/) {} + virtual void comment(std::string_view /*text*/) {} // `n` program points where the transform as it stands puts them: the // same machine and display coordinates a move endpoint on this line diff --git a/src/emc/rs274ngc/interp_base.cc b/src/emc/rs274ngc/interp_base.cc index 3df5478412f..d8e083dd65c 100644 --- a/src/emc/rs274ngc/interp_base.cc +++ b/src/emc/rs274ngc/interp_base.cc @@ -17,7 +17,6 @@ */ #include "interp_base.hh" #include -#include #include #include @@ -25,8 +24,7 @@ InterpBase::~InterpBase() {} InterpBase *interp_from_shlib(const char *shlib) { void * interp_lib; - char relative_interp[PATH_MAX]; - char const * interp_path; + std::string interp_path; dlopen(NULL, RTLD_GLOBAL); @@ -36,16 +34,15 @@ InterpBase *interp_from_shlib(const char *shlib) { } else { // The passed-in .so name is a relative path or just a bare // filename, look for it in `${EMC2_HOME}/lib/linuxcnc`. - snprintf(relative_interp, sizeof(relative_interp), "%s/%s", EMC2_HOME "/lib/linuxcnc", shlib); - interp_path = relative_interp; + interp_path = std::string(EMC2_HOME "/lib/linuxcnc/") + shlib; } - interp_lib = dlopen(interp_path, RTLD_NOW); + interp_lib = dlopen(interp_path.c_str(), RTLD_NOW); if(!interp_lib) { - fprintf(stderr, "emcTaskInit: could not open interpreter '%s': %s\n", interp_path, dlerror()); + fprintf(stderr, "emcTaskInit: could not open interpreter '%s': %s\n", interp_path.c_str(), dlerror()); return NULL; } - fprintf(stderr, "emcTaskInit: using custom interpreter '%s'\n", interp_path); + fprintf(stderr, "emcTaskInit: using custom interpreter '%s'\n", interp_path.c_str()); typedef InterpBase* (*Constructor)(); Constructor constructor = (Constructor)dlsym(interp_lib, "makeInterp"); diff --git a/src/emc/rs274ngc/interp_base.hh b/src/emc/rs274ngc/interp_base.hh index 03d302a09c1..f85759c2ce7 100644 --- a/src/emc/rs274ngc/interp_base.hh +++ b/src/emc/rs274ngc/interp_base.hh @@ -21,6 +21,7 @@ #include #include +#include #include #include #include "../nml_intf/modal_state.hh" @@ -29,10 +30,11 @@ class InterpBase : boost::noncopyable { public: virtual ~InterpBase(); - virtual char *error_text(int errcode, char *buf, size_t buflen) = 0; - virtual char *line_text(char *buf, size_t buflen) = 0; - virtual char *file_name(char *buf, size_t buflen) = 0; - virtual char *stack_name(int index, char *buf, size_t buflen) = 0; + virtual std::string error_text(int errcode) = 0; + virtual std::string line_text() = 0; + virtual std::string file_name() = 0; + // empty past the end of the call stack + virtual std::string stack_name(int index) = 0; virtual size_t line_length() = 0; virtual int sequence_number() = 0; virtual int ini_load(const char *inifile) = 0; @@ -63,8 +65,8 @@ public: const char ** /*filename*/, const char ** /*subname*/, int * /*line*/) { return -1; } - virtual char *command(char *buf, size_t buflen) = 0; - virtual char *file(char *buf, size_t buflen) = 0; + virtual std::string command() = 0; + virtual std::string file() = 0; virtual int on_abort(int reason, const char *message) = 0; virtual void active_g_codes(int active_gcodes[ACTIVE_G_CODES]) = 0; virtual void active_m_codes(int active_mcodes[ACTIVE_M_CODES]) = 0; diff --git a/src/emc/rs274ngc/interp_convert.cc b/src/emc/rs274ngc/interp_convert.cc index 379b21eaba6..5a05a2c90ec 100644 --- a/src/emc/rs274ngc/interp_convert.cc +++ b/src/emc/rs274ngc/interp_convert.cc @@ -1867,7 +1867,7 @@ int Interp::convert_axis_offsets(int g_code, //!< g_code being executed (mus #define VAL_LEN 30 -int Interp::convert_param_comment(char *comment, char *expanded, int /*len*/) +int Interp::convert_param_comment(const char *comment, std::string &expanded) { FORCE_LC_NUMERIC_C; int i; @@ -1876,10 +1876,10 @@ int Interp::convert_param_comment(char *comment, char *expanded, int /*len*/) int paramNumber; int stat; double value; - char valbuf[VAL_LEN]; // max double length + room - char *v; int found; + expanded.clear(); + while(*comment) { @@ -1925,19 +1925,19 @@ int Interp::convert_param_comment(char *comment, char *expanded, int /*len*/) // not a format string so, // back up to the digit to continue processing comment--; - *expanded++ = '.'; + expanded += '.'; } } else { - *expanded++ = '.'; + expanded += '.'; } } else { - *expanded++ = '%'; + expanded += '%'; } } else if(*comment == '#') @@ -2020,7 +2020,7 @@ int Interp::convert_param_comment(char *comment, char *expanded, int /*len*/) // neither numeric or name logDebug("neither numeric nor name"); // just store the '#' - *expanded++ = '#'; + expanded += '#'; CHKS((*comment == 0), NCE_NAMED_PARAMETER_NOT_TERMINATED); continue; @@ -2028,34 +2028,25 @@ int Interp::convert_param_comment(char *comment, char *expanded, int /*len*/) // we have a parameter -- now insert it // we have the value + // values that print longer than VAL_LEN show as ###### + std::string valbuf = "######"; if(found) { // avoid -0.0/0.0 issues double pvalue = equal(value, 0.0) ? 0.0 : value; - int n = snprintf(valbuf, VAL_LEN, format, pvalue); - bool fail = (n >= VAL_LEN || n < 0); - if(fail) - rs274ngc_strxcpy(valbuf, "######"); - - } - else - { - rs274ngc_strxcpy(valbuf, "######"); - } - logDebug("found:%d value:|%s|", found, valbuf); - - v = valbuf; - while(*v) - { - *expanded++ = *v++; + char buf[VAL_LEN]; + int n = snprintf(buf, VAL_LEN, format, pvalue); + if (n >= 0 && n < VAL_LEN) + valbuf = buf; } + logDebug("found:%d value:|%s|", found, valbuf.c_str()); + expanded += valbuf; } else // not a '#' { - *expanded++ = *comment++; + expanded += *comment++; } } - *expanded = 0; // the final nul return INTERP_OK; } @@ -2094,9 +2085,9 @@ static int startswith(char *haystack, char *needle) { int Interp::convert_comment(char *comment, bool enqueue) //!< string with comment { enum - { LC_SIZE = 256, EX_SIZE = 2*LC_SIZE}; // 256 from comment[256] in rs274ngc.hh + { LC_SIZE = 256 }; // 256 from comment[256] in rs274ngc.hh char lc[LC_SIZE+1]; - char expanded[EX_SIZE+1]; + std::string expanded; char MSG_STR[] = "msg,"; //!!!KL add two -- debug => same as msg @@ -2131,8 +2122,7 @@ int Interp::convert_comment(char *comment, bool enqueue) //!< string with } else if (startswith(lc, DEBUG_STR)) { - convert_param_comment(comment+start+strlen(DEBUG_STR), expanded, - EX_SIZE); + convert_param_comment(comment+start+strlen(DEBUG_STR), expanded); if (_setup.parameters[5599] > 0.0) MESSAGE(expanded); return INTERP_OK; @@ -2141,17 +2131,15 @@ int Interp::convert_comment(char *comment, bool enqueue) //!< string with { FILE *fd = get_stdout(); if (fd) { - convert_param_comment(comment+start+strlen(PRINT_STR), expanded, - EX_SIZE); - fprintf(fd, "%s\n", expanded); + convert_param_comment(comment+start+strlen(PRINT_STR), expanded); + fprintf(fd, "%s\n", expanded.c_str()); fflush(fd); } return INTERP_OK; } else if (startswith(lc, LOG_STR)) { - convert_param_comment(comment+start+strlen(LOG_STR), expanded, - EX_SIZE); + convert_param_comment(comment+start+strlen(LOG_STR), expanded); LOG(expanded); return INTERP_OK; } @@ -2179,8 +2167,7 @@ int Interp::convert_comment(char *comment, bool enqueue) //!< string with } else if (startswith(lc, ABORT_STR)) { - convert_param_comment(comment+start+strlen(ABORT_STR), expanded, - EX_SIZE); + convert_param_comment(comment+start+strlen(ABORT_STR), expanded); setSavedError(expanded); // avoid printf interpretation return INTERP_ERROR; } @@ -3539,15 +3526,7 @@ int Interp::convert_length_units(int g_code, //!< g_code being executed (mus scale_linear_axes(settings, INCH_PER_MM); - settings->tool_offset.tran.x = GET_EXTERNAL_TOOL_LENGTH_XOFFSET(); - settings->tool_offset.tran.y = GET_EXTERNAL_TOOL_LENGTH_YOFFSET(); - settings->tool_offset.tran.z = GET_EXTERNAL_TOOL_LENGTH_ZOFFSET(); - settings->tool_offset.a = GET_EXTERNAL_TOOL_LENGTH_AOFFSET(); - settings->tool_offset.b = GET_EXTERNAL_TOOL_LENGTH_BOFFSET(); - settings->tool_offset.c = GET_EXTERNAL_TOOL_LENGTH_COFFSET(); - settings->tool_offset.u = GET_EXTERNAL_TOOL_LENGTH_UOFFSET(); - settings->tool_offset.v = GET_EXTERNAL_TOOL_LENGTH_VOFFSET(); - settings->tool_offset.w = GET_EXTERNAL_TOOL_LENGTH_WOFFSET(); + settings->tool_offset = GET_EXTERNAL_TOOL_LENGTH_OFFSET(); settings->feed_rate = GET_EXTERNAL_FEED_RATE(); settings->tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE(); settings->naivecam_tolerance = @@ -3580,15 +3559,7 @@ int Interp::convert_length_units(int g_code, //!< g_code being executed (mus scale_linear_axes(settings, MM_PER_INCH); - settings->tool_offset.tran.x = GET_EXTERNAL_TOOL_LENGTH_XOFFSET(); - settings->tool_offset.tran.y = GET_EXTERNAL_TOOL_LENGTH_YOFFSET(); - settings->tool_offset.tran.z = GET_EXTERNAL_TOOL_LENGTH_ZOFFSET(); - settings->tool_offset.a = GET_EXTERNAL_TOOL_LENGTH_AOFFSET(); - settings->tool_offset.b = GET_EXTERNAL_TOOL_LENGTH_BOFFSET(); - settings->tool_offset.c = GET_EXTERNAL_TOOL_LENGTH_COFFSET(); - settings->tool_offset.u = GET_EXTERNAL_TOOL_LENGTH_UOFFSET(); - settings->tool_offset.v = GET_EXTERNAL_TOOL_LENGTH_VOFFSET(); - settings->tool_offset.w = GET_EXTERNAL_TOOL_LENGTH_WOFFSET(); + settings->tool_offset = GET_EXTERNAL_TOOL_LENGTH_OFFSET(); settings->feed_rate = GET_EXTERNAL_FEED_RATE(); settings->tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE(); settings->naivecam_tolerance = @@ -3917,9 +3888,9 @@ int Interp::restore_settings(setup_pointer settings, while (s != NULL) { int status = execute(s); if (status != INTERP_OK) { - char currentError[LINELEN+1]; - rs274ngc_strxcpy(currentError,getSavedError()); - CHKS(status, _("M7x: restore_settings failed executing: '%s': %s"), s, currentError); + // a copy: CHKS replaces the saved error while formatting + const std::string currentError = getSavedError(); + CHKS(status, _("M7x: restore_settings failed executing: '%s': %s"), s, currentError.c_str()); } s = strtok_r(NULL, "\n", &stateptr); } @@ -3994,10 +3965,10 @@ int Interp::restore_from_tag(StateTag const &tag) while (s != NULL) { int status = execute(s); if (status != INTERP_OK) { - char currentError[LINELEN+1]; - strcpy(currentError,getSavedError()); + // a copy: CHKS replaces the saved error while formatting + const std::string currentError = getSavedError(); CHKS(status, _("Failed to restore interp state on abort " - "'%s': %s"), s, currentError); + "'%s': %s"), s, currentError.c_str()); } s = strtok_r(NULL, "\n", &stateptr); } diff --git a/src/emc/rs274ngc/interp_internal.cc b/src/emc/rs274ngc/interp_internal.cc index bcccebe27c2..b107d221bc7 100644 --- a/src/emc/rs274ngc/interp_internal.cc +++ b/src/emc/rs274ngc/interp_internal.cc @@ -415,15 +415,16 @@ int Interp::precedence(int an_operator) int Interp::refresh_actual_position(setup_pointer settings) { - settings->current_x = GET_EXTERNAL_POSITION_X(); - settings->current_y = GET_EXTERNAL_POSITION_Y(); - settings->current_z = GET_EXTERNAL_POSITION_Z(); - settings->AA_current = GET_EXTERNAL_POSITION_A(); - settings->BB_current = GET_EXTERNAL_POSITION_B(); - settings->CC_current = GET_EXTERNAL_POSITION_C(); - settings->u_current = GET_EXTERNAL_POSITION_U(); - settings->v_current = GET_EXTERNAL_POSITION_V(); - settings->w_current = GET_EXTERNAL_POSITION_W(); + const CANON_POSITION pos = GET_EXTERNAL_POSITION(); + settings->current_x = pos.x; + settings->current_y = pos.y; + settings->current_z = pos.z; + settings->AA_current = pos.a; + settings->BB_current = pos.b; + settings->CC_current = pos.c; + settings->u_current = pos.u; + settings->v_current = pos.v; + settings->w_current = pos.w; return INTERP_OK; } @@ -448,41 +449,42 @@ int Interp::set_probe_data(setup_pointer settings) //!< pointer to machine { double a, b, c, u, v, w; refresh_actual_position(settings); - settings->parameters[5061] = GET_EXTERNAL_PROBE_POSITION_X(); - settings->parameters[5062] = GET_EXTERNAL_PROBE_POSITION_Y(); - settings->parameters[5063] = GET_EXTERNAL_PROBE_POSITION_Z(); + const CANON_POSITION probe = GET_EXTERNAL_PROBE_POSITION(); + settings->parameters[5061] = probe.x; + settings->parameters[5062] = probe.y; + settings->parameters[5063] = probe.z; - a = GET_EXTERNAL_PROBE_POSITION_A(); + a = probe.a; if(settings->axis_wrapped[AXIS_A] || settings->axis_rotary_modulo[AXIS_A]) { a = wrap_rotary_to_360(a); } settings->parameters[5064] = a; - b = GET_EXTERNAL_PROBE_POSITION_B(); + b = probe.b; if(settings->axis_wrapped[AXIS_B] || settings->axis_rotary_modulo[AXIS_B]) { b = wrap_rotary_to_360(b); } settings->parameters[5065] = b; - c = GET_EXTERNAL_PROBE_POSITION_C(); + c = probe.c; if(settings->axis_wrapped[AXIS_C] || settings->axis_rotary_modulo[AXIS_C]) { c = wrap_rotary_to_360(c); } settings->parameters[5066] = c; - u = GET_EXTERNAL_PROBE_POSITION_U(); + u = probe.u; if(settings->axis_wrapped[AXIS_U] || settings->axis_rotary_modulo[AXIS_U]) { u = wrap_rotary_to_360(u); } settings->parameters[5067] = u; - v = GET_EXTERNAL_PROBE_POSITION_V(); + v = probe.v; if(settings->axis_wrapped[AXIS_V] || settings->axis_rotary_modulo[AXIS_V]) { v = wrap_rotary_to_360(v); } settings->parameters[5068] = v; - w = GET_EXTERNAL_PROBE_POSITION_W(); + w = probe.w; if(settings->axis_wrapped[AXIS_W] || settings->axis_rotary_modulo[AXIS_W]) { w = wrap_rotary_to_360(w); } diff --git a/src/emc/rs274ngc/interp_internal.hh b/src/emc/rs274ngc/interp_internal.hh index ebe9d0d0d49..ca02fa43494 100644 --- a/src/emc/rs274ngc/interp_internal.hh +++ b/src/emc/rs274ngc/interp_internal.hh @@ -611,7 +611,6 @@ typedef parameter_map::iterator parameter_map_iterator; // flag initialization of r/o parameter #define OVERRIDE_READONLY 1 -#define MAX_REMAPOPTS 20 // current implementation limits - legal modal groups // for M- and G-codes #define M_MODE_OK(m) ((m > 3) && (m < 11)) @@ -697,7 +696,6 @@ and is not represented here */ #define STACK_LEN 50 -#define STACK_ENTRY_LEN 256 #define MAX_SUB_DIRS 10 struct setup @@ -831,7 +829,10 @@ struct setup CANON_SPEED_FEED_MODE speed_feed_mode; // independent or synched bool speed_override[EMCMOT_MAX_SPINDLES]; // whether speed override is enabled CANON_DIRECTION spindle_turning[EMCMOT_MAX_SPINDLES]; // direction spindle is turning - char stack[STACK_LEN][STACK_ENTRY_LEN]; // stack of calls for error reporting + // stack of calls for error reporting: function names, which are string + // literals (__PRETTY_FUNCTION__), so only the pointers are kept. The + // entry after the last one is nullptr. + const char *stack[STACK_LEN]; int stack_index; // index into the stack EmcPose tool_offset; // tool length offset CANON_TOOL_TABLE tool_table[CANON_POCKETS_MAX]; // index is pocket number @@ -863,13 +864,12 @@ struct setup bool feed_hold; // feed hold is enabled int loggingLevel; // 0 means logging is off int debugmask; // from INI EMC/DEBUG - char log_file[PATH_MAX]; - char program_prefix[PATH_MAX]; // program directory + std::string program_prefix; // program directory const char *subroutines[MAX_SUB_DIRS]; // subroutines directories int use_lazy_close; // wait until next open before closing // the input file int lazy_closing; // close has been called - char wizard_root[PATH_MAX]; + std::string wizard_root; int tool_change_at_g30; int tool_change_quill_up; int tool_change_with_spindle_on; @@ -966,37 +966,33 @@ static inline void rs274ngc_strlcpy(char *dst, const char *src, size_t dstsize) dst[sizeof(dst)-1] = 0; \ } while(0) +// Start the error call stack with the current function +#define ERROR_STACK_START() \ + do { \ + _setup.stack[0] = __PRETTY_FUNCTION__; \ + _setup.stack[1] = nullptr; \ + _setup.stack_index = 1; \ + } while(0) + // Just set an error string using printf-style formats, do NOT return #define ERM(fmt, ...) \ do { \ setError (fmt, ## __VA_ARGS__); \ - _setup.stack_index = 0; \ - (rs274ngc_strlcpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN)); \ - _setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \ - _setup.stack_index++; \ - _setup.stack[_setup.stack_index][0] = 0; \ + ERROR_STACK_START(); \ } while(0) // Set an error string using printf-style formats and return #define ERS(fmt, ...) \ do { \ setError (fmt, ## __VA_ARGS__); \ - _setup.stack_index = 0; \ - (rs274ngc_strlcpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN)); \ - _setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \ - _setup.stack_index++; \ - _setup.stack[_setup.stack_index][0] = 0; \ + ERROR_STACK_START(); \ return INTERP_ERROR; \ } while(0) // Return one of the very few numeric errors #define ERN(error_code) \ do { \ - _setup.stack_index = 0; \ - (rs274ngc_strlcpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN)); \ - _setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \ - _setup.stack_index++; \ - _setup.stack[_setup.stack_index][0] = 0; \ + ERROR_STACK_START(); \ return error_code; \ } while(0) @@ -1004,11 +1000,10 @@ static inline void rs274ngc_strlcpy(char *dst, const char *src, size_t dstsize) // Propagate an error up the stack #define ERP(error_code) \ do { \ - if (_setup.stack_index < STACK_LEN - 1) { \ - (rs274ngc_strlcpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN)); \ - _setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \ - _setup.stack_index++; \ - _setup.stack[_setup.stack_index][0] = 0; \ + if (_setup.stack_index >= 0 \ + && _setup.stack_index < STACK_LEN - 1) { \ + _setup.stack[_setup.stack_index++] = __PRETTY_FUNCTION__; \ + _setup.stack[_setup.stack_index] = nullptr; \ } \ return error_code; \ } while(0) diff --git a/src/emc/rs274ngc/interp_o_word.cc b/src/emc/rs274ngc/interp_o_word.cc index 828119dc99d..8969fa36c1c 100644 --- a/src/emc/rs274ngc/interp_o_word.cc +++ b/src/emc/rs274ngc/interp_o_word.cc @@ -47,35 +47,33 @@ namespace bp = boost::python; */ int Interp::findFile( // ARGUMENTS - char *direct, // the directory to start looking in - char *target, // the name of the file to find - char *foundFileDirect) // where to store the result + const std::string &direct, // the directory to start looking in + std::string_view target, // the name of the file to find + std::string &foundFileDirect) // the directory it was found in { FILE *file; DIR *aDir; struct dirent *aFile; - char targetPath[PATH_MAX+1]; - snprintf(targetPath, PATH_MAX, "%s/%s", direct, target); - file = fopen(targetPath, "r"); + std::string targetPath = direct + "/"; + targetPath += target; + file = fopen(targetPath.c_str(), "r"); if (file) { - rs274ngc_strlcpy(foundFileDirect, direct, PATH_MAX); + foundFileDirect = direct; fclose(file); return INTERP_OK; } - aDir = opendir(direct); + aDir = opendir(direct.c_str()); if (!aDir) { ERS(NCE_FILE_NOT_OPEN); } while ((aFile = readdir(aDir))) { if (aFile->d_type == DT_DIR && - (0 != strncmp(aFile->d_name, "..", 3)) && - (0 != strncmp(aFile->d_name, ".", 2))) { + (0 != strcmp(aFile->d_name, "..")) && + (0 != strcmp(aFile->d_name, "."))) { - char path[PATH_MAX+1]; - snprintf(path, PATH_MAX, "%s/%s", direct, aFile->d_name); - if (INTERP_OK == findFile(path, target, foundFileDirect)) { + if (INTERP_OK == findFile(direct + "/" + aFile->d_name, target, foundFileDirect)) { closedir(aDir); return INTERP_OK; } @@ -542,7 +540,7 @@ int Interp::control_back_to( block_pointer block, // pointer to block setup_pointer settings) // pointer to machine settings { static char name[] = "control_back_to"; - char newFileName[PATH_MAX]; + std::string newFileName; FILE *newFP; offset_map_iterator it; offset_pointer op; @@ -588,21 +586,21 @@ int Interp::control_back_to( block_pointer block, // pointer to block } // #2 open the File - newFP = find_ngc_file(settings, block->o_name, newFileName); + newFP = find_ngc_file(settings, block->o_name, &newFileName); if (newFP) { - logOword("fopen: |%s| OK", newFileName); + logOword("fopen: |%s| OK", newFileName.c_str()); settings->sequence_number = 0; // close the old file... if (settings->file_pointer) fclose(settings->file_pointer); settings->file_pointer = newFP; - if (strlen(newFileName) >= sizeof(settings->filename)) { - logOword("new filename '%s' is too long (max len %zu)\n", newFileName, sizeof(settings->filename)-1); - ERS(NCE_UNABLE_TO_OPEN_FILE, newFileName); + if (newFileName.size() >= sizeof(settings->filename)) { + logOword("new filename '%s' is too long (max len %zu)\n", newFileName.c_str(), sizeof(settings->filename)-1); + ERS(NCE_UNABLE_TO_OPEN_FILE, newFileName.c_str()); } - strncpy(settings->filename, newFileName, sizeof(settings->filename)); + rs274ngc_strxcpy(settings->filename, newFileName.c_str()); } else { // No file found for this sub name. // Block forward-seek if the current file is not the main program. @@ -614,12 +612,12 @@ int Interp::control_back_to( block_pointer block, // pointer to block if (main_frame->filename == NULL || strcmp(settings->filename, main_frame->filename) != 0) { ERS(_("Subroutine 'O%s' not found -- " - "not in offset table and no file '%s' found"), - block->o_name, newFileName); + "not in offset table and no file '%s.ngc' found"), + block->o_name, block->o_name); } } char *dirname = getcwd(NULL, 0); - logOword("fopen: |%s| failed CWD:|%s|", newFileName, + logOword("fopen: |%s.ngc| failed CWD:|%s|", block->o_name, dirname); free(dirname); } diff --git a/src/emc/rs274ngc/interp_remap.cc b/src/emc/rs274ngc/interp_remap.cc index 9f197242fcb..d6cb492d449 100644 --- a/src/emc/rs274ngc/interp_remap.cc +++ b/src/emc/rs274ngc/interp_remap.cc @@ -113,7 +113,7 @@ int Interp::convert_remapped_code(block_pointer /*block*/, int status; block_pointer cblock; bp::list plist; - char cmd[LINELEN]; + std::string cmd; if (number == -1) logRemap("convert_remapped_code '%c'", letter); @@ -156,7 +156,7 @@ int Interp::convert_remapped_code(block_pointer /*block*/, // oword mechanism - so no duplication of handler calling code // is needed. - snprintf(cmd, sizeof(cmd),"O <%s> call ", REMAP_FUNC(remap)); + cmd = std::string("O <") + REMAP_FUNC(remap) + "> call "; // the controlling block holds all dynamic remap information. cblock = &CONTROLLING_BLOCK(*settings); @@ -168,16 +168,16 @@ int Interp::convert_remapped_code(block_pointer /*block*/, // if user specified '@' // named local params are dealt with in execute_call() when // the new call frame is fully established - CHP(add_parameters(settings, cblock, &cmd[strlen(cmd)])); + CHP(add_parameters(settings, cblock, &cmd)); } if ((_setup.debugmask & EMC_DEBUG_REMAP) && (_setup.loggingLevel > 2)) { - logRemap("convert_remapped_code(%s)", cmd); + logRemap("convert_remapped_code(%s)", cmd.c_str()); } // good to go, pass to o-word call handling mechanism - status = read(cmd); + status = read(cmd.c_str()); block_pointer eblock = &EXECUTING_BLOCK(*settings); eblock->call_type = CT_REMAP; CHKS(status != INTERP_OK, @@ -217,7 +217,7 @@ int Interp::convert_remapped_code(block_pointer /*block*/, int Interp::add_parameters(setup_pointer settings, block_pointer cblock, - char *posarglist) + std::string *posarglist) { const char *code; block_pointer block; @@ -281,7 +281,7 @@ int Interp::add_parameters(setup_pointer settings, if (posarglist) { char actual[LINELEN]; snprintf(actual, sizeof(actual), "[%.4lf]", value); - strcat(posarglist, actual); + *posarglist += actual; cblock->param_cnt++; } else { @@ -405,46 +405,47 @@ remap_pointer Interp::remapping(const char *code) int Interp::parse_remap(const char *inistring, int lineno) { - char iniline[LINELEN]; - char *argv[MAX_REMAPOPTS]; - int argc = 0; + std::vector argv; + int argc; const char *code; remap r; bool errored = false; int g1 = 0, g2 = 0; int mcode = -1; int gcode = -1; - char *s; memset((void *)&r, 0, sizeof(remap)); r.modal_group = -1; // mark as unset, required param for m/g r.motion_code = INT_MIN; - rs274ngc_strxcpy(iniline, inistring); - // strip trailing comments - if ((s = strchr(iniline, '#')) != NULL) { - *s = '\0'; - } - char* saveptr; - s = strtok_r((char *) iniline, " \t", &saveptr); - - while( s != NULL && argc < MAX_REMAPOPTS - 1) { - argv[argc++] = s; - s = strtok_r( NULL, " \t", &saveptr); + { + std::string_view line = inistring; + // strip trailing comments + line = line.substr(0, line.find('#')); + // split on blanks and tabs + while (true) { + size_t start = line.find_first_not_of(" \t"); + if (start == line.npos) + break; + line.remove_prefix(start); + size_t end = line.find_first_of(" \t"); + argv.emplace_back(line.substr(0, end)); + line.remove_prefix(end == line.npos ? line.size() : end); + } } - if (argc == MAX_REMAPOPTS) { - Error("parse_remap: too many arguments (max %d)", MAX_REMAPOPTS); + argc = argv.size(); + if (argc == 0) { + Error("parse_remap: no code to remap: %d:REMAP = %s", lineno, inistring); goto fail; } - argv[argc] = NULL; - code = strstore(argv[0]); + code = strstore(argv[0].c_str()); r.name = code; for (int i = 1; i < argc; i++) { int kwlen = 0; - char *kw = argv[i]; - char *arg = strchr(argv[i],'='); + char *kw = argv[i].data(); + char *arg = strchr(kw,'='); if (arg != NULL) { - kwlen = arg - argv[i]; + kwlen = arg - kw; arg++; if (!strlen(arg)) { // 'kw=' Error("option '%s' - zero length value: %d:REMAP = %s", @@ -536,8 +537,9 @@ int Interp::parse_remap(const char *inistring, int lineno) r.remap_py = strstore(arg); continue; } - Error("unrecognized option '%*s' in %d:REMAP = %s", + Error("unrecognized option '%.*s' in %d:REMAP = %s", kwlen,kw,lineno,inistring); + errored = true; } if (errored) { goto fail; @@ -574,12 +576,26 @@ int Interp::parse_remap(const char *inistring, int lineno) _setup.remaps[code] = r; break; - case 'm': - if (sscanf(code + 1, "%d", &mcode) != 1) { + case 'm': { + int len = 0; + if (sscanf(code + 1, "%d%n", &mcode, &len) != 1 || code[1 + len] != '\0') { Error("parsing M-code: expecting integer like 'M420', got '%s' : %d:REMAP = %s", code,lineno,inistring); goto fail; } + if (!is_m_code_remappable(mcode)) { + Error("code '%s' can't be remapped : %d:REMAP = %s", + code,lineno,inistring); + goto fail; + } + // the built-in code looks M-code remaps up as "M6", so store M06 as that + code = strstore(("M" + std::to_string(mcode)).c_str()); + r.name = code; + if (_setup.m_remapped[mcode]) { + Error("code '%s' already remapped : %d:REMAP = %s", + code,lineno,inistring); + goto fail; + } if (r.modal_group == -1) { Error("warning: code '%s' : no modalgroup= given, using default group %d : %d:REMAP = %s", code, MCODE_DEFAULT_MODAL_GROUP,lineno,inistring); @@ -593,21 +609,31 @@ int Interp::parse_remap(const char *inistring, int lineno) _setup.remaps[code] = r; _setup.m_remapped[mcode] = &_setup.remaps[code]; break; - case 'g': - + } + case 'g': { + int len = 0; // code may be G88.1 or so - normalize to use 'G881' instead // (multiply by 10, no dots) - if (sscanf(code + 1, "%d.%d", &g1, &g2) == 2) { + if (sscanf(code + 1, "%d.%1d%n", &g1, &g2, &len) == 2) { gcode = g1 * 10 + g2; - } - if ( gcode == -1) { - if (sscanf(code + 1, "%d", &gcode) != 1) { - Error("code '%s' : can\'t parse G-code : %d:REMAP = %s", - code, lineno, inistring); - goto fail; - } + } else if (sscanf(code + 1, "%d%n", &gcode, &len) == 1) { gcode *= 10; } + if (gcode < 0 || code[1 + len] != '\0') { + Error("code '%s' : can\'t parse G-code : %d:REMAP = %s", + code, lineno, inistring); + goto fail; + } + if (!is_g_code_remappable(gcode)) { + Error("code '%s' can't be remapped : %d:REMAP = %s", + code,lineno,inistring); + goto fail; + } + if (_setup.g_remapped[gcode]) { + Error("code '%s' already remapped : %d:REMAP = %s", + code,lineno,inistring); + goto fail; + } r.motion_code = gcode; if (r.modal_group == -1) { Error("warning: code '%s' : no modalgroup= given, using default group %d : %d:REMAP = %s", @@ -616,7 +642,7 @@ int Interp::parse_remap(const char *inistring, int lineno) } if (!G_MODE_OK(r.modal_group)) { Error("error: code '%s' : %s modalgroup= given : %d:REMAP = %s", - argv[0], + argv[0].c_str(), r.modal_group == -1 ? "no" : "invalid", lineno, inistring); @@ -625,6 +651,7 @@ int Interp::parse_remap(const char *inistring, int lineno) _setup.remaps[code] = r; _setup.g_remapped[gcode] = &_setup.remaps[code]; break; + } default: // make sure the python plugin is in a usable state if needed @@ -639,5 +666,7 @@ int Interp::parse_remap(const char *inistring, int lineno) return INTERP_OK; fail: + // the details went to the log above; init reports this text + setError("invalid REMAP in INI line %d: %s", lineno, inistring); return INTERP_ERROR; } diff --git a/src/emc/rs274ngc/interp_setup.cc b/src/emc/rs274ngc/interp_setup.cc index bd513053de2..23fed349478 100644 --- a/src/emc/rs274ngc/interp_setup.cc +++ b/src/emc/rs274ngc/interp_setup.cc @@ -180,7 +180,6 @@ setup::setup() : feed_hold(0), loggingLevel(0), debugmask(0), - log_file{}, program_prefix{}, subroutines{}, use_lazy_close(0), diff --git a/src/emc/rs274ngc/interp_write.cc b/src/emc/rs274ngc/interp_write.cc index 63dc9b73b0b..8af67ed6930 100644 --- a/src/emc/rs274ngc/interp_write.cc +++ b/src/emc/rs274ngc/interp_write.cc @@ -242,7 +242,10 @@ int Interp::write_state_tag(block_pointer block, bool in_sub = (settings->call_level > 0 && settings->remap_level == 0); bool external_sub = strcmp(settings->filename, settings->sub_context[0].filename); - rs274ngc_strxcpy(state.filename, settings->filename); + // state_tag_t travels in a motion message, so its filename stays fixed-size + size_t len = std::string_view(settings->filename) + .copy(state.filename, sizeof(state.filename) - 1); + state.filename[len] = 0; state.flags[GM_FLAG_IN_REMAP] = in_remap; state.flags[GM_FLAG_IN_SUB] = in_sub; diff --git a/src/emc/rs274ngc/interpmodule.cc b/src/emc/rs274ngc/interpmodule.cc index 1597ec1be34..773a12e7065 100644 --- a/src/emc/rs274ngc/interpmodule.cc +++ b/src/emc/rs274ngc/interpmodule.cc @@ -32,6 +32,8 @@ #include #include #include +#include +#include #include #include "boost_pyenum_macros.hh" @@ -100,12 +102,9 @@ static void setErrorMsg(Interp &interp, const char *s) if ((s == NULL) || (strlen(s) == 0)) s = "###"; interp.setError ("%s", s); - settings->stack_index = 0; - strncpy(settings->stack[settings->stack_index], - "Python", STACK_ENTRY_LEN); - settings->stack[settings->stack_index][STACK_ENTRY_LEN-1] = 0; - settings->stack_index++; - settings->stack[settings->stack_index][0] = 0; + settings->stack[0] = "Python"; + settings->stack[1] = nullptr; + settings->stack_index = 1; } static bp::object errorStack(Interp &interp) @@ -113,8 +112,8 @@ static bp::object errorStack(Interp &interp) setup *settings = &interp._setup; bp::list msgs; - for (int i = 0; i < settings->stack_index; i++) - msgs.append(bp::object( (const char *) settings->stack[i])); + for (int i = 0; i < settings->stack_index && i < STACK_LEN && settings->stack[i]; i++) + msgs.append(bp::object(settings->stack[i])); return msgs; } @@ -787,9 +786,6 @@ static inline void set_spindle_turning(Interp &interp, int spindle, int value) static inline int get_stack_index (Interp &interp) { return interp._setup.stack_index; } -static inline void set_stack_index(Interp &interp, int value) { - interp._setup.stack_index = value; -} static inline int get_value_returned (Interp &interp) { return interp._setup.value_returned; } @@ -911,7 +907,8 @@ BOOST_PYTHON_MODULE(interpreter) { .def("set_errormsg", &setErrorMsg) - .def("get_errormsg", &Interp::getSavedError) + .def("get_errormsg", &Interp::getSavedError, + bp::return_value_policy()) .def("stack", &errorStack) .def("synch", &Interp::synch) @@ -1018,7 +1015,7 @@ BOOST_PYTHON_MODULE(interpreter) { .add_property("spindle_mode", &get_spindle_mode, &set_spindle_mode) .add_property("num_spindles", &get_num_spindles, &set_num_spindles) .add_property("spindle_turning", &get_spindle_turning, &set_spindle_turning) - .add_property("stack_index", &get_stack_index, &set_stack_index) + .add_property("stack_index", &get_stack_index) .add_property("value_returned", &get_value_returned, &set_value_returned) .add_property("current_tool", &get_current_tool, &set_current_tool) diff --git a/src/emc/rs274ngc/nurbs_additional_functions.cc b/src/emc/rs274ngc/nurbs_additional_functions.cc index c4825d6aa01..8b4a4340ccb 100644 --- a/src/emc/rs274ngc/nurbs_additional_functions.cc +++ b/src/emc/rs274ngc/nurbs_additional_functions.cc @@ -13,6 +13,7 @@ #include #include #include "nml_intf/canon.hh" +#include "nml_intf/nurbs_math.hh" static void unit(NURBS_PLANE_POINT &p) { diff --git a/src/emc/rs274ngc/rs274ngc_interp.hh b/src/emc/rs274ngc/rs274ngc_interp.hh index 5e4dce0d250..9c8526cdc3f 100644 --- a/src/emc/rs274ngc/rs274ngc_interp.hh +++ b/src/emc/rs274ngc/rs274ngc_interp.hh @@ -62,11 +62,11 @@ public: int reset() override; // restore interpreter variables from a file - int restore_parameters(const char *filename); + int restore_parameters(const std::string &filename); // save interpreter variables to file - int save_parameters(const char *filename, - const double parameters[]); + int save_parameters(const std::string &filename, + const double parameters[]); // synchronize your internal model with the external world int synch() override; @@ -95,32 +95,26 @@ public: // Print contents of state tag for debugging void print_state_tag(StateTag const &tag) override; -// copy the text of the error message whose number is error_code into the -// error_text array, but stop at max_size if the text is longer. - char *error_text(int error_code, char *error_text, - size_t max_size) override; +// the text of the error message whose number is error_code + std::string error_text(int error_code) override; void setError(const char *fmt, ...) __attribute__((format(printf,2,3))); -// copy the name of the currently open file into the file_name array, -// but stop at max_size if the name is longer - char *file_name(char *file_name, size_t max_size) override; +// the name of the currently open file + std::string file_name() override; // return the length of the most recently read line size_t line_length() override; -// copy the text of the most recently read line into the line_text array, -// but stop at max_size if the text is longer - char *line_text(char *line_text, size_t max_size) override; +// the text of the most recently read line + std::string line_text() override; // return the current sequence number (how many lines read) int sequence_number() override; -// copy the function name from the stack_index'th position of the -// function call stack at the time of the most recent error into -// the function name string, but stop at max_size if the name is longer - char *stack_name(int stack_index, char *function_name, - size_t max_size) override; +// the function name at the stack_index'th position of the function +// call stack at the time of the most recent error, empty past the end + std::string stack_name(int stack_index) override; // Get the parameter file name from the INI file. int ini_load(const char *filename) override; @@ -131,9 +125,9 @@ public: int resolve_call_stack_frame(int node_id, int level, const char **filename, const char **subname, int *line) override; - char *command(char *buf, size_t len) override { line_text(buf, len); return buf; } + std::string command() override { return line_text(); } - char *file(char *buf, size_t len) override { file_name(buf, len); return buf; } + std::string file() override { return file_name(); } int init_tool_parameters(); int default_tool_parameters(); @@ -265,7 +259,7 @@ public: char arc_axis2(CANON_PLANE plane); int convert_axis_offsets(int g_code, block_pointer block, setup_pointer settings); - int convert_param_comment(char *comment, char *expanded, int len); + int convert_param_comment(const char *comment, std::string &expanded); int convert_comment(char *comment, bool enqueue = true); int convert_control_mode(int g_code, double tolerance, double naivecam_tolerance, double r_word, bool r_present, /* G64_R_PLANNER */ @@ -566,9 +560,9 @@ int read_dollar(char *line, int *counter, block_pointer block, // O_word stuff int findFile( // ARGUMENTS - char *direct, // the directory to start looking in - char *target, // the name of the file to find - char *foundFileDirect); // where to store the result + const std::string &direct, // the directory to start looking in + std::string_view target, // the name of the file to find + std::string &foundFileDirect); // the directory it was found in int control_save_offset( /* ARGUMENTS */ // int line, /* (o-word) line number */ @@ -641,7 +635,7 @@ int read_inputs(setup_pointer settings); // add named params/param dict if argspec given // present optional words to the subroutine's local variables and Py dict int add_parameters(setup_pointer settings, block_pointer cblock, - char *posarglist); + std::string *posarglist); int init_named_parameters(); int init_python_predef_parameter(const char *name); @@ -679,11 +673,11 @@ int read_inputs(setup_pointer settings); int calltype); int py_execute(const char *cmd, bool as_file = false); // for (py, ....) comments int py_reload(); - FILE *find_ngc_file(setup_pointer settings,const char *basename, char *foundhere = NULL); + FILE *find_ngc_file(setup_pointer settings, std::string_view basename, std::string *foundhere = nullptr); - const char *getSavedError(); + const std::string &getSavedError() const { return saved_error_; } // set error message text without going through printf format interpretation - int setSavedError(const char *msg); + int setSavedError(std::string_view msg); int unwind_call(int status, const char *file, int line, const char *function); @@ -719,6 +713,8 @@ int read_inputs(setup_pointer settings); InterpReturn check_g74_g84_spindle(GCodes motion, CANON_DIRECTION dir); private: + std::string saved_error_; // text of the last error, set by setError + [[nodiscard]] static bool is_parameter_readonly(int index); [[nodiscard]] static bool is_any_m_code_remapped(block_pointer block, setup_pointer settings); diff --git a/src/emc/rs274ngc/rs274ngc_pre.cc b/src/emc/rs274ngc/rs274ngc_pre.cc index f420af7b336..6d45e31d559 100644 --- a/src/emc/rs274ngc/rs274ngc_pre.cc +++ b/src/emc/rs274ngc/rs274ngc_pre.cc @@ -86,7 +86,10 @@ include an option for suppressing superfluous commands. #include #include #include +#include +#include #include +#include #include #include @@ -123,7 +126,6 @@ const char *Interp::interp_status(int status) { extern struct _inittab builtin_modules[]; int trace; -static char savedError[LINELEN+1]; Interp::Interp() : log_file(stderr), @@ -754,6 +756,13 @@ int Interp::find_remappings(block_pointer block, setup_pointer settings) /***********************************************************************/ +// The parameter file the canon names, or the default when it names none. +static std::string parameter_file() +{ + std::string name = GET_EXTERNAL_PARAMETER_FILE_NAME(); + return name.empty() ? RS274NGC_PARAMETER_FILE_NAME_DEFAULT : name; +} + /*! Interp::exit Returned Value: int (INTERP_OK) @@ -771,13 +780,7 @@ written. Otherwise, the default parameter file name is used. int Interp::exit() { - char file_name[LINELEN]; - - GET_EXTERNAL_PARAMETER_FILE_NAME(file_name, (LINELEN - 1)); - save_parameters(((file_name[0] == - 0) ? - RS274NGC_PARAMETER_FILE_NAME_DEFAULT : - file_name), _setup.parameters); + save_parameters(parameter_file(), _setup.parameters); reset(); // interpreter shutdown Python hook @@ -795,7 +798,7 @@ int Interp::exit() ERM("pycall(%s):\n%s", INIT_FUNC, python_plugin->last_exception().c_str()); // this likely wont make it to the UI's any more so bark on stderr - fprintf(stderr, "%s\n",savedError); + fprintf(stderr, "%s\n", saved_error_.c_str()); } } @@ -807,6 +810,18 @@ void Interp::set_loglevel(int level) { _setup.loggingLevel = level; } /***********************************************************************/ +// realpath() into a std::string. On failure `out` is left empty. +static bool real_path(const std::string &path, std::string &out) +{ + out.clear(); + char *resolved = realpath(path.c_str(), nullptr); + if (!resolved) + return false; + out = resolved; + free(resolved); + return true; +} + /*! rs274_ngc_init Returned Value: int @@ -833,7 +848,6 @@ always calls SET_FEED_REFERENCE(CANON_XYZ). int Interp::init() { int k; // starting index in parameters of origin offsets - char filename[LINELEN]; double *pars; // short name for _setup.parameters char *iniFileName; @@ -967,18 +981,18 @@ int Interp::init() _setup.use_lazy_close = 1; - _setup.wizard_root[0] = 0; + _setup.wizard_root.clear(); if(auto inistring = inifile.findString("WIZARD_ROOT", "WIZARD")) { logDebug("[WIZARD]WIZARD_ROOT:%s", inistring->c_str()); - if (realpath(inistring->c_str(), _setup.wizard_root) == NULL) { + if (!real_path(*inistring, _setup.wizard_root)) { //realpath didn't find the file logDebug("realpath failed to find wizard_root:%s:", inistring->c_str()); } } - logDebug("_setup.wizard_root:%s:", _setup.wizard_root); + logDebug("_setup.wizard_root:%s:", _setup.wizard_root.c_str()); - _setup.program_prefix[0] = 0; + _setup.program_prefix.clear(); if(auto inistring = inifile.findString("PROGRAM_PREFIX", "DISPLAY")) { // found it @@ -986,54 +1000,50 @@ int Interp::init() if (inifile.TildeExpansion(*inistring, expandinistring)) { logDebug("TildeExpansion failed for: %s",inistring->c_str()); } - if (realpath(expandinistring.c_str(), _setup.program_prefix) == NULL){ + if (!real_path(expandinistring, _setup.program_prefix)) { //realpath didn't find the file logDebug("realpath failed to find program_prefix:%s:", inistring->c_str()); } logDebug("program prefix:%s: prefix:%s:", - inistring->c_str(), _setup.program_prefix); + inistring->c_str(), _setup.program_prefix.c_str()); } else { logDebug("PROGRAM_PREFIX not found"); } - logDebug("_setup.program_prefix:%s:", _setup.program_prefix); + logDebug("_setup.program_prefix:%s:", _setup.program_prefix.c_str()); if(auto inistring = inifile.findString("SUBROUTINE_PATH", "RS274NGC")) { // found it - int dct; - char* nextdir; - char tmpdirs[PATH_MAX+1]; - - for (dct=0; dct < MAX_SUB_DIRS; dct++) { + for (int dct=0; dct < MAX_SUB_DIRS; dct++) { _setup.subroutines[dct] = NULL; } - rs274ngc_strxcpy(tmpdirs,inistring->c_str()); - char *saveptr; - nextdir = strtok_r(tmpdirs,":",&saveptr); // first token - dct = 0; - while (1) { - char tmp_path[PATH_MAX]; + std::string_view dirs = *inistring; + int dct = 0; + while (!dirs.empty()) { + size_t colon = dirs.find(':'); + std::string nextdir(dirs.substr(0, colon)); + dirs.remove_prefix(colon == dirs.npos ? dirs.size() : colon + 1); + if (nextdir.empty()) + continue; // skip empty entries, as strtok did + if (dct >= MAX_SUB_DIRS) { + logDebug("too many entries in SUBROUTINE_PATH, max=%d", MAX_SUB_DIRS); + break; + } std::string expandnextdir; if (inifile.TildeExpansion(nextdir, expandnextdir)) { - logDebug("TildeExpansion failed for: %s",nextdir); + logDebug("TildeExpansion failed for: %s",nextdir.c_str()); } - if (realpath(expandnextdir.c_str(), tmp_path) == NULL){ + std::string resolved; + if (!real_path(expandnextdir, resolved)) { //realpath didn't find the directory - logDebug("realpath failed to find subroutines[%d]:%s:",dct,nextdir); - _setup.subroutines[dct] = NULL; + logDebug("realpath failed to find subroutines[%d]:%s:",dct,nextdir.c_str()); } else { - _setup.subroutines[dct] = strstore(tmp_path); + _setup.subroutines[dct] = strstore(resolved.c_str()); logDebug("program prefix[%d]:%s",dct,_setup.subroutines[dct]); dct++; } - if (dct >= MAX_SUB_DIRS) { - logDebug("too many entries in SUBROUTINE_PATH, max=%d", MAX_SUB_DIRS); - break; - } - nextdir = strtok_r(NULL,":",&saveptr); - if (nextdir == NULL) break; // no more tokens } } else @@ -1108,10 +1118,7 @@ int Interp::init() } USE_LENGTH_UNITS(_setup.length_units); - GET_EXTERNAL_PARAMETER_FILE_NAME(filename, LINELEN); - if (filename[0] == 0) - rs274ngc_strxcpy(filename, RS274NGC_PARAMETER_FILE_NAME_DEFAULT); - CHP(restore_parameters(filename)); + CHP(restore_parameters(parameter_file())); pars = _setup.parameters; _setup.origin_index = (int) (pars[5220] + 0.0001); if(_setup.origin_index < 1 || _setup.origin_index > 9) { @@ -1911,11 +1918,10 @@ sets of origin offsets. Any parameter not given a value in the file has its value set to zero. */ -int Interp::restore_parameters(const char *filename) //!< name of parameter file to read +int Interp::restore_parameters(const std::string &filename) //!< name of parameter file to read { FORCE_LC_NUMERIC_C; - FILE *infile; - char line[256]; + std::string line; int variable; double value; int required; // number of next required parameter @@ -1925,28 +1931,24 @@ int Interp::restore_parameters(const char *filename) //!< name of parameter fi // it's OK if the parameter file doesn't exist yet // it'll be created in due course with some default values - if(access(filename, F_OK) == -1) + if(access(filename.c_str(), F_OK) == -1) return INTERP_OK; // open original for reading - infile = fopen(filename, "r"); - CHKS((infile == NULL), _("Unable to open parameter file: '%s'"), filename); + std::ifstream infile(filename); + CHKS((!infile), _("Unable to open parameter file: '%s'"), filename.c_str()); pars = _setup.parameters; k = 0; index = 0; required = required_parameters[index++]; - while (feof(infile) == 0) { - if (fgets(line, 256, infile) == NULL) { - break; - } + while (std::getline(infile, line)) { // try for a variable-value match in the file - if (sscanf(line, "%d %lf", &variable, &value) == 2) { + if (sscanf(line.c_str(), "%d %lf", &variable, &value) == 2) { CHKS(((variable <= 0) || (variable >= RS274NGC_MAX_PARAMETERS)), NCE_PARAMETER_NUMBER_OUT_OF_RANGE); for (; k < RS274NGC_MAX_PARAMETERS; k++) { if (k > variable) { - fclose(infile); ERS(NCE_PARAMETER_FILE_OUT_OF_ORDER); } else if (k == variable) { pars[k] = value; @@ -1963,7 +1965,7 @@ int Interp::restore_parameters(const char *filename) //!< name of parameter fi } } } - fclose(infile); + infile.close(); for (; k < RS274NGC_MAX_PARAMETERS; k++) { pars[k] = 0; } @@ -2004,85 +2006,74 @@ If a required parameter is missing from the input file, this does not complain, but does write it in the output file. */ -int Interp::save_parameters(const char *filename, //!< name of file to write - const double parameters[]) //!< parameters to save +int Interp::save_parameters(const std::string &filename, //!< name of file to write + const double parameters[]) //!< parameters to save { FORCE_LC_NUMERIC_C; - FILE *infile; - FILE *outfile; - char line[PATH_MAX]; + std::string line; int variable; double value; int required; // number of next required parameter int index; // index into _required_parameters int k; - std::string tempfile = std::string(filename) + ".new"; - outfile = fopen(tempfile.c_str(), "w"); - CHKS((outfile == NULL), NCE_CANNOT_OPEN_VARIABLE_FILE); - - infile = fopen(filename, "r"); - if(!infile) - infile = fopen("/dev/null", "r"); - if(!infile) { - // If we can't open the 'filename', we may not be able to open "/dev/null" - // either. If so, print an error, close 'outfile' and continue. - perror("Interp::save_parameters(): fopen(/dev/null)"); - fclose(outfile); - return INTERP_OK; - } + // stdio rather than a stream, for fdatasync() below + std::string tempfile = filename + ".new"; + std::unique_ptr outfile(fopen(tempfile.c_str(), "w"), fclose); + CHKS((!outfile), NCE_CANNOT_OPEN_VARIABLE_FILE); + // on an error, drop the half-written file and keep the old one + auto discard = [&]() { + outfile.reset(); + unlink(tempfile.c_str()); + }; + + // a missing file reads as empty, so only the required parameters are written + std::ifstream infile(filename); k = 0; index = 0; required = required_parameters[index++]; - while (feof(infile) == 0) { - if (fgets(line, sizeof(line), infile) == NULL) { - break; - } + while (std::getline(infile, line)) { // try for a variable-value match - if (sscanf(line, "%d %lf", &variable, &value) == 2) { - CHKS(((variable <= 0) - || (variable >= RS274NGC_MAX_PARAMETERS)), - NCE_PARAMETER_NUMBER_OUT_OF_RANGE); + if (sscanf(line.c_str(), "%d %lf", &variable, &value) == 2) { + if ((variable <= 0) || (variable >= RS274NGC_MAX_PARAMETERS)) { + discard(); + ERS(NCE_PARAMETER_NUMBER_OUT_OF_RANGE); + } for (; k < RS274NGC_MAX_PARAMETERS; k++) { if (k > variable) { - fclose(infile); - fclose(outfile); + discard(); ERS(NCE_PARAMETER_FILE_OUT_OF_ORDER); } else if (k == variable) { - snprintf(line, sizeof(line), "%d\t%f\n", k, parameters[k]); - fputs(line, outfile); + fprintf(outfile.get(), "%d\t%f\n", k, parameters[k]); if (k == required) required = required_parameters[index++]; k++; break; } else if (k == required) // know (k < variable) { - snprintf(line, sizeof(line), "%d\t%f\n", k, parameters[k]); - fputs(line, outfile); + fprintf(outfile.get(), "%d\t%f\n", k, parameters[k]); required = required_parameters[index++]; } } } } - fclose(infile); + infile.close(); for (; k < RS274NGC_MAX_PARAMETERS; k++) { if (k == required) { - snprintf(line, sizeof(line), "%d\t%f\n", k, parameters[k]); - fputs(line, outfile); + fprintf(outfile.get(), "%d\t%f\n", k, parameters[k]); required = required_parameters[index++]; } } - fflush(outfile); - fdatasync(fileno(outfile)); - fclose(outfile); - std::string bakfile = std::string(filename) - + RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX; + fflush(outfile.get()); + fdatasync(fileno(outfile.get())); + outfile.reset(); + std::string bakfile = filename + RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX; unlink(bakfile.c_str()); - if(link(filename, bakfile.c_str()) < 0) + if(link(filename.c_str(), bakfile.c_str()) < 0) perror("link (updating variable file)"); - if(rename(tempfile.c_str(), filename) < 0) + if(rename(tempfile.c_str(), filename.c_str()) < 0) perror("rename (updating variable file)"); return INTERP_OK; } @@ -2109,19 +2100,19 @@ the controller. int Interp::synch() { - char file_name[LINELEN]; - _setup.current_x = GET_EXTERNAL_POSITION_X(); - _setup.current_y = GET_EXTERNAL_POSITION_Y(); - _setup.current_z = GET_EXTERNAL_POSITION_Z(); + const CANON_POSITION pos = GET_EXTERNAL_POSITION(); + _setup.current_x = pos.x; + _setup.current_y = pos.y; + _setup.current_z = pos.z; _setup.control_mode = GET_EXTERNAL_MOTION_CONTROL_MODE(); _setup.tolerance = GET_EXTERNAL_MOTION_CONTROL_TOLERANCE(); _setup.naivecam_tolerance = GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE(); - _setup.AA_current = GET_EXTERNAL_POSITION_A(); - _setup.BB_current = GET_EXTERNAL_POSITION_B(); - _setup.CC_current = GET_EXTERNAL_POSITION_C(); - _setup.u_current = GET_EXTERNAL_POSITION_U(); - _setup.v_current = GET_EXTERNAL_POSITION_V(); - _setup.w_current = GET_EXTERNAL_POSITION_W(); + _setup.AA_current = pos.a; + _setup.BB_current = pos.b; + _setup.CC_current = pos.c; + _setup.u_current = pos.u; + _setup.v_current = pos.v; + _setup.w_current = pos.w; _setup.control_mode = GET_EXTERNAL_MOTION_CONTROL_MODE(); /* misnomer: _setup.current_pocket,selected_pocket @@ -2148,11 +2139,7 @@ int Interp::synch() _setup.spindle_mode[s] = SPINDLE_MODE::CONSTANT_RPM; _setup.css_maximum[s] = 0.0; } - GET_EXTERNAL_PARAMETER_FILE_NAME(file_name, (LINELEN - 1)); - save_parameters(((file_name[0] == - 0) ? - RS274NGC_PARAMETER_FILE_NAME_DEFAULT : - file_name), _setup.parameters); + save_parameters(parameter_file(), _setup.parameters); load_tool_table(); /* must set _setup.tool_max first */ @@ -2356,25 +2343,23 @@ void Interp::print_state_tag(StateTag const &tag) void Interp::setError(const char *fmt, ...) { - va_list ap; + va_list ap, ap2; va_start(ap, fmt); - - vsnprintf(savedError, LINELEN, fmt, ap); - + va_copy(ap2, ap); + int n = vsnprintf(nullptr, 0, fmt, ap); va_end(ap); -} -const char *Interp::getSavedError() -{ - return savedError; + saved_error_.assign(n > 0 ? n : 0, '\0'); + if (n > 0) + vsnprintf(saved_error_.data(), n + 1, fmt, ap2); + va_end(ap2); } // set error message text without going through printf format interpretation -int Interp::setSavedError(const char *msg) +int Interp::setSavedError(std::string_view msg) { - savedError[0] = '\0'; - strncpy(savedError, msg, LINELEN); + saved_error_ = msg; return INTERP_OK; } @@ -2382,69 +2367,39 @@ int Interp::setSavedError(const char *msg) /*! Interp::error_text -Returned Value: none +Returned Value: the text of the error error_code: the saved message for +INTERP_ERROR, a fixed text for INTERP_FILE_NOT_OPEN, empty otherwise. -Side Effects: see below +Side Effects: none Called By: external programs -This copies the error string whose index in the _rs274ngc_errors array -is error_code into the error_text array -- unless the error_code is -an out-of-bounds index or the length of the error string is not less -than max_size, in which case an empty string is put into the -error_text. The length of the error_text array should be at least -max_size. - */ -char * Interp::error_text(int error_code, //!< code number of error - char *error_text, //!< char array to copy error text into - size_t max_size) //!< maximum number of characters to copy +std::string Interp::error_text(int error_code) //!< code number of error { - if(error_code == INTERP_ERROR) - { - strncpy(error_text, savedError, max_size); - error_text[max_size-1] = 0; - - return error_text; - } - else if (error_code == INTERP_FILE_NOT_OPEN) - { - strncpy(error_text, "File not open", max_size); - error_text[max_size-1] = 0; - - return error_text; - } - - error_text[0] = 0; - return error_text; + if (error_code == INTERP_ERROR) + return saved_error_; + if (error_code == INTERP_FILE_NOT_OPEN) + return "File not open"; + return {}; } /***********************************************************************/ /*! Interp::file_name -Returned Value: none +Returned Value: the name of the currently open file -Side Effects: see below +Side Effects: none Called By: external programs -This copies the _setup.filename (the name of the currently open -file) into the file_name array -- unless the name is not shorter than -max_size, in which case a null string is put in the file_name array. - - */ -char *Interp::file_name(char *file_name, //!< string: to copy file name into - size_t max_size) //!< maximum number of characters to copy +std::string Interp::file_name() { - if (strlen(_setup.filename) < ((size_t) max_size)) - strcpy(file_name, _setup.filename); - else - file_name[0] = 0; - return file_name; + return _setup.filename; } /***********************************************************************/ @@ -2468,33 +2423,17 @@ size_t Interp::line_length() /*! Interp::line_text -Returned Value: none +Returned Value: the text of the most recently read line -Side Effects: See below +Side Effects: none Called By: external programs -This copies at most (max_size - 1) non-null characters of the most -recently read line into the line_text string and puts a NULL after the -last non-null character. - */ -char *Interp::line_text(char *line_text, //!< string: to copy line into - size_t max_size) //!< maximum number of characters to copy +std::string Interp::line_text() { - size_t n; - char *the_text; - - the_text = _setup.linetext; - for (n = 0; n < (max_size - 1); n++) { - if (the_text[n] != 0) - line_text[n] = the_text[n]; - else - break; - } - line_text[n] = 0; - return line_text; + return _setup.linetext; } /***********************************************************************/ @@ -2520,18 +2459,13 @@ int Interp::sequence_number() /*! Interp::stack_name -Returned Value: none +Returned Value: the name at position stack_index of the _setup.stack +array, or an empty string if stack_index is out of bounds. -Side Effects: see below +Side Effects: none Called By: external programs -This copies at most (max_size - 1) non-null characters from the -string whose index in the _setup.stack array is stack_index into the -function_name string and puts a NULL after the last non-null character -- -unless the stack_index is an out-of-bounds index, in which case an -empty string is put into the function_name. - This function is intended to be used several times in a row to get the stack of function calls that existed when the most recent error occurred. It should be called first with stack_index equal to 0, @@ -2540,25 +2474,11 @@ empty string is returned for the name. */ -char *Interp::stack_name(int stack_index, //!< index into stack of function names - char *function_name, //!< string: to copy function name into - size_t max_size) //!< maximum number of characters to copy +std::string Interp::stack_name(int stack_index) //!< index into stack of function names { - size_t n; - char *the_name; - - if ((stack_index > -1) && (stack_index < STACK_LEN)) { - the_name = _setup.stack[stack_index]; - for (n = 0; n < (max_size - 1); n++) { - if (the_name[n] != 0) - function_name[n] = the_name[n]; - else - break; - } - function_name[n] = 0; - } else - function_name[0] = 0; - return function_name; + if ((stack_index > -1) && (stack_index < STACK_LEN) && _setup.stack[stack_index]) + return _setup.stack[stack_index]; + return {}; } /***********************************************************************/ @@ -2593,23 +2513,17 @@ int Interp::ini_load(const char *filename) logDebug("Opened inifile:%s:", filename); - char parameter_file_name[LINELEN]={}; + std::string parameter_file_name; if (auto inistring = inifile.findString("PARAMETER_FILE", "RS274NGC")) { - if (inistring->length() >= sizeof(parameter_file_name)) { - logDebug("%s:[RS274NGC]PARAMETER_FILE is too long (max len %zu)", - filename, sizeof(parameter_file_name)-1); - } else { - strncpy(parameter_file_name, inistring->c_str(), sizeof(parameter_file_name)-1); - parameter_file_name[sizeof(parameter_file_name)-1] = '\0'; - logDebug("found PARAMETER_FILE:%s:", parameter_file_name); - } + parameter_file_name = *inistring; + logDebug("found PARAMETER_FILE:%s:", inistring->c_str()); } else { // not found, leave RS274NGC_PARAMETER_FILE alone logDebug("did not find PARAMETER_FILE"); } SET_PARAMETER_FILE_NAME(parameter_file_name); - CHKS((strlen(parameter_file_name) == 0), _("Parameter file name is missing")); + CHKS(parameter_file_name.empty(), _("Parameter file name is missing")); return 0; } @@ -2787,6 +2701,18 @@ int Interp::on_abort(int reason, const char *message) return status; } +// expand '~' and variables the way the shell would, keeping the first word +static std::string expand_path(const std::string &path) +{ + wordexp_t exp_result{}; + std::string out = path; + if (wordexp(path.c_str(), &exp_result, 0) == 0 && exp_result.we_wordc > 0) + out = exp_result.we_wordv[0]; + // exp_result starts zeroed, so freeing it is safe whatever wordexp() returned + wordfree(&exp_result); + return out; +} + // spun out from interp_o_word so we can use it to test ngc file accessibility during // config file parsing (REMAP... ngc=) // Will expand ~ to user's home path @@ -2795,90 +2721,44 @@ int Interp::on_abort(int reason, const char *message) // 2) tries adding the INI defined program prefix to path // 3) tries adding the INI defined subroutine prefix to path // 4) tries adding the INI defined whizard prefix to path -FILE *Interp::find_ngc_file(setup_pointer settings,const char *basename, char *foundhere ) +FILE *Interp::find_ngc_file(setup_pointer settings, std::string_view basename, std::string *foundhere) { - FILE *newFP = NULL; - char tmpFileName[PATH_MAX+1]; - char newFileName[PATH_MAX+1]; - char foundPlace[PATH_MAX+1]; - int dct; - wordexp_t exp_result; - - // #1 check if this is the full path already - - // expand user path - wordexp(basename, &exp_result, 0); - // add .ngc to expanded path - snprintf(tmpFileName, sizeof(tmpFileName), "%s.ngc", exp_result.we_wordv[0]); - - // copy to newFileName - in case this is the one... - size_t chk = snprintf(newFileName, sizeof(newFileName), "%s", tmpFileName); - - // found a file we can open? - if (chk < sizeof(newFileName)){ - newFP = fopen(newFileName, "r"); - } + // #1 check if this is the full path already: expand the user path, add .ngc + const std::string tmpFileName = expand_path(std::string(basename)) + ".ngc"; + std::string newFileName = tmpFileName; + FILE *newFP = fopen(newFileName.c_str(), "r"); // #2 then look in the program_prefix place - if (!newFP) { - - // expand '~' into user path - wordexp(settings->program_prefix, &exp_result, 0); - chk = snprintf(newFileName, sizeof(newFileName), "%s/%s", exp_result.we_wordv[0], tmpFileName); - - // found a file we can open? - if (chk < sizeof(newFileName)){ - newFP = fopen(newFileName, "r"); - } + if (!newFP && !settings->program_prefix.empty()) { + newFileName = expand_path(settings->program_prefix) + "/" + tmpFileName; + newFP = fopen(newFileName.c_str(), "r"); } - + // #3 then look in the list of subroutines prefixes if (!newFP) { - for (dct = 0; dct < MAX_SUB_DIRS; dct++) { + for (int dct = 0; dct < MAX_SUB_DIRS; dct++) { if (!settings->subroutines[dct]) - continue; - - // expand '~' into user path - wordexp(settings->subroutines[dct], &exp_result, 0); - chk = snprintf(newFileName, sizeof(newFileName), "%s/%s", exp_result.we_wordv[0], tmpFileName); - - // found a file we can open? - if (chk < sizeof(newFileName)){ - newFP = fopen(newFileName, "r"); - if (newFP) { - // logOword("fopen: |%s|", newFileName); + continue; + newFileName = expand_path(settings->subroutines[dct]) + "/" + tmpFileName; + newFP = fopen(newFileName.c_str(), "r"); + if (newFP) break; // use first occurrence in dir search - } - } - } + } } // #4 if still not found, search the wizard tree // Wiz directory already expands the '~' to user path if (!newFP) { - int ret; - - // walks the directory hierarchy ? - ret = findFile(settings->wizard_root, tmpFileName, foundPlace); - - if (INTERP_OK == ret) { - // create the long name - chk = snprintf(newFileName, sizeof(newFileName), "%s/%s", - foundPlace, tmpFileName); - - // found a file we can open? - if (chk < sizeof(newFileName)){ - newFP = fopen(newFileName, "r"); - } + std::string foundPlace; + if (findFile(settings->wizard_root, tmpFileName, foundPlace) == INTERP_OK) { + newFileName = foundPlace + "/" + tmpFileName; + newFP = fopen(newFileName.c_str(), "r"); } } // pass what we found - if (foundhere && (newFP != NULL)) - strcpy(foundhere, newFileName); - - // Not sure this is needed but the internet told me - wordfree(&exp_result); + if (foundhere && newFP) + *foundhere = newFileName; return newFP; } diff --git a/src/emc/sai/driver.cc b/src/emc/sai/driver.cc index 850471d1a35..39ea1cd4fe7 100644 --- a/src/emc/sai/driver.cc +++ b/src/emc/sai/driver.cc @@ -30,6 +30,8 @@ #include /* toupper */ #include #include +#include +#include #include #include @@ -107,24 +109,19 @@ void report_error( /* ARGUMENTS */ int error_code, /* the code number of the error message */ int print_stack) /* print stack if ON, otherwise not */ { - char interp_error_text_buf[LINELEN]; - int k; - - error_text(error_code, interp_error_text_buf, 5); /* for coverage of code */ - error_text(error_code, interp_error_text_buf, LINELEN); + const std::string text = error_text(error_code); fprintf(stderr, "%s\n", - ((interp_error_text_buf[0] == 0) ? "Unknown error, bad error code" : interp_error_text_buf)); - line_text(interp_error_text_buf, LINELEN); - fprintf(stderr, "%s\n", interp_error_text_buf); + text.empty() ? "Unknown error, bad error code" : text.c_str()); + fprintf(stderr, "%s\n", line_text().c_str()); if (print_stack == ON) { - for (k = 0; ; k++) + // a plugin interpreter may never return an empty name + for (int k = 0; k < STACK_LEN; k++) { - stack_name(k, interp_error_text_buf, LINELEN); - if (interp_error_text_buf[0] != 0) - fprintf(stderr, "%s\n", interp_error_text_buf); - else + const std::string name = stack_name(k); + if (name.empty()) break; + fprintf(stderr, "%s\n", name.c_str()); } } } @@ -360,21 +357,16 @@ Called By: main */ -int designate_parameter_file(char * parameter_file_name) +int designate_parameter_file(std::string ¶meter_file_name) { - FILE * test_port; - - fprintf(stderr, "name of parameter file => "); - if(!fgets(parameter_file_name, PARAMETER_FILE_NAME_LENGTH, stdin)) + std::cerr << "name of parameter file => "; + if (!std::getline(std::cin, parameter_file_name)) return 1; - parameter_file_name[strlen(parameter_file_name) - 1] = 0; - test_port = fopen(parameter_file_name, "r"); - if (test_port == NULL) + if (!std::ifstream(parameter_file_name)) { - fprintf(stderr, "Cannot open %s\n", parameter_file_name); + std::cerr << "Cannot open " << parameter_file_name << "\n"; return 1; } - fclose(test_port); return 0; } @@ -744,8 +736,7 @@ int main (int argc, char ** argv) exit(1); } status = interpret_from_file(do_next, block_delete, print_stack); - file_name(buffer, 5); /* called to exercise the function */ - file_name(buffer, 79); /* called to exercise the function */ + file_name(); /* called to exercise the function */ interp_close(); } line_length(); /* called to exercise the function */ diff --git a/src/emc/sai/saicanon.cc b/src/emc/sai/saicanon.cc index 11ea4dfae7e..befb9da5287 100644 --- a/src/emc/sai/saicanon.cc +++ b/src/emc/sai/saicanon.cc @@ -41,12 +41,13 @@ #include #include #include +#include -#define UNEXPECTED_MSG fprintf(stderr,"UNEXPECTED %s %d\n",__FILE__,__LINE__); +#define UNEXPECTED_MSG fmt::print(stderr, "UNEXPECTED {} {}\n", __FILE__, __LINE__); StandaloneInterpInternals _sai = StandaloneInterpInternals(); -char _parameter_file_name[PARAMETER_FILE_NAME_LENGTH]; +std::string _parameter_file_name; /* where to print */ FILE * _outfile = stdout; /* where to print, set in main */ @@ -74,51 +75,46 @@ extern InterpBase *pinterp; void print_nc_line_number() { - char text[256]; - int k; - int m; - - pinterp->line_text(text, 256); - for (k = 0; - ((k < 256) && - ((text[k] == '\t') || (text[k] == ' ') || (text[k] == '/'))); - k++); - if ((k < 256) && ((text[k] == 'n') || (text[k] == 'N'))) + // the first 255 characters, as the 256-byte buffer this read into held + const std::string text = pinterp->line_text().substr(0, 255); + size_t k = text.find_first_not_of("\t /"); + if (k == std::string::npos) + k = text.size(); + if (k < text.size() && (text[k] == 'n' || text[k] == 'N')) { fputc('N', _outfile); - for (k++, m = 0; - ((k < 256) && (text[k] >= '0') && (text[k] <= '9')); - k++, m++) + int m = 0; + for (k++; k < text.size() && text[k] >= '0' && text[k] <= '9'; k++, m++) fputc(text[k], _outfile); for (; m < 6; m++) fputc(' ', _outfile); } - else if (k < 256) + else fprintf(_outfile, "N..... "); } -#define ECHO_WITH_ARGS(fmt, ...) PRINT("%s(" fmt ")\n", __FUNCTION__, ##__VA_ARGS__) +#define ECHO_WITH_ARGS(fmt, ...) PRINT("{}(" fmt ")\n", __FUNCTION__, ##__VA_ARGS__) #define PRINT(control, ...) do \ { \ - fprintf(_outfile, "%5d ", _sai._line_number++); \ + fmt::print(_outfile, "{:5d} ", _sai._line_number++); \ print_nc_line_number(); \ - fprintf(_outfile, control, ##__VA_ARGS__); \ + fmt::print(_outfile, control, ##__VA_ARGS__); \ } while (false) /* Representation */ void SET_XY_ROTATION(double t) { - ECHO_WITH_ARGS("%.4f", t); + ECHO_WITH_ARGS("{:.4f}", t); } void HOME_CYCLE(void) { ECHO_WITH_ARGS(""); } -void HOME_CYCLE_JOINT(int joint) { ECHO_WITH_ARGS("%d", joint); } +void HOME_CYCLE_JOINT(int joint) { ECHO_WITH_ARGS("{}", joint); } void SET_G68_FRAME(double x, double y, double z, const double rotation[9], int active) { - ECHO_WITH_ARGS("%.4f, %.4f, %.4f, " - "[%.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f], %d", + ECHO_WITH_ARGS("{:.4f}, {:.4f}, {:.4f}, " + "[{:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}], {}", x, y, z, rotation[0], rotation[1], rotation[2], rotation[3], rotation[4], rotation[5], @@ -130,7 +126,7 @@ void SET_G5X_OFFSET(int index, double a, double b, double c, double /*u*/, double /*v*/, double /*w*/) { - ECHO_WITH_ARGS("%d, %.4f, %.4f, %.4f, %.4f, %.4f, %.4f", + ECHO_WITH_ARGS("{}, {:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}", index, x, y, z, a, b, c); _sai._program_position_x = _sai._program_position_x + _sai._g5x_x - x; _sai._program_position_y = _sai._program_position_y + _sai._g5x_y - y; @@ -150,7 +146,7 @@ void SET_G5X_OFFSET(int index, void SET_G92_OFFSET(double x, double y, double z, double a, double b, double c, double /*u*/, double /*v*/, double /*w*/) { - ECHO_WITH_ARGS("%.4f, %.4f, %.4f, %.4f, %.4f, %.4f", + ECHO_WITH_ARGS("{:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}, {:.4f}", x, y, z, a, b, c); _sai._program_position_x = _sai._program_position_x + _sai._g92_x - x; _sai._program_position_y = _sai._program_position_y + _sai._g92_y - y; @@ -218,7 +214,7 @@ void USE_LENGTH_UNITS(CANON_UNITS in_unit) /* Free Space Motion */ void SET_TRAVERSE_RATE(double rate) { - PRINT("SET_TRAVERSE_RATE(%.4f)\n", rate); + PRINT("SET_TRAVERSE_RATE({:.4f})\n", rate); _sai._traverse_rate = rate; } @@ -230,10 +226,10 @@ void STRAIGHT_TRAVERSE( int /*line_number*/, , double /*u*/, double /*v*/, double /*w*/ ) { - ECHO_WITH_ARGS("%.4f, %.4f, %.4f" - ", %.4f" /*AA*/ - ", %.4f" /*BB*/ - ", %.4f" /*CC*/ + ECHO_WITH_ARGS("{:.4f}, {:.4f}, {:.4f}" + ", {:.4f}" /*AA*/ + ", {:.4f}" /*BB*/ + ", {:.4f}" /*CC*/ , x, y, z , a /*AA*/ , b /*BB*/ @@ -250,18 +246,18 @@ void STRAIGHT_TRAVERSE( int /*line_number*/, /* Machining Attributes */ void SET_FEED_MODE(int spindle, int mode) { - PRINT("SET_FEED_MODE(%d, %d)\n", spindle, mode); + PRINT("SET_FEED_MODE({}, {})\n", spindle, mode); _sai._feed_mode = mode; } void SET_FEED_RATE(double rate) { - PRINT("SET_FEED_RATE(%.4f)\n", rate); + PRINT("SET_FEED_RATE({:.4f})\n", rate); _sai._feed_rate = rate; } void SET_FEED_REFERENCE(CANON_FEED_REFERENCE reference) { - PRINT("SET_FEED_REFERENCE(%s)\n", + PRINT("SET_FEED_REFERENCE({})\n", (reference == CANON_WORKPIECE) ? "CANON_WORKPIECE" : "CANON_XYZ"); } @@ -270,7 +266,7 @@ extern void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE mode, double tolerance, { /* G64_R_PLANNER: standalone-interp echo of the optional planner mode */ if (planner_type >= 0 || scurve_peak_scale >= 0.0) - PRINT("SET_PLANNER_MODE(type=%d, peak_scale=%f)\n", planner_type, scurve_peak_scale); + PRINT("SET_PLANNER_MODE(type={}, peak_scale={:f})\n", planner_type, scurve_peak_scale); _sai.motion_tolerance = 0; if (mode == CANON_EXACT_STOP) { @@ -285,7 +281,7 @@ extern void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE mode, double tolerance, else if (mode == CANON_CONTINUOUS) { _sai.motion_tolerance = tolerance; - PRINT("SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, %f)\n", tolerance); + PRINT("SET_MOTION_CONTROL_MODE(CANON_CONTINUOUS, {:f})\n", tolerance); _sai._motion_mode = CANON_CONTINUOUS; } else @@ -295,12 +291,12 @@ extern void SET_MOTION_CONTROL_MODE(CANON_MOTION_MODE mode, double tolerance, extern void SET_NAIVECAM_TOLERANCE(double tolerance) { _sai.naivecam_tolerance = tolerance; - PRINT("SET_NAIVECAM_TOLERANCE(%.4f)\n", tolerance); + PRINT("SET_NAIVECAM_TOLERANCE({:.4f})\n", tolerance); } void SELECT_PLANE(CANON_PLANE in_plane) { - PRINT("SELECT_PLANE(CANON_PLANE_%s)\n", + PRINT("SELECT_PLANE(CANON_PLANE_{})\n", ((in_plane == CANON_PLANE::XY) ? "XY" : (in_plane == CANON_PLANE::YZ) ? "YZ" : (in_plane == CANON_PLANE::XZ) ? "XZ" : "UNKNOWN")); @@ -308,10 +304,10 @@ void SELECT_PLANE(CANON_PLANE in_plane) } void SET_CUTTER_RADIUS_COMPENSATION(double radius) -{PRINT("SET_CUTTER_RADIUS_COMPENSATION(%.4f)\n", radius);} +{PRINT("SET_CUTTER_RADIUS_COMPENSATION({:.4f})\n", radius);} void START_CUTTER_RADIUS_COMPENSATION(int side) -{PRINT("START_CUTTER_RADIUS_COMPENSATION(%s)\n", +{PRINT("START_CUTTER_RADIUS_COMPENSATION({})\n", (side == CANON_SIDE_LEFT) ? "LEFT" : (side == CANON_SIDE_RIGHT) ? "RIGHT" : "UNKNOWN"); } @@ -329,7 +325,7 @@ void STOP_SPEED_FEED_SYNCH() /* Machining Functions G_5_2 */ void NURBS_G5_FEED(int /*lineno*/, const std::vector& nurbs_control_points, unsigned int /*nurbs_order*/, CANON_PLANE /*plane*/) { - ECHO_WITH_ARGS("%lu, ...", (unsigned long)nurbs_control_points.size()); + ECHO_WITH_ARGS("{}, ...", nurbs_control_points.size()); _sai._program_position_x = nurbs_control_points[nurbs_control_points.size()-1].NURBS_X; _sai._program_position_y = nurbs_control_points[nurbs_control_points.size()-1].NURBS_Y; @@ -339,7 +335,7 @@ void NURBS_G5_FEED(int /*lineno*/, const std::vector& nurbs void NURBS_G6_FEED(int /*lineno*/, const std::vector& nurbs_control_points, unsigned int /*k*/, double /*feedrate*/, int /*l*/, CANON_PLANE /*plane*/) { //fprintf(_outfile, "%5d ", _line_number++); print_nc_line_number(); - fprintf(_outfile, "saicanon NURBS_G6_FEED_(%lu, ...)\n", (unsigned long)nurbs_control_points.size()); + fmt::print(_outfile, "saicanon NURBS_G6_FEED_({}, ...)\n", nurbs_control_points.size()); _sai._program_position_x = nurbs_control_points[nurbs_control_points.size()-1].NURBS_X; _sai._program_position_y = nurbs_control_points[nurbs_control_points.size()-1].NURBS_Y; @@ -354,10 +350,10 @@ void ARC_FEED(int /*line_number*/, , double /*u*/, double /*v*/, double /*w*/ ) { - ECHO_WITH_ARGS("%.4f, %.4f, %.4f, %.4f, %d, %.4f" - ", %.4f" /*AA*/ - ", %.4f" /*BB*/ - ", %.4f" /*CC*/ + ECHO_WITH_ARGS("{:.4f}, {:.4f}, {:.4f}, {:.4f}, {}, {:.4f}" + ", {:.4f}" /*AA*/ + ", {:.4f}" /*BB*/ + ", {:.4f}" /*CC*/ , first_end, second_end, first_axis, second_axis, rotation, axis_end_point , a /*AA*/ @@ -395,10 +391,10 @@ void STRAIGHT_FEED(int /*line_number*/, , double /*u*/, double /*v*/, double /*w*/ ) { - ECHO_WITH_ARGS("%.4f, %.4f, %.4f" - ", %.4f" /*AA*/ - ", %.4f" /*BB*/ - ", %.4f" /*CC*/ + ECHO_WITH_ARGS("{:.4f}, {:.4f}, {:.4f}" + ", {:.4f}" /*AA*/ + ", {:.4f}" /*BB*/ + ", {:.4f}" /*CC*/ , x, y, z , a /*AA*/ , b /*BB*/ @@ -434,10 +430,10 @@ void STRAIGHT_PROBE(int /*line_number*/, dz = (_sai._program_position_z - z); distance = sqrt((dx * dx) + (dy * dy) + (dz * dz)); - ECHO_WITH_ARGS("%.4f, %.4f, %.4f" - ", %.4f" /*AA*/ - ", %.4f" /*BB*/ - ", %.4f" /*CC*/ + ECHO_WITH_ARGS("{:.4f}, {:.4f}, {:.4f}" + ", {:.4f}" /*AA*/ + ", {:.4f}" /*BB*/ + ", {:.4f}" /*CC*/ , x, y, z , a /*AA*/ , b /*BB*/ @@ -464,13 +460,13 @@ void STRAIGHT_PROBE(int /*line_number*/, void RIGID_TAP(int /*line_number*/, double x, double y, double z, double /*scale*/) { - ECHO_WITH_ARGS("%.4f, %.4f, %.4f", x, y, z); + ECHO_WITH_ARGS("{:.4f}, {:.4f}, {:.4f}", x, y, z); } void DWELL(double seconds) { - ECHO_WITH_ARGS("%.4f", seconds); + ECHO_WITH_ARGS("{:.4f}", seconds); } /* Spindle Functions */ @@ -478,32 +474,32 @@ void SPINDLE_RETRACT_TRAVERSE() {PRINT("SPINDLE_RETRACT_TRAVERSE()\n");} void SET_SPINDLE_MODE(int spindle, double arg) { - PRINT("SET_SPINDLE_MODE(%d %.4f)\n", spindle, arg); + PRINT("SET_SPINDLE_MODE({} {:.4f})\n", spindle, arg); } void START_SPINDLE_CLOCKWISE(int spindle, int /*wait_for_atspeed*/) { - PRINT("START_SPINDLE_CLOCKWISE(%i)\n", spindle); + PRINT("START_SPINDLE_CLOCKWISE({})\n", spindle); _sai._spindle_turning[spindle] = ((_sai._spindle_speed[spindle] == 0) ? CANON_STOPPED : CANON_CLOCKWISE); } void START_SPINDLE_COUNTERCLOCKWISE(int spindle, int /*wait_for_atspeed*/) { - PRINT("START_SPINDLE_COUNTERCLOCKWISE(%i)\n", spindle); + PRINT("START_SPINDLE_COUNTERCLOCKWISE({})\n", spindle); _sai._spindle_turning[spindle] = ((_sai._spindle_speed[spindle] == 0) ? CANON_STOPPED : CANON_COUNTERCLOCKWISE); } void SET_SPINDLE_SPEED(int spindle, double rpm) { - PRINT("SET_SPINDLE_SPEED(%i, %.4f)\n", spindle, rpm); + PRINT("SET_SPINDLE_SPEED({}, {:.4f})\n", spindle, rpm); _sai._spindle_speed[spindle] = rpm; } void STOP_SPINDLE_TURNING(int spindle, int /*wait_for_atspeed*/) { - PRINT("STOP_SPINDLE_TURNING(%i)\n", spindle); + PRINT("STOP_SPINDLE_TURNING({})\n", spindle); _sai._spindle_turning[spindle] = CANON_STOPPED; } @@ -511,12 +507,12 @@ void SPINDLE_RETRACT() {PRINT("SPINDLE_RETRACT()\n");} void ORIENT_SPINDLE(int spindle, double orientation, int mode) -{PRINT("ORIENT_SPINDLE(%d, %.4f, %d)\n", spindle, orientation, mode); +{PRINT("ORIENT_SPINDLE({}, {:.4f}, {})\n", spindle, orientation, mode); } void WAIT_SPINDLE_ORIENT_COMPLETE(int spindle, double timeout) { - PRINT("SPINDLE.%i.WAIT_ORIENT_COMPLETE(%.4f)\n", spindle, timeout); + PRINT("SPINDLE.{}.WAIT_ORIENT_COMPLETE({:.4f})\n", spindle, timeout); } void USE_NO_SPINDLE_FORCE() @@ -545,11 +541,11 @@ void SET_TOOL_TABLE_ENTRY(int idx, int toolno, const EmcPose& offset, double dia tdata.backangle = backangle; tdata.orientation = orientation; if (tooldata_put(tdata,idx) == IDX_FAIL) { - fprintf(stderr,"UNEXPECTED idx %s %d\n",__FILE__,__LINE__); + fmt::print(stderr, "UNEXPECTED idx {} {}\n", __FILE__, __LINE__); } #endif //} - ECHO_WITH_ARGS("%d, %d, %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f %.4f, %.4f, %.4f, %d", + ECHO_WITH_ARGS("{}, {}, {:.4f} {:.4f} {:.4f} {:.4f} {:.4f} {:.4f} {:.4f} {:.4f} {:.4f}, {:.4f}, {:.4f}, {}", idx, toolno, offset.tran.x, offset.tran.y, offset.tran.z, offset.a, offset.b, offset.c, offset.u, offset.v, offset.w, frontangle, backangle, orientation); @@ -558,7 +554,7 @@ void SET_TOOL_TABLE_ENTRY(int idx, int toolno, const EmcPose& offset, double dia void USE_TOOL_LENGTH_OFFSET(const EmcPose& offset) { _sai._tool_offset = offset; - ECHO_WITH_ARGS("%.4f %.4f %.4f, %.4f %.4f %.4f, %.4f %.4f %.4f", + ECHO_WITH_ARGS("{:.4f} {:.4f} {:.4f}, {:.4f} {:.4f} {:.4f}, {:.4f} {:.4f} {:.4f}", offset.tran.x, offset.tran.y, offset.tran.z, offset.a, offset.b, offset.c, offset.u, offset.v, offset.w); } @@ -575,20 +571,20 @@ void CHANGE_TOOL() } _sai._tools[0] = tdata; if (tooldata_put(tdata,0) == IDX_FAIL) { - fprintf(stderr,"UNEXPECTED idx %s %d\n",__FILE__,__LINE__); + fmt::print(stderr, "UNEXPECTED idx {} {}\n", __FILE__, __LINE__); } #endif //} } void SELECT_TOOL(int tool)//TODO: fix slot number { - PRINT("SELECT_TOOL(%d)\n", tool); + PRINT("SELECT_TOOL({})\n", tool); _sai._selected_tool = tool; } void CHANGE_TOOL_NUMBER(int tool) { - PRINT("CHANGE_TOOL_NUMBER(%d)\n", tool); + PRINT("CHANGE_TOOL_NUMBER({})\n", tool); _sai._active_slot = tool; } @@ -601,7 +597,7 @@ void RELOAD_TOOLDATA(void) /* Misc Functions */ void CLAMP_AXIS(CANON_AXIS axis) -{PRINT("CLAMP_AXIS(%s)\n", +{PRINT("CLAMP_AXIS({})\n", (axis == CANON_AXIS_X) ? "CANON_AXIS_X" : (axis == CANON_AXIS_Y) ? "CANON_AXIS_Y" : (axis == CANON_AXIS_Z) ? "CANON_AXIS_Z" : @@ -609,8 +605,8 @@ void CLAMP_AXIS(CANON_AXIS axis) (axis == CANON_AXIS_B) ? "CANON_AXIS_B" : (axis == CANON_AXIS_C) ? "CANON_AXIS_C" : "UNKNOWN");} -void COMMENT(const char *s) -{PRINT("COMMENT(\"%s\")\n", s);} +void COMMENT(std::string_view s) +{PRINT("COMMENT(\"{}\")\n", s);} void DISABLE_ADAPTIVE_FEED() {PRINT("DISABLE_ADAPTIVE_FEED()\n");} @@ -622,7 +618,7 @@ void DISABLE_FEED_OVERRIDE() {PRINT("DISABLE_FEED_OVERRIDE()\n"); fo_enable = false; } void DISABLE_SPEED_OVERRIDE(int spindle) -{PRINT("DISABLE_SPEED_OVERRIDE(%i)\n", spindle); so_enable = false; } +{PRINT("DISABLE_SPEED_OVERRIDE({})\n", spindle); so_enable = false; } void ENABLE_ADAPTIVE_FEED() {PRINT("ENABLE_ADAPTIVE_FEED()\n");} @@ -634,10 +630,10 @@ void ENABLE_FEED_OVERRIDE() {PRINT("ENABLE_FEED_OVERRIDE()\n"); fo_enable = true; } void ENABLE_SPEED_OVERRIDE(int spindle) -{PRINT("ENABLE_SPEED_OVERRIDE(%i)\n", spindle); so_enable = true; } +{PRINT("ENABLE_SPEED_OVERRIDE({})\n", spindle); so_enable = true; } void LOCK_SPEED_OVERRIDE(int spindle) -{PRINT("LOCK_SPEED_OVERRIDE(%i)\n", spindle); } +{PRINT("LOCK_SPEED_OVERRIDE({})\n", spindle); } void FLOOD_OFF() { @@ -655,15 +651,15 @@ void INIT_CANON() { } -void MESSAGE(char *s) -{PRINT("MESSAGE(\"%s\")\n", s);} +void MESSAGE(std::string_view s) +{PRINT("MESSAGE(\"{}\")\n", s);} -void LOG(char *s) -{PRINT("LOG(\"%s\")\n", s);} -void LOGOPEN(char *s) -{PRINT("LOGOPEN(\"%s\")\n", s);} -void LOGAPPEND(char *s) -{PRINT("LOGAPPEND(\"%s\")\n", s);} +void LOG(std::string_view s) +{PRINT("LOG(\"{}\")\n", s);} +void LOGOPEN(std::string_view s) +{PRINT("LOGOPEN(\"{}\")\n", s);} +void LOGAPPEND(std::string_view s) +{PRINT("LOGAPPEND(\"{}\")\n", s);} void LOGCLOSE() {PRINT("LOGCLOSE()\n");} @@ -689,7 +685,7 @@ void TURN_PROBE_ON() {PRINT("TURN_PROBE_ON()\n");} void UNCLAMP_AXIS(CANON_AXIS axis) -{PRINT("UNCLAMP_AXIS(%s)\n", +{PRINT("UNCLAMP_AXIS({})\n", (axis == CANON_AXIS_X) ? "CANON_AXIS_X" : (axis == CANON_AXIS_Y) ? "CANON_AXIS_Y" : (axis == CANON_AXIS_Z) ? "CANON_AXIS_Z" : @@ -758,9 +754,9 @@ void START_SPEED_FEED_SYNCH(int /*spindle*/, double sync, bool vel, double angle // only print the angle when one was asked for, so that the expected output // of tests predating the D word stays valid if (angle_degrees != 0.0) - PRINT("START_SPEED_FEED_SYNC(%f,%d,%f)\n", sync, vel, angle_degrees); + PRINT("START_SPEED_FEED_SYNC({:f},{:d},{:f})\n", sync, vel, angle_degrees); else - PRINT("START_SPEED_FEED_SYNC(%f,%d)\n", sync, vel); + PRINT("START_SPEED_FEED_SYNC({:f},{:d})\n", sync, vel); } CANON_MOTION_MODE motion_mode; @@ -816,26 +812,14 @@ extern int GET_EXTERNAL_G68_FRAME(double * /*origin*/, double * /*rotation*/) return -1; } -extern void SET_PARAMETER_FILE_NAME(const char *name) +void SET_PARAMETER_FILE_NAME(std::string_view name) { - strncpy(_parameter_file_name, name, PARAMETER_FILE_NAME_LENGTH - 1); + _parameter_file_name = name; } -void GET_EXTERNAL_PARAMETER_FILE_NAME( - char * file_name, /* string: to copy file name into */ - int max_size) /* maximum number of characters to copy */ +std::string GET_EXTERNAL_PARAMETER_FILE_NAME() { - // Paranoid checks - if (NULL == file_name) - return; - - if (max_size < 0) - return; - - if (strlen(_parameter_file_name) < (size_t)max_size) - strcpy(file_name, _parameter_file_name); - else - file_name[0] = 0; + return _parameter_file_name; } CANON_PLANE GET_EXTERNAL_PLANE() @@ -843,113 +827,31 @@ CANON_PLANE GET_EXTERNAL_PLANE() return _sai._active_plane; } -/* returns the current a-axis position */ -double GET_EXTERNAL_POSITION_A() -{ - return _sai._program_position_a; -} - -/* returns the current b-axis position */ -double GET_EXTERNAL_POSITION_B() -{ - return _sai._program_position_b; -} - -/* returns the current c-axis position */ -double GET_EXTERNAL_POSITION_C() -{ - return _sai._program_position_c; -} - -/* returns the current x-axis position */ -double GET_EXTERNAL_POSITION_X() -{ - return _sai._program_position_x; -} - -/* returns the current y-axis position */ -double GET_EXTERNAL_POSITION_Y() -{ - return _sai._program_position_y; -} - -/* returns the current z-axis position */ -double GET_EXTERNAL_POSITION_Z() -{ - return _sai._program_position_z; -} - -// XXX fix sai for uvw -double GET_EXTERNAL_POSITION_U() -{ - return 0.; -} - -double GET_EXTERNAL_POSITION_V() -{ - return 0.; -} - -double GET_EXTERNAL_POSITION_W() -{ - return 0.; -} - -double GET_EXTERNAL_PROBE_POSITION_U() -{ - return 0.; -} - -double GET_EXTERNAL_PROBE_POSITION_V() -{ - return 0.; -} - -double GET_EXTERNAL_PROBE_POSITION_W() -{ - return 0.; -} - -/* returns the a-axis position at the last probe trip. This is only valid - once the probe command has executed to completion. */ -double GET_EXTERNAL_PROBE_POSITION_A() -{ - return _sai._probe_position_a; -} - -/* returns the b-axis position at the last probe trip. This is only valid - once the probe command has executed to completion. */ -double GET_EXTERNAL_PROBE_POSITION_B() +/* returns the current position. XXX fix sai for uvw */ +CANON_POSITION GET_EXTERNAL_POSITION() { - return _sai._probe_position_b; + CANON_POSITION pos; // u, v, w stay 0 + pos.x = _sai._program_position_x; + pos.y = _sai._program_position_y; + pos.z = _sai._program_position_z; + pos.a = _sai._program_position_a; + pos.b = _sai._program_position_b; + pos.c = _sai._program_position_c; + return pos; } -/* returns the c-axis position at the last probe trip. This is only valid +/* returns the position at the last probe trip. This is only valid once the probe command has executed to completion. */ -double GET_EXTERNAL_PROBE_POSITION_C() +CANON_POSITION GET_EXTERNAL_PROBE_POSITION() { - return _sai._probe_position_c; -} - -/* returns the x-axis position at the last probe trip. This is only valid - once the probe command has executed to completion. */ -double GET_EXTERNAL_PROBE_POSITION_X() -{ - return _sai._probe_position_x; -} - -/* returns the y-axis position at the last probe trip. This is only valid - once the probe command has executed to completion. */ -double GET_EXTERNAL_PROBE_POSITION_Y() -{ - return _sai._probe_position_y; -} - -/* returns the z-axis position at the last probe trip. This is only valid - once the probe command has executed to completion. */ -double GET_EXTERNAL_PROBE_POSITION_Z() -{ - return _sai._probe_position_z; + CANON_POSITION pos; // u, v, w stay 0 + pos.x = _sai._probe_position_x; + pos.y = _sai._probe_position_y; + pos.z = _sai._probe_position_z; + pos.a = _sai._probe_position_a; + pos.b = _sai._probe_position_b; + pos.c = _sai._probe_position_c; + return pos; } /* Returns the value for any analog non-contact probing. */ @@ -1039,83 +941,43 @@ int USER_DEFINED_FUNCTION_ADD(USER_DEFINED_FUNCTION_TYPE func, int num) void SET_MOTION_OUTPUT_BIT(int index) { - PRINT("SET_MOTION_OUTPUT_BIT(%d)\n", index); + PRINT("SET_MOTION_OUTPUT_BIT({})\n", index); return; } void CLEAR_MOTION_OUTPUT_BIT(int index) { - PRINT("CLEAR_MOTION_OUTPUT_BIT(%d)\n", index); + PRINT("CLEAR_MOTION_OUTPUT_BIT({})\n", index); return; } void SET_MOTION_OUTPUT_VALUE(int index, double value) { - PRINT("SET_MOTION_OUTPUT_VALUE(%d,%f)\n", index, value); + PRINT("SET_MOTION_OUTPUT_VALUE({},{:f})\n", index, value); return; } void SET_AUX_OUTPUT_BIT(int index) { - PRINT("SET_AUX_OUTPUT_BIT(%d)\n", index); + PRINT("SET_AUX_OUTPUT_BIT({})\n", index); return; } void CLEAR_AUX_OUTPUT_BIT(int index) { - PRINT("CLEAR_AUX_OUTPUT_BIT(%d)\n", index); + PRINT("CLEAR_AUX_OUTPUT_BIT({})\n", index); return; } void SET_AUX_OUTPUT_VALUE(int index, double value) { - PRINT("SET_AUX_OUTPUT_VALUE(%d,%f)\n", index, value); + PRINT("SET_AUX_OUTPUT_VALUE({},{:f})\n", index, value); return; } -double GET_EXTERNAL_TOOL_LENGTH_XOFFSET() -{ - return _sai._tool_offset.tran.x; -} - -double GET_EXTERNAL_TOOL_LENGTH_YOFFSET() -{ - return _sai._tool_offset.tran.y; -} - -double GET_EXTERNAL_TOOL_LENGTH_ZOFFSET() -{ - return _sai._tool_offset.tran.z; -} - -double GET_EXTERNAL_TOOL_LENGTH_AOFFSET() +EmcPose GET_EXTERNAL_TOOL_LENGTH_OFFSET() { - return _sai._tool_offset.a; -} - -double GET_EXTERNAL_TOOL_LENGTH_BOFFSET() -{ - return _sai._tool_offset.b; -} - -double GET_EXTERNAL_TOOL_LENGTH_COFFSET() -{ - return _sai._tool_offset.c; -} - -double GET_EXTERNAL_TOOL_LENGTH_UOFFSET() -{ - return _sai._tool_offset.u; -} - -double GET_EXTERNAL_TOOL_LENGTH_VOFFSET() -{ - return _sai._tool_offset.v; -} - -double GET_EXTERNAL_TOOL_LENGTH_WOFFSET() -{ - return _sai._tool_offset.w; + return _sai._tool_offset; } void FINISH(void) { @@ -1156,26 +1018,9 @@ EmcPose GET_EXTERNAL_OFFSETS() { }; /* Sends error message */ -void CANON_ERROR(const char *fmt, ...) -{ - va_list ap; - - if (fmt != NULL) { - va_start(ap, fmt); - char *err; - int res = vasprintf(&err, fmt, ap); - if(res < 0) err = NULL; - va_end(ap); - if(err) - { - PRINT("CANON_ERROR(%s)\n", err); - free(err); - } - else - { - PRINT("CANON_ERROR(vasprintf failed: %s)\n", strerror(errno)); - } - } +void CANON_ERROR(std::string_view message) +{ + PRINT("CANON_ERROR({})\n", message); } void reset_internals() @@ -1245,5 +1090,5 @@ void UPDATE_TAG(const StateTag& /*tag*/){ void SELECT_KINS_TYPE(int switchkins_type) { - ECHO_WITH_ARGS("%d", switchkins_type); + ECHO_WITH_ARGS("{}", switchkins_type); } diff --git a/src/emc/sai/saicanon.hh b/src/emc/sai/saicanon.hh index f5946ef5039..56981652405 100644 --- a/src/emc/sai/saicanon.hh +++ b/src/emc/sai/saicanon.hh @@ -12,7 +12,7 @@ class InterpBase; extern StandaloneInterpInternals _sai; extern InterpBase *pinterp; extern FILE *_outfile; -extern char _parameter_file_name[PARAMETER_FILE_NAME_LENGTH]; +extern std::string _parameter_file_name; struct StandaloneInterpInternals { diff --git a/src/emc/task/emccanon.cc b/src/emc/task/emccanon.cc index 5ad736c59e8..ae3a97c5aab 100644 --- a/src/emc/task/emccanon.cc +++ b/src/emc/task/emccanon.cc @@ -53,11 +53,15 @@ #include #include #include // strncpy() +#include +#include +#include #include // isspace() #include "nml_intf/emc.hh" // EMC NML #include "nml_intf/emc_nml.hh" #include // SWITCHKINS_MAX_TYPES #include "nml_intf/canon.hh" +#include "nml_intf/nurbs_math.hh" #include "nml_intf/canon_position.hh" // data type for a machine position #include "nml_intf/interpl_nml.hh" // interp_list #include "nml_intf/emcglb.h" // TRAJ_MAX_VELOCITY @@ -3145,94 +3149,55 @@ void CLAMP_AXIS(CANON_AXIS /*axis*/) /*! \todo FIXME-- unimplemented */ } -/* - setString and addString initializes or adds src to dst, never exceeding - dst's maxlen chars. -*/ - -static char *setString(char *dst, const char *src, int maxlen) -{ - dst[0] = 0; - strncat(dst, src, maxlen - 1); - dst[maxlen - 1] = 0; - return dst; -} - -static char *addString(char *dst, const char *src, int maxlen) -{ - int dstlen = strlen(dst); - int srclen = strlen(src); - int actlen; - - if (srclen >= maxlen - dstlen) { - actlen = maxlen - dstlen - 1; - dst[maxlen - 1] = 0; - } else { - actlen = srclen; - } - - strncat(dst, src, actlen); - - return dst; -} - /* The probe file is opened with a hot-comment (PROBEOPEN ), and the results of each probed point are written to that file. The file is closed with a (PROBECLOSE) comment. */ -static FILE *probefile = NULL; +static std::ofstream probefile; -void COMMENT(const char *comment) +void COMMENT(std::string_view comment) { // nothing need be done here, but you can play tricks with hot comments - char msg[LINELEN]; - char probefilename[LINELEN]; - const char *ptr; - // set RPY orientation for subsequent moves - if (!strncmp(comment, "RPY", strlen("RPY"))) { - PM_RPY rpy; + if (comment.starts_with("RPY")) { // it's RPY

- if (3 != - sscanf(comment, "%*s %lf %lf %lf", &rpy.r, &rpy.p, &rpy.y)) { - // print current orientation - printf("rpy = %f %f %f, quat = %f %f %f %f\n", - rpy.r, rpy.p, rpy.y, quat.s, quat.x, quat.y, quat.z); - } else { - // set and print orientation + std::istringstream args{std::string(comment)}; + std::string word; + double r, p, y; + PM_RPY rpy; + if (args >> word >> r >> p >> y) { + // set the new orientation + rpy = PM_RPY(r, p, y); quat = rpy; - printf("rpy = %f %f %f, quat = %f %f %f %f\n", - rpy.r, rpy.p, rpy.y, quat.s, quat.x, quat.y, quat.z); + } else { + // only show the current one + rpy = quat; } + printf("rpy = %f %f %f, quat = %f %f %f %f\n", + rpy.r, rpy.p, rpy.y, quat.s, quat.x, quat.y, quat.z); return; } // open probe output file - if (!strncmp(comment, "PROBEOPEN", strlen("PROBEOPEN"))) { - // position ptr to first char after PROBEOPEN - ptr = &comment[strlen("PROBEOPEN")]; - // and step over white space to name, or NULL - while (isspace(*ptr)) { - ptr++; + if (comment.starts_with("PROBEOPEN")) { + // the name follows PROBEOPEN after white space + std::string_view name = comment.substr(strlen("PROBEOPEN")); + while (!name.empty() && isspace((unsigned char)name.front())) { + name.remove_prefix(1); } - setString(probefilename, ptr, LINELEN); - if (NULL == (probefile = fopen(probefilename, "wt"))) { + probefile.close(); + probefile.open(std::string(name)); + if (!probefile) { // pop up a warning message - setString(msg, "can't open probe file ", LINELEN); - addString(msg, probefilename, LINELEN); - MESSAGE(msg); - probefile = NULL; + MESSAGE("can't open probe file " + std::string(name)); } return; } // close probe output file - if (!strncmp(comment, "PROBECLOSE", strlen("PROBECLOSE"))) { - if (probefile != NULL) { - fclose(probefile); - probefile = NULL; - } + if (comment.starts_with("PROBECLOSE")) { + probefile.close(); return; } @@ -3342,41 +3307,43 @@ void FLOOD_ON() SIMPLE_COMMAND_(); } -void MESSAGE(char *s) +void MESSAGE(std::string_view s) { auto operator_display_msg = std::make_unique(); flush_segments(); - strncpy(operator_display_msg->display, s, LINELEN-1); - operator_display_msg->display[LINELEN - 1] = 0; + const size_t n = std::min(s.size(), size_t(LINELEN - 1)); + s.copy(operator_display_msg->display, n); + operator_display_msg->display[n] = 0; interp_list.append(std::move(operator_display_msg)); } -static FILE *logfile = NULL; +static std::ofstream logfile; -void LOG(char *s) { +void LOG(std::string_view s) { flush_segments(); - if(logfile) { fprintf(logfile, "%s\n", s); fflush(logfile); } - fprintf(stderr, "LOG(%s)\n", s); + if(logfile.is_open()) logfile << s << std::endl; + std::cerr << "LOG(" << s << ")\n"; +} +static void log_open(std::string_view name, std::ios::openmode mode, const char *what) { + logfile.close(); + logfile.clear(); + logfile.open(std::string(name), mode); + std::cerr << what << "(" << name << ") -> " << (logfile ? "open" : "failed") << "\n"; } -void LOGOPEN(char *name) { - if(logfile) fclose(logfile); - logfile = fopen(name, "wt"); - fprintf(stderr, "LOGOPEN(%s) -> %p\n", name, logfile); +void LOGOPEN(std::string_view name) { + log_open(name, std::ios::out | std::ios::trunc, "LOGOPEN"); } -void LOGAPPEND(char *name) { - if(logfile) fclose(logfile); - logfile = fopen(name, "at"); - fprintf(stderr, "LOGAPPEND(%s) -> %p\n", name, logfile); +void LOGAPPEND(std::string_view name) { + log_open(name, std::ios::out | std::ios::app, "LOGAPPEND"); } void LOGCLOSE() { - if(logfile) fclose(logfile); - logfile = NULL; + logfile.close(); fprintf(stderr, "LOGCLOSE()\n"); } @@ -3451,49 +3418,19 @@ void PROGRAM_END() SIMPLE_COMMAND_(); } -double GET_EXTERNAL_TOOL_LENGTH_XOFFSET() -{ - return TO_PROG_LEN(canon.toolOffset.tran.x); -} - -double GET_EXTERNAL_TOOL_LENGTH_YOFFSET() -{ - return TO_PROG_LEN(canon.toolOffset.tran.y); -} - -double GET_EXTERNAL_TOOL_LENGTH_ZOFFSET() -{ - return TO_PROG_LEN(canon.toolOffset.tran.z); -} - -double GET_EXTERNAL_TOOL_LENGTH_AOFFSET() -{ - return TO_PROG_AX(AXIS_A, canon.toolOffset.a); -} - -double GET_EXTERNAL_TOOL_LENGTH_BOFFSET() -{ - return TO_PROG_AX(AXIS_B, canon.toolOffset.b); -} - -double GET_EXTERNAL_TOOL_LENGTH_COFFSET() -{ - return TO_PROG_AX(AXIS_C, canon.toolOffset.c); -} - -double GET_EXTERNAL_TOOL_LENGTH_UOFFSET() +EmcPose GET_EXTERNAL_TOOL_LENGTH_OFFSET() { - return TO_PROG_AX(AXIS_U, canon.toolOffset.u); -} - -double GET_EXTERNAL_TOOL_LENGTH_VOFFSET() -{ - return TO_PROG_AX(AXIS_V, canon.toolOffset.v); -} - -double GET_EXTERNAL_TOOL_LENGTH_WOFFSET() -{ - return TO_PROG_AX(AXIS_W, canon.toolOffset.w); + EmcPose off; + off.tran.x = TO_PROG_LEN(canon.toolOffset.tran.x); + off.tran.y = TO_PROG_LEN(canon.toolOffset.tran.y); + off.tran.z = TO_PROG_LEN(canon.toolOffset.tran.z); + off.a = TO_PROG_AX(AXIS_A, canon.toolOffset.a); + off.b = TO_PROG_AX(AXIS_B, canon.toolOffset.b); + off.c = TO_PROG_AX(AXIS_C, canon.toolOffset.c); + off.u = TO_PROG_AX(AXIS_U, canon.toolOffset.u); + off.v = TO_PROG_AX(AXIS_V, canon.toolOffset.v); + off.w = TO_PROG_AX(AXIS_W, canon.toolOffset.w); + return off; } /* @@ -3579,20 +3516,15 @@ void INIT_CANON() } /* Sends error message */ -void CANON_ERROR(const char *fmt, ...) +void CANON_ERROR(std::string_view message) { - va_list ap; auto operator_error_msg = std::make_unique(); flush_segments(); - if (fmt != NULL) { - va_start(ap, fmt); - vsnprintf(operator_error_msg->error, sizeof(operator_error_msg->error), fmt, ap); - va_end(ap); - } else { - operator_error_msg->error[0] = 0; - } + const size_t n = std::min(message.size(), sizeof(operator_error_msg->error) - 1); + message.copy(operator_error_msg->error, n); + operator_error_msg->error[n] = 0; interp_list.append(std::move(operator_error_msg)); } @@ -3687,9 +3619,9 @@ CANON_POSITION GET_EXTERNAL_PROBE_POSITION() position = unoffset_and_unrotate_pos(pos); to_prog(position); - if (probefile != NULL) { + if (probefile.is_open()) { if (last_probed_position != position) { - fprintf(probefile, "%f %f %f %f %f %f %f %f %f\n", + probefile << fmt::format("{:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f} {:f}\n", position.x, position.y, position.z, position.a, position.b, position.c, position.u, position.v, position.w); @@ -3831,154 +3763,16 @@ CANON_DIRECTION GET_EXTERNAL_SPINDLE(int spindle) return CANON_COUNTERCLOCKWISE; } -static char _parameter_file_name[LINELEN]; +static std::string _parameter_file_name; -void SET_PARAMETER_FILE_NAME(const char *name) +void SET_PARAMETER_FILE_NAME(std::string_view name) { - strncpy(_parameter_file_name, name, PARAMETER_FILE_NAME_LENGTH); -} - -void GET_EXTERNAL_PARAMETER_FILE_NAME(char *file_name, /* string: to copy - file name into */ - int max_size) -{ /* maximum number of characters to copy */ - // Paranoid checks - if (NULL == file_name) - return; - - if (max_size < 0) - return; - - if (strlen(_parameter_file_name) < ((size_t) max_size)) - strcpy(file_name, _parameter_file_name); - else - file_name[0] = 0; -} - -double GET_EXTERNAL_POSITION_X(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_POSITION(); - return position.x; -} - -double GET_EXTERNAL_POSITION_Y(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_POSITION(); - return position.y; + _parameter_file_name = name; } -double GET_EXTERNAL_POSITION_Z(void) +std::string GET_EXTERNAL_PARAMETER_FILE_NAME() { - CANON_POSITION position; - position = GET_EXTERNAL_POSITION(); - return position.z; -} - -double GET_EXTERNAL_POSITION_A(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_POSITION(); - return position.a; -} - -double GET_EXTERNAL_POSITION_B(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_POSITION(); - return position.b; -} - -double GET_EXTERNAL_POSITION_C(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_POSITION(); - return position.c; -} - -double GET_EXTERNAL_POSITION_U(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_POSITION(); - return position.u; -} - -double GET_EXTERNAL_POSITION_V(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_POSITION(); - return position.v; -} - -double GET_EXTERNAL_POSITION_W(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_POSITION(); - return position.w; -} - -double GET_EXTERNAL_PROBE_POSITION_X(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_PROBE_POSITION(); - return position.x; -} - -double GET_EXTERNAL_PROBE_POSITION_Y(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_PROBE_POSITION(); - return position.y; -} - -double GET_EXTERNAL_PROBE_POSITION_Z(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_PROBE_POSITION(); - return position.z; -} - -double GET_EXTERNAL_PROBE_POSITION_A(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_PROBE_POSITION(); - return position.a; -} - -double GET_EXTERNAL_PROBE_POSITION_B(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_PROBE_POSITION(); - return position.b; -} - -double GET_EXTERNAL_PROBE_POSITION_C(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_PROBE_POSITION(); - return position.c; -} - -double GET_EXTERNAL_PROBE_POSITION_U(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_PROBE_POSITION(); - return position.u; -} - -double GET_EXTERNAL_PROBE_POSITION_V(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_PROBE_POSITION(); - return position.v; -} - -double GET_EXTERNAL_PROBE_POSITION_W(void) -{ - CANON_POSITION position; - position = GET_EXTERNAL_PROBE_POSITION(); - return position.w; + return _parameter_file_name; } CANON_MOTION_MODE GET_EXTERNAL_MOTION_CONTROL_MODE() diff --git a/src/emc/task/emctask.cc b/src/emc/task/emctask.cc index c9772a266db..2b4490aca48 100644 --- a/src/emc/task/emctask.cc +++ b/src/emc/task/emctask.cc @@ -61,39 +61,35 @@ InterpBase *pinterp=NULL; setup_pointer _is = NULL; // helper for gdb hardware watchpoints FIXME // Print error messages thrown by interpreter -static char interp_error_text_buf[LINELEN]; -static char interp_stack_buf[LINELEN]; static void print_interp_error(int retval) { int index = 0; if (retval == 0) { - return; + return; } if (NULL != emcStatus) { - emcStatus->task.interpreter_errcode = retval; + emcStatus->task.interpreter_errcode = retval; } - interp_error_text_buf[0] = 0; - interp.error_text(retval, interp_error_text_buf, LINELEN); - if (0 != interp_error_text_buf[0]) { - log_error("interp_error: {}\n", interp_error_text_buf); + const std::string error_text = interp.error_text(retval); + if (!error_text.empty()) { + log_error("interp_error: {}\n", error_text); } - emcOperatorError("%s", interp_error_text_buf); + emcOperatorError("%s", error_text.c_str()); index = 0; if (emc_debug & EMC_DEBUG_INTERP) { - log_info("Interpreter stack: \t"); - while (index < 5) { - interp_stack_buf[0] = 0; - interp.stack_name(index, interp_stack_buf, LINELEN); - if (0 == interp_stack_buf[0]) { - break; - } - log_info(" - {} ", interp_stack_buf); - index++; - } - log_info("\n"); + log_info("Interpreter stack: \t"); + while (index < 5) { + const std::string name = interp.stack_name(index); + if (name.empty()) { + break; + } + log_info(" - {} ", name); + index++; + } + log_info("\n"); } } @@ -664,9 +660,10 @@ int emcTaskPlanLevel() int emcTaskPlanCommand(char *cmd) { - char buf[LINELEN]; - - strcpy(cmd, interp.command(buf, LINELEN)); + // cmd is the LINELEN array emcStatus->task.command + const std::string command = interp.command(); + strncpy(cmd, command.c_str(), LINELEN - 1); + cmd[LINELEN - 1] = 0; log_debug(EMC_DEBUG_INTERP, "emcTaskPlanCommand({}) called. (line_number={})\n", cmd, emcStatus->task.readLine); @@ -695,8 +692,7 @@ int emcTaskUpdate(EMC_TASK_STAT * stat) // currentLine set in main // readLine set in main - char buf[LINELEN]; - rtapi_strxcpy(stat->file, interp.file(buf, LINELEN)); + rtapi_strxcpy(stat->file, interp.file().c_str()); // Report the subroutine call stack of the move motion is executing, not the // one the interpreter has read ahead to -- those are decoupled by up to diff --git a/tests/interp/compile/use-rs274.cc b/tests/interp/compile/use-rs274.cc index 45e75382484..91e63e533f1 100644 --- a/tests/interp/compile/use-rs274.cc +++ b/tests/interp/compile/use-rs274.cc @@ -18,6 +18,7 @@ #include "linuxcnc.h" // LINELEN #include "rs274ngc.hh" #include "canon.hh" +#include "nurbs_math.hh" static void read_execute(InterpBase *b, const char *line) { fprintf(stderr, "> %s\n", line); @@ -151,7 +152,7 @@ void SELECT_TOOL(int tool) {} void CHANGE_TOOL_NUMBER(int number) {} void RELOAD_TOOLDATA() {} void CLAMP_AXIS(CANON_AXIS axis) {} -void COMMENT(const char *s) { puts(s); } +void COMMENT(std::string_view s) { printf("%.*s\n", (int)s.size(), s.data()); } void DISABLE_ADAPTIVE_FEED() {} void ENABLE_ADAPTIVE_FEED() {} void DISABLE_FEED_OVERRIDE() {} @@ -162,10 +163,10 @@ void DISABLE_FEED_HOLD() {} void ENABLE_FEED_HOLD() {} void FLOOD_OFF() {} void FLOOD_ON() {} -void MESSAGE(char *s) {} -void LOG(char *s) {} -void LOGOPEN(char *s) {} -void LOGAPPEND(char *s) {} +void MESSAGE(std::string_view s) {} +void LOG(std::string_view s) {} +void LOGOPEN(std::string_view s) {} +void LOGAPPEND(std::string_view s) {} void LOGCLOSE() {} void MIST_OFF() {} void MIST_ON() {} @@ -205,44 +206,18 @@ int GET_EXTERNAL_MIST() { return 0; } CANON_MOTION_MODE GET_EXTERNAL_MOTION_CONTROL_MODE() { return CANON_EXACT_STOP; } double GET_EXTERNAL_MOTION_CONTROL_TOLERANCE() { return 0.0; } -extern void SET_PARAMETER_FILE_NAME(const char *name) {} +void SET_PARAMETER_FILE_NAME(std::string_view name) {} double GET_EXTERNAL_MOTION_CONTROL_NAIVECAM_TOLERANCE() { return 0.0; } -void GET_EXTERNAL_PARAMETER_FILE_NAME(char *filename, int max_size) { - snprintf(filename, max_size, "%s", "rs274ngc.var"); -} +std::string GET_EXTERNAL_PARAMETER_FILE_NAME() { return "rs274ngc.var"; } CANON_PLANE GET_EXTERNAL_PLANE() { return CANON_PLANE::XY; } -double GET_EXTERNAL_POSITION_A() { return 0.0; } -double GET_EXTERNAL_POSITION_B() { return 0.0; } -double GET_EXTERNAL_POSITION_C() { return 0.0; } -double GET_EXTERNAL_POSITION_X() { return 0.0; } -double GET_EXTERNAL_POSITION_Y() { return 0.0; } -double GET_EXTERNAL_POSITION_Z() { return 0.0; } -double GET_EXTERNAL_POSITION_U() { return 0.0; } -double GET_EXTERNAL_POSITION_V() { return 0.0; } -double GET_EXTERNAL_POSITION_W() { return 0.0; } -double GET_EXTERNAL_PROBE_POSITION_A() { return 0.0; } -double GET_EXTERNAL_PROBE_POSITION_B() { return 0.0; } -double GET_EXTERNAL_PROBE_POSITION_C() { return 0.0; } -double GET_EXTERNAL_PROBE_POSITION_X() { return 0.0; } -double GET_EXTERNAL_PROBE_POSITION_Y() { return 0.0; } -double GET_EXTERNAL_PROBE_POSITION_Z() { return 0.0; } -double GET_EXTERNAL_PROBE_POSITION_U() { return 0.0; } -double GET_EXTERNAL_PROBE_POSITION_V() { return 0.0; } -double GET_EXTERNAL_PROBE_POSITION_W() { return 0.0; } +CANON_POSITION GET_EXTERNAL_POSITION() { return CANON_POSITION(); } +CANON_POSITION GET_EXTERNAL_PROBE_POSITION() { return CANON_POSITION(); } +EmcPose GET_EXTERNAL_TOOL_LENGTH_OFFSET() { return EmcPose(); } double GET_EXTERNAL_PROBE_VALUE() { return 0.0; } int GET_EXTERNAL_PROBE_TRIPPED_VALUE() { return 0; } int GET_EXTERNAL_QUEUE_EMPTY() { return 0; } double GET_EXTERNAL_SPEED(int spindle) { return 0.0; } CANON_DIRECTION GET_EXTERNAL_SPINDLE(int spindle) { return CANON_STOPPED; } -double GET_EXTERNAL_TOOL_LENGTH_XOFFSET() { return 0.0; } -double GET_EXTERNAL_TOOL_LENGTH_YOFFSET() { return 0.0; } -double GET_EXTERNAL_TOOL_LENGTH_ZOFFSET() { return 0.0; } -double GET_EXTERNAL_TOOL_LENGTH_AOFFSET() { return 0.0; } -double GET_EXTERNAL_TOOL_LENGTH_BOFFSET() { return 0.0; } -double GET_EXTERNAL_TOOL_LENGTH_COFFSET() { return 0.0; } -double GET_EXTERNAL_TOOL_LENGTH_UOFFSET() { return 0.0; } -double GET_EXTERNAL_TOOL_LENGTH_VOFFSET() { return 0.0; } -double GET_EXTERNAL_TOOL_LENGTH_WOFFSET() { return 0.0; } int GET_EXTERNAL_TOOL_SLOT() { return 0; } int GET_EXTERNAL_SELECTED_TOOL_SLOT() { return 0; } CANON_TOOL_TABLE GET_EXTERNAL_TOOL_TABLE(int pocket) { CANON_TOOL_TABLE retval; memset(&retval, 0, sizeof(retval)); return retval; } @@ -258,7 +233,7 @@ double GET_EXTERNAL_ANALOG_INPUT(int index, double def) { return 0.0; } int GET_EXTERNAL_AXIS_MASK() { return 7; } void FINISH(void) {} void ON_RESET(void) {} -void CANON_ERROR(const char *fmt, ...) {} +void CANON_ERROR(std::string_view message) {} void UPDATE_TAG(const StateTag& tag) {} USER_DEFINED_FUNCTION_TYPE USER_DEFINED_FUNCTION[USER_DEFINED_FUNCTION_NUM]; diff --git a/tests/remap/introspect/test.ini b/tests/remap/introspect/test.ini index 2f621f0f8e5..efb14f93c38 100644 --- a/tests/remap/introspect/test.ini +++ b/tests/remap/introspect/test.ini @@ -5,7 +5,7 @@ DEBUG=0 SUBROUTINE_PATH = . LOG_LEVEL=0 INI_VARS = 1 -REMAP= M123 ngc=foo modalgroup=5 argspec=Pq +REMAP= M423 ngc=foo modalgroup=5 argspec=Pq [PYTHON] PATH_PREPEND=.