GCC Code Coverage Report
Directory: emc/rs274ngc/ Exec Total Coverage
File: emc/rs274ngc/interp_internal.hh Lines: 9 11 81.8 %
Date: 2016-10-27 Branches: 3 6 50.0 %

Line Exec Source
1
/********************************************************************
2
* Description: interp_internal.hh
3
*
4
*   Derived from a work by Thomas Kramer
5
*
6
* Author:
7
* License: GPL Version 2
8
* System: Linux
9
*
10
* Copyright (c) 2004 All rights reserved.
11
*
12
********************************************************************/
13
#ifndef INTERP_INTERNAL_HH
14
#define INTERP_INTERNAL_HH
15
16
#include <algorithm>
17
#include "config.h"
18
#include <limits.h>
19
#include <stdio.h>
20
#include <set>
21
#include <map>
22
#include <bitset>
23
#include "canon.hh"
24
#include "emcpos.h"
25
#include "libintl.h"
26
#include <boost/python/object_fwd.hpp>
27
#include <cmath>
28
29
30
#define _(s) gettext(s)
31
32
/**********************/
33
/*   COMPILER MACROS  */
34
/**********************/
35
36
template<class T>
37
T R2D(T r) { return r * (180. / M_PI); }
38
template<class T>
39
351
T D2R(T r) { return r * (M_PI / 180.); }
40
template<class T>
41
78
T SQ(T a) { return a*a; }
42
43
template<class T>
44
97
inline int round_to_int(T x) {
45
97
    return (int)std::nearbyint(x);
46
}
47
48
/* how far above hole bottom for rapid return, in inches */
49
#define G83_RAPID_DELTA 0.010
50
51
/* nested remap: a remapped code is found in the body of a subroutine
52
 * which is executing on behalf of another remapped code
53
 * example: a user G code command executes a tool change
54
 */
55
#define MAX_NESTED_REMAPS 10
56
57
// English - Metric conversion (long number keeps error buildup down)
58
#define MM_PER_INCH 25.4
59
//#define INCH_PER_MM 0.039370078740157477
60
61
/* numerical constants */
62
63
/*****************************************************************************
64
The default tolerance (if none tighter is specified in the ini file) should be:
65
2 * 0.001 * sqrt(2) for inch, and 2 * 0.01 * sqrt(2) for mm.
66
This would mean that any valid arc where the endpoints and/or centerpoint
67
got rounded or truncated to 0.001 inch or 0.01 mm precision would be accepted.
68
69
Tighter tolerance down to a minimum of 1 micron +- also accepted.
70
******************************************************************************/
71
72
#define CENTER_ARC_RADIUS_TOLERANCE_INCH (2 * 0.001 * M_SQRT2)
73
#define MIN_CENTER_ARC_RADIUS_TOLERANCE_INCH 0.00004
74
75
// Note: started from original tolerance and divided by 10 here (since that was originally done inside the interpreter)
76
#define RADIUS_TOLERANCE_INCH 0.00005
77
78
/* Equivalent metric constants */
79
80
#define CENTER_ARC_RADIUS_TOLERANCE_MM (2 * 0.01 * M_SQRT2)
81
#define MIN_CENTER_ARC_RADIUS_TOLERANCE_MM 0.001
82
83
#define RADIUS_TOLERANCE_MM (RADIUS_TOLERANCE_INCH * MM_PER_INCH)
84
85
// Modest relative error
86
#define SPIRAL_RELATIVE_TOLERANCE 0.001
87
88
/* angle threshold for concavity for cutter compensation, in radians */
89
#define TOLERANCE_CONCAVE_CORNER 0.05
90
#define TOLERANCE_EQUAL 0.0001 /* two numbers compare EQ if the
91
				  difference is less than this */
92
93
static inline bool equal(double a, double b)
94
{
95
314
    return (fabs(a - b) < TOLERANCE_EQUAL);
96
}
97
98
99
#define TINY 1e-12              /* for arc_data_r */
100
101
// max number of m codes on one line
102
#define MAX_EMS  4
103
104
// feed_mode
105
enum feed_mode { UNITS_PER_MINUTE=0, INVERSE_TIME=1, UNITS_PER_REVOLUTION=2 };
106
107
// cutter radius compensation mode, 0 or false means none
108
// not using CANON_SIDE since interpreter handles cutter radius comp
109
#define RIGHT 1
110
#define LEFT 2
111
112
// spindle control modes
113
enum SPINDLE_MODE { CONSTANT_RPM, CONSTANT_SURFACE };
114
115
// unary operations
116
// These are not enums because the "&" operator is used in
117
// reading the operation names and is illegal with an enum
118
119
#define ABS 1
120
#define ACOS 2
121
#define ASIN 3
122
#define ATAN 4
123
#define COS 5
124
#define EXP 6
125
#define FIX 7
126
#define FUP 8
127
#define LN 9
128
#define ROUND 10
129
#define SIN 11
130
#define SQRT 12
131
#define TAN 13
132
#define EXISTS 14
133
134
135
// binary operations
136
#define NO_OPERATION 0
137
#define DIVIDED_BY 1
138
#define MODULO 2
139
#define POWER 3
140
#define TIMES 4
141
#define AND2 5
142
#define EXCLUSIVE_OR 6
143
#define MINUS 7
144
#define NON_EXCLUSIVE_OR 8
145
#define PLUS 9
146
#define RIGHT_BRACKET 10
147
148
/* relational operators (are binary operators)*/
149
#define LT 11
150
#define EQ 12
151
#define NE 13
152
#define LE 14
153
#define GE 15
154
#define GT 16
155
#define RELATIONAL_OP_FIRST 11
156
#define RELATIONAL_OP_LAST  16
157
158
// O code
159
#define O_none      0
160
#define O_sub       1
161
#define O_endsub    2
162
#define O_call      3
163
#define O_do        4
164
#define O_while     5
165
#define O_if        6
166
#define O_elseif    7
167
#define O_else      8
168
#define O_endif     9
169
#define O_break    10
170
#define O_continue 11
171
#define O_endwhile 12
172
#define O_return   13
173
#define O_repeat   14
174
#define O_endrepeat 15
175
176
// G Codes are symbolic to be dialect-independent in source code
177
#define G_0      0
178
#define G_1     10
179
#define G_2     20
180
#define G_3     30
181
#define G_4     40
182
#define G_5     50
183
#define G_5_1   51
184
#define G_5_2   52
185
#define G_5_3   53
186
#define G_7     70
187
#define G_8     80
188
#define G_10   100
189
#define G_17   170
190
#define G_17_1 171
191
#define G_18   180
192
#define G_18_1 181
193
#define G_19   190
194
#define G_19_1 191
195
#define G_20   200
196
#define G_21   210
197
#define G_28   280
198
#define G_28_1 281
199
#define G_30   300
200
#define G_30_1 301
201
#define G_33   330
202
#define G_33_1 331
203
#define G_38_2 382
204
#define G_38_3 383
205
#define G_38_4 384
206
#define G_38_5 385
207
#define G_40   400
208
#define G_41   410
209
#define G_41_1 411
210
#define G_42   420
211
#define G_42_1 421
212
#define G_43   430
213
#define G_43_1 431
214
#define G_43_2 432
215
#define G_49   490
216
#define G_50   500
217
#define G_51   510
218
#define G_52   520
219
#define G_53   530
220
#define G_54   540
221
#define G_55   550
222
#define G_56   560
223
#define G_57   570
224
#define G_58   580
225
#define G_59   590
226
#define G_59_1 591
227
#define G_59_2 592
228
#define G_59_3 593
229
#define G_61   610
230
#define G_61_1 611
231
#define G_64   640
232
#define G_73   730
233
#define G_76   760
234
#define G_80   800
235
#define G_81   810
236
#define G_82   820
237
#define G_83   830
238
#define G_84   840
239
#define G_85   850
240
#define G_86   860
241
#define G_87   870
242
#define G_88   880
243
#define G_89   890
244
#define G_90   900
245
#define G_90_1 901
246
#define G_91   910
247
#define G_91_1 911
248
#define G_92   920
249
#define G_92_1 921
250
#define G_92_2 922
251
#define G_92_3 923
252
#define G_93   930
253
#define G_94   940
254
#define G_95   950
255
#define G_96   960
256
#define G_97   970
257
#define G_98   980
258
#define G_99   990
259
260
// name of parameter file for saving/restoring interpreter variables
261
#define RS274NGC_PARAMETER_FILE_NAME_DEFAULT "rs274ngc.var"
262
#define RS274NGC_PARAMETER_FILE_BACKUP_SUFFIX ".bak"
263
264
// number of parameters in parameter table
265
266
// leave some room above 5428 for further introspection
267
// 5599 = control DEBUG, output, 0=no output; default=1.0
268
// 5600-5601 = toolchanger codes
269
#define RS274NGC_MAX_PARAMETERS 5602
270
271
// Subroutine parameters
272
#define INTERP_SUB_PARAMS 30
273
#define INTERP_SUB_ROUTINE_LEVELS 10
274
#define INTERP_FIRST_SUBROUTINE_PARAM 1
275
276
// max number of local variables saved (?)
277
#define MAX_NAMED_PARAMETERS 50
278
279
/**********************/
280
/*      TYPEDEFS      */
281
/**********************/
282
283
/* distance_mode */
284
typedef enum
285
{ MODE_ABSOLUTE, MODE_INCREMENTAL }
286
DISTANCE_MODE;
287
288
/* retract_mode for cycles */
289
typedef enum
290
{ R_PLANE, OLD_Z }
291
RETRACT_MODE;
292
293
// string table - to get rid of strdup/free
294
const char *strstore(const char *s);
295
296
297
// Block execution phases in execution order
298
// very carefully check code for sequencing when
299
// adding phases!
300
301
// used to record execution trail in breadcrumbs
302
enum phases  {
303
    NO_REMAPPED_STEPS,
304
    STEP_COMMENT,
305
    STEP_SPINDLE_MODE,
306
    STEP_FEED_MODE,
307
    STEP_SET_FEED_RATE,
308
    STEP_SET_SPINDLE_SPEED,
309
    STEP_PREPARE,
310
    STEP_M_5,
311
    STEP_M_6,
312
    STEP_RETAIN_G43,
313
    STEP_M_7,
314
    STEP_M_8,
315
    STEP_M_9,
316
    STEP_M_10,
317
    STEP_DWELL,
318
    STEP_SET_PLANE,
319
    STEP_LENGTH_UNITS,
320
    STEP_LATHE_DIAMETER_MODE,
321
    STEP_CUTTER_COMP,
322
    STEP_TOOL_LENGTH_OFFSET,
323
    STEP_COORD_SYSTEM,
324
    STEP_CONTROL_MODE,
325
    STEP_DISTANCE_MODE,
326
    STEP_IJK_DISTANCE_MODE,
327
    STEP_RETRACT_MODE,
328
    STEP_MODAL_0,
329
    STEP_MOTION,
330
    STEP_MGROUP4,
331
    MAX_STEPS
332
};
333
334
335
typedef struct remap_struct remap;
336
typedef remap *remap_pointer;
337
338
// the remap configuration descriptor
339
typedef struct remap_struct {
340
    const char *name;
341
    const char *argspec;
342
    // if no modalgroup= was given in the REMAP= line, use these defaults
343
#define MCODE_DEFAULT_MODAL_GROUP 10
344
#define GCODE_DEFAULT_MODAL_GROUP 1
345
    int modal_group;
346
    int motion_code; // only for g's - to identify cycles
347
    const char *prolog_func; // Py function or null
348
    const char *remap_py;    // Py function maybe  null, OR
349
    const char *remap_ngc;   // NGC file, maybe  null
350
    const char *epilog_func; // Py function or null
351
} remap;
352
353
354
// case insensitive compare for std::map etc
355
struct nocase_cmp
356
{
357
106139
    bool operator()(const char* s1, const char* s2) const
358
    {
359
106139
        return strcasecmp(s1, s2) < 0;
360
    }
361
};
362
363
typedef std::map<const char *,remap,nocase_cmp> remap_map;
364
typedef remap_map::iterator remap_iterator;
365
366
typedef std::map<int, remap_pointer> int_remap_map;
367
typedef int_remap_map::iterator int_remap_iterator;
368
369
#define REMAP_FUNC(r) (r->remap_ngc ? r->remap_ngc: \
370
		       (r->remap_py ? r->remap_py : "BUG-no-remap-func"))
371
372
typedef struct block_struct
373
{
374
  block_struct ();
375
376
  bool a_flag;
377
  double a_number;
378
  bool b_flag;
379
  double b_number;
380
  bool c_flag;
381
  double c_number;
382
  char comment[256];
383
  double d_number_float;
384
  bool d_flag;
385
  bool e_flag;
386
  double e_number;
387
  bool f_flag;
388
  double f_number;
389
390
// Modal groups
391
// also indices into g_modes
392
// unused: 9,11
393
#define GM_MODAL_0        0
394
#define GM_MOTION         1
395
#define GM_SET_PLANE      2
396
#define GM_DISTANCE_MODE  3
397
#define GM_IJK_DISTANCE_MODE  4
398
#define GM_FEED_MODE      5
399
#define GM_LENGTH_UNITS   6
400
#define GM_CUTTER_COMP    7
401
#define GM_TOOL_LENGTH_OFFSET 8
402
#define GM_RETRACT_MODE   10
403
#define GM_COORD_SYSTEM   12
404
#define GM_CONTROL_MODE   13
405
#define GM_SPINDLE_MODE  14
406
#define GM_LATHE_DIAMETER_MODE  15
407
408
409
  int g_modes[16];
410
  bool h_flag;
411
  int h_number;
412
  bool i_flag;
413
  double i_number;
414
  bool j_flag;
415
  double j_number;
416
  bool k_flag;
417
  double k_number;
418
  int l_number;
419
  bool l_flag;
420
  int line_number;
421
  int saved_line_number;  // value of sequence_number when a remap was encountered
422
  int n_number;
423
  int motion_to_be;
424
  int m_count;
425
  int m_modes[11];
426
  int user_m;
427
  double p_number;
428
  bool p_flag;
429
  double q_number;
430
  bool q_flag;
431
  bool r_flag;
432
  double r_number;
433
  bool s_flag;
434
  double s_number;
435
  bool t_flag;
436
  int t_number;
437
  bool u_flag;
438
  double u_number;
439
  bool v_flag;
440
  double v_number;
441
  bool w_flag;
442
  double w_number;
443
  bool x_flag;
444
  double x_number;
445
  bool y_flag;
446
  double y_number;
447
  bool z_flag;
448
  double z_number;
449
450
  int radius_flag;
451
  double radius;
452
  int theta_flag;
453
  double theta;
454
455
  // control (o-word) stuff
456
  long     offset;   // start of line in file
457
  int      o_type;
458
  int      call_type; // oword-sub, python oword-sub, remap
459
  const char    *o_name;   // !!!KL be sure to free this
460
  double   params[INTERP_SUB_PARAMS];
461
  int param_cnt;
462
463
  // bitmap of phases already executed
464
  // we have some 31 or so different steps in a block. We must remember
465
  // which one is done when we reexecute a block after a remap.
466
  std::bitset<MAX_STEPS>  breadcrumbs;
467
468
#define TICKOFF(step) block->breadcrumbs[step] = 1
469
#define TODO(step) (block->breadcrumbs[step] == 0)
470
#define ONCE(step) (TODO(step) ? TICKOFF(step),1 : 0)
471
#define ONCE_M(step) (TODO(STEP_M_ ## step) ? TICKOFF(STEP_M_ ## step),1 : 0)
472
473
474
    // there might be several remapped items in a block, but at any point
475
    // in time there's only one excuting
476
    // conceptually blocks[1..n] are also the 'remap frames'
477
    remap_pointer executing_remap; // refers to config descriptor
478
    std::set<int> remappings; // all remappings in this block (enum phases)
479
    int phase; // current remap execution phase
480
481
    // the strategy to get the builtin behaviour of a code in a remap procedure is as follows:
482
    // if recursion is detected in find_remappings() (called by parse_line()), that *step*
483
    // (roughly the modal group) is NOT added to the set of remapped steps in a block (block->remappings)
484
    // in the convert_* procedures we test if the step is remapped with the macro below, and wether
485
    // it is the current code which is remapped (IS_USER_MCODE, IS_USER_GCODE etc). If both
486
    // are true, we execute the remap procedure; if not, use the builtin code.
487
#define STEP_REMAPPED_IN_BLOCK(bp, step) (bp->remappings.find(step) != bp->remappings.end())
488
489
    // true if in a remap procedure the code being remapped was
490
    // referenced, which caused execution of the builtin semantics
491
    // reason for recording the fact: this permits an epilog to do the
492
    // right thing depending on wether the builtin was used or not.
493
    bool builtin_used;
494
}
495
block;
496
497
// indicates which type of Python handler yielded, and needs reexecution
498
// post sync/read_inputs
499
enum call_states {
500
    CS_NORMAL,
501
    CS_REEXEC_PROLOG,
502
    CS_REEXEC_PYBODY,
503
    CS_REEXEC_EPILOG,
504
    CS_REEXEC_PYOSUB,
505
};
506
507
// detail for O_call; tags the frame
508
enum call_types {
509
    CT_NGC_OWORD_SUB,    // no restartable Python code involved
510
    CT_PYTHON_OWORD_SUB, // restartable Python code may be involved
511
    CT_REMAP,            // restartable Python code may be involved
512
};
513
514
515
enum retopts { RET_NONE, RET_DOUBLE, RET_INT, RET_YIELD, RET_STOPITERATION, RET_ERRORMSG };
516
517
typedef block *block_pointer;
518
519
// parameters will go to a std::map<const char *,paramter_value_pointer>
520
typedef struct parameter_value_struct {
521
    double value;
522
    unsigned attr;
523
} parameter_value;
524
525
typedef parameter_value *parameter_pointer;
526
typedef std::map<const char *, parameter_value, nocase_cmp> parameter_map;
527
typedef parameter_map::iterator parameter_map_iterator;
528
529
#define PA_READONLY	1
530
#define PA_GLOBAL	2
531
#define PA_UNSET	4
532
#define PA_USE_LOOKUP	8   // use lookup_named_param() to retrieve value
533
#define PA_FROM_INI	16  // a variable of the form '_[section]value' was retrieved from the ini file
534
#define PA_PYTHON	32  // call namedparams.<varname>() to retrieve the value
535
536
// optional 3rd arg to store_named_param()
537
// flag initialization of r/o parameter
538
#define OVERRIDE_READONLY 1
539
540
#define MAX_REMAPOPTS 20
541
// current implementation limits - legal modal groups
542
// for M and G codes
543
#define M_MODE_OK(m) ((m > 3) && (m < 11))
544
#define G_MODE_OK(m) (m == 1)
545
546
struct pycontext_impl;
547
struct pycontext {
548
    pycontext();
549
    pycontext(const struct pycontext &);
550
    pycontext &operator=(const struct pycontext &);
551
    ~pycontext();
552
    pycontext_impl *impl;
553
};
554
555
typedef struct context_struct {
556
    context_struct();
557
558
    long position;       // location (ftell) in file
559
    int sequence_number; // location (line number) in file
560
    const char *filename;      // name of file for this context
561
    const char *subName;       // name of the subroutine (oword)
562
    double saved_params[INTERP_SUB_PARAMS];
563
    parameter_map named_params;
564
    unsigned char context_status;		// see CONTEXT_ defines below
565
    int saved_g_codes[ACTIVE_G_CODES];  // array of active G codes
566
    int saved_m_codes[ACTIVE_M_CODES];  // array of active M codes
567
    double saved_settings[ACTIVE_SETTINGS];     // array of feed, speed, etc.
568
    int call_type; // enum call_types
569
    pycontext pystuff;
570
    // Python-related stuff
571
} context;
572
573
typedef context *context_pointer;
574
575
// context.context_status
576
#define CONTEXT_VALID   1 // this was stored by M7*
577
#define CONTEXT_RESTORE_ON_RETURN 2 // automatically execute M71 on sub return
578
#define REMAP_FRAME   4 // a remap call frame
579
580
typedef struct offset_struct {
581
  int type;
582
  const char *filename;  // the name of the file
583
  long offset;     // the offset in the file
584
  int sequence_number;
585
  int repeat_count;
586
} offset;
587
588
typedef std::map<const char *, offset, nocase_cmp> offset_map_type;
589
typedef std::map<const char *, offset, nocase_cmp>::iterator offset_map_iterator;
590
591
/*
592
593
The current_x, current_y, and current_z are the location of the tool
594
in the current coordinate system. current_x and current_y differ from
595
program_x and program_y when cutter radius compensation is on.
596
current_z is the position of the tool tip in program coordinates when
597
tool length compensation is using the actual tool length; it is the
598
position of the spindle when tool length is zero.
599
600
In a setup, the axis_offset values are set by g92 and the origin_offset
601
values are set by g54 - g59.3. The net origin offset uses both values
602
and is not represented here
603
604
*/
605
#define STACK_LEN 50
606
#define STACK_ENTRY_LEN 80
607
#define MAX_SUB_DIRS 10
608
609
struct setup
610
{
611
  setup();
612
  ~setup();
613
614
  double AA_axis_offset;        // A-axis g92 offset
615
  double AA_current;            // current A-axis position
616
  double AA_origin_offset;      // A-axis origin offset
617
  double BB_axis_offset;        // B-axis g92offset
618
  double BB_current;            // current B-axis position
619
  double BB_origin_offset;      // B-axis origin offset
620
  double CC_axis_offset;        // C-axis g92offset
621
  double CC_current;            // current C-axis position
622
  double CC_origin_offset;      // C-axis origin offset
623
624
  double u_axis_offset, u_current, u_origin_offset;
625
  double v_axis_offset, v_current, v_origin_offset;
626
  double w_axis_offset, w_current, w_origin_offset;
627
628
  int active_g_codes[ACTIVE_G_CODES];  // array of active G codes
629
  int active_m_codes[ACTIVE_M_CODES];  // array of active M codes
630
  double active_settings[ACTIVE_SETTINGS];     // array of feed, speed, etc.
631
  bool arc_not_allowed;       // we just exited cutter compensation, so we error if the next move isn't straight
632
  double axis_offset_x;         // X-axis g92 offset
633
  double axis_offset_y;         // Y-axis g92 offset
634
  double axis_offset_z;         // Z-axis g92 offset
635
  // block block1;                 // parsed next block
636
  // stack of controlling blocks for remap execution
637
  block blocks[MAX_NESTED_REMAPS];
638
  // index into blocks, points to currently controlling block
639
  int remap_level;
640
641
#define CONTROLLING_BLOCK(s) ((s).blocks[(s).remap_level])
642
#define EXECUTING_BLOCK(s)   ((s).blocks[0])
643
644
  char blocktext[LINELEN];   // linetext downcased, white space gone
645
  CANON_MOTION_MODE control_mode;       // exact path or cutting mode
646
  int current_pocket;             // carousel slot number of current tool
647
  double current_x;             // current X-axis position
648
  double current_y;             // current Y-axis position
649
  double current_z;             // current Z-axis position
650
  double cutter_comp_radius;    // current cutter compensation radius
651
  int cutter_comp_orientation;  // current cutter compensation tool orientation
652
  int cutter_comp_side;         // current cutter compensation side
653
  double cycle_cc;              // cc-value (normal) for canned cycles
654
  double cycle_i;               // i-value for canned cycles
655
  double cycle_j;               // j-value for canned cycles
656
  double cycle_k;               // k-value for canned cycles
657
  int cycle_l;                  // l-value for canned cycles
658
  double cycle_p;               // p-value (dwell) for canned cycles
659
  double cycle_q;               // q-value for canned cycles
660
  double cycle_r;               // r-value for canned cycles
661
  double cycle_il;              // "initial level" height when switching from non-cycle into cycle, for g98 retract
662
  int cycle_il_flag;            // il is currently valid because we're in a series of cycles
663
  DISTANCE_MODE distance_mode;  // absolute or incremental
664
  DISTANCE_MODE ijk_distance_mode;  // absolute or incremental for IJK in arcs
665
  int feed_mode;                // G_93 (inverse time) or G_94 units/min
666
  bool feed_override;         // whether feed override is enabled
667
  double feed_rate;             // feed rate in current units/min
668
  char filename[PATH_MAX];      // name of currently open NC code file
669
  FILE *file_pointer;           // file pointer for open NC code file
670
  bool flood;                 // whether flood coolant is on
671
  CANON_UNITS length_units;     // millimeters or inches
672
  double center_arc_radius_tolerance_inch; // modify with ini setting
673
  double center_arc_radius_tolerance_mm;   // modify with ini setting
674
  int line_length;              // length of line last read
675
  char linetext[LINELEN];       // text of most recent line read
676
  bool mist;                  // whether mist coolant is on
677
  int motion_mode;              // active G-code for motion
678
  int origin_index;             // active origin (1=G54 to 9=G59.3)
679
  double origin_offset_x;       // g5x offset x
680
  double origin_offset_y;       // g5x offset y
681
  double origin_offset_z;       // g5x offset z
682
  double rotation_xy;         // rotation of coordinate system around Z, in degrees
683
  double parameters[RS274NGC_MAX_PARAMETERS];   // system parameters
684
  int parameter_occurrence;     // parameter buffer index
685
  int parameter_numbers[MAX_NAMED_PARAMETERS];    // parameter number buffer
686
  double parameter_values[MAX_NAMED_PARAMETERS];  // parameter value buffer
687
  int named_parameter_occurrence;
688
  const char *named_parameters[MAX_NAMED_PARAMETERS];
689
  double named_parameter_values[MAX_NAMED_PARAMETERS];
690
  bool percent_flag;          // true means first line was percent sign
691
  CANON_PLANE plane;            // active plane, XY-, YZ-, or XZ-plane
692
  bool probe_flag;            // flag indicating probing done
693
  bool input_flag;            // flag indicating waiting for input done
694
  bool toolchange_flag;       // flag indicating we just had a tool change
695
  int input_index;		// channel queried
696
  bool input_digital;		// input queried was digital (false=analog)
697
  bool cutter_comp_firstmove; // this is the first comp move
698
  double program_x;             // program x, used when cutter comp on
699
  double program_y;             // program y, used when cutter comp on
700
  double program_z;             // program y, used when cutter comp on
701
  RETRACT_MODE retract_mode;    // for cycles, old_z or r_plane
702
  int random_toolchanger;       // tool changer swaps pockets, and pocket 0 is the spindle instead of "no tool"
703
  int selected_pocket;          // tool slot selected but not active
704
    int selected_tool;          // start switchover to pocket-agnostic interp
705
  int sequence_number;          // sequence number of line last read
706
  double speed;                 // current spindle speed in rpm or SxM
707
  SPINDLE_MODE spindle_mode;    // CONSTANT_RPM or CONSTANT_SURFACE
708
  CANON_SPEED_FEED_MODE speed_feed_mode;        // independent or synched
709
  bool speed_override;        // whether speed override is enabled
710
  CANON_DIRECTION spindle_turning;      // direction spindle is turning
711
  char stack[STACK_LEN][STACK_ENTRY_LEN];      // stack of calls for error reporting
712
  int stack_index;              // index into the stack
713
  EmcPose tool_offset;          // tool length offset
714
  int pockets_max;                 // number of pockets in carousel (including pocket 0, the spindle)
715
  CANON_TOOL_TABLE tool_table[CANON_POCKETS_MAX];      // index is pocket number
716
  double traverse_rate;         // rate for traverse motions
717
  double orient_offset;         // added to M19 R word, from [RS274NGC]ORIENT_OFFSET
718
719
  /* stuff for subroutines and control structures */
720
  int defining_sub;                  // true if in a subroutine defn
721
  const char *sub_name;                    // name of sub we are defining (free this)
722
  int doing_continue;                // true if doing a continue
723
  int doing_break;                   // true if doing a break
724
  int executed_if;                   // true if executed in current if
725
  const char *skipping_o;                  // o_name we are skipping for (or zero)
726
  const char *skipping_to_sub;             // o_name of sub skipping to (or zero)
727
  int skipping_start;                // start of skipping (sequence)
728
  double test_value;                 // value for "if", "while", "elseif"
729
  double return_value;               // optional return value for "return", "endsub"
730
  int value_returned;                // the last NGC procedure did/did not return a value
731
  int call_level;                    // current subroutine level
732
  context sub_context[INTERP_SUB_ROUTINE_LEVELS];
733
  int call_state;                  //  enum call_states - inidicate Py handler reexecution
734
  offset_map_type offset_map;      // store label x name, file, line
735
736
  bool adaptive_feed;              // adaptive feed is enabled
737
  bool feed_hold;                  // feed hold is enabled
738
  int loggingLevel;                  // 0 means logging is off
739
  int debugmask;                     // from ini  EMC/DEBUG
740
  char log_file[PATH_MAX];
741
  char program_prefix[PATH_MAX];            // program directory
742
  const char *subroutines[MAX_SUB_DIRS];  // subroutines directories
743
  int use_lazy_close;                // wait until next open before closing
744
                                     // the input file
745
  int lazy_closing;                  // close has been called
746
  char wizard_root[PATH_MAX];
747
  int tool_change_at_g30;
748
  int tool_change_quill_up;
749
  int tool_change_with_spindle_on;
750
  int a_axis_wrapped;
751
  int b_axis_wrapped;
752
  int c_axis_wrapped;
753
754
  int a_indexer_jnum;
755
  int b_indexer_jnum;
756
  int c_indexer_jnum;
757
758
  bool lathe_diameter_mode;       //Lathe diameter mode (g07/G08)
759
  bool mdi_interrupt;
760
  int feature_set;
761
762
  int disable_g92_persistence;
763
764
#define FEATURE(x) (_setup.feature_set & FEATURE_ ## x)
765
#define FEATURE_RETAIN_G43           0x00000001
766
#define FEATURE_OWORD_N_ARGS         0x00000002
767
#define FEATURE_INI_VARS             0x00000004
768
#define FEATURE_HAL_PIN_VARS         0x00000008
769
    // do not lowercase named params inside comments - for #<_hal[PinName]>
770
#define FEATURE_NO_DOWNCASE_OWORD    0x00000010
771
#define FEATURE_OWORD_WARNONLY       0x00000020
772
773
    boost::python::object *pythis;  // boost::cref to 'this'
774
    const char *on_abort_command;
775
    int_remap_map  g_remapped,m_remapped;
776
    remap_map remaps;
777
#define INIT_FUNC  "__init__"
778
#define DELETE_FUNC  "__delete__"
779
780
    // task calls upon interp.init() repeatedly
781
    // protect init() operations which are not idempotent
782
    int init_once;
783
};
784
785
typedef setup *setup_pointer;
786
// the externally visible singleton instance
787
788
extern class PythonPlugin *python_plugin;
789
#define PYUSABLE (((python_plugin) != NULL) && (python_plugin->usable()))
790
791
1503
inline bool is_a_cycle(int motion) {
792
1503
    return ((motion > G_80) && (motion < G_90)) || (motion == G_73);
793
}
794
/*
795
796
The _setup model includes a stack array for the names of function
797
calls. This stack is written into if an error occurs. Just before each
798
function returns an error code, it writes its name in the next
799
available string, initializes the following string, and increments
800
the array index. The following four macros do the work.
801
802
The size of the stack array is 50. An error in the middle of a very
803
complex expression would cause the ERP and CHP macros to write past the
804
bounds of the array if a check were not provided. No real program
805
would contain such a thing, but the check is included to make the
806
macros totally crash-proof. If the function call stack is deeper than
807
49, the top of the stack will be missing.
808
809
*/
810
811
812
// Just set an error string using printf-style formats, do NOT return
813
#define ERM(fmt, ...)                                      \
814
    do {                                                   \
815
        setError (fmt, ## __VA_ARGS__);                    \
816
        _setup.stack_index = 0;                            \
817
        strncpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN); \
818
        _setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \
819
        _setup.stack_index++; \
820
        _setup.stack[_setup.stack_index][0] = 0;           \
821
    } while(0)
822
823
// Set an error string using printf-style formats and return
824
#define ERS(fmt, ...)                                      \
825
    do {                                                   \
826
        setError (fmt, ## __VA_ARGS__);                    \
827
        _setup.stack_index = 0;                            \
828
        strncpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN); \
829
        _setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \
830
        _setup.stack_index++; \
831
        _setup.stack[_setup.stack_index][0] = 0;           \
832
        return INTERP_ERROR;                               \
833
    } while(0)
834
835
// Return one of the very few numeric errors
836
#define ERN(error_code)                                    \
837
    do {                                                   \
838
        _setup.stack_index = 0;                            \
839
        strncpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN); \
840
        _setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0; \
841
        _setup.stack_index++; \
842
        _setup.stack[_setup.stack_index][0] = 0;           \
843
        return error_code;                                 \
844
    } while(0)
845
846
847
// Propagate an error up the stack
848
#define ERP(error_code)                                        \
849
    do {                                                       \
850
        if (_setup.stack_index < STACK_LEN - 1) {                         \
851
            strncpy(_setup.stack[_setup.stack_index], __PRETTY_FUNCTION__, STACK_ENTRY_LEN); \
852
            _setup.stack[_setup.stack_index][STACK_ENTRY_LEN-1] = 0;    \
853
            _setup.stack_index++;                                       \
854
            _setup.stack[_setup.stack_index][0] = 0;           \
855
        }                                                      \
856
        return error_code;                                     \
857
    } while(0)
858
859
860
// If the condition is true, set an error string as with ERS
861
#define CHKS(bad, fmt, ...)                                    \
862
    do {                                                       \
863
        if (bad) {                                             \
864
	    ERS(fmt, ## __VA_ARGS__);                          \
865
        }                                                      \
866
    } while(0)
867
868
// If the condition is true, return one of the few numeric errors
869
#define CHKN(bad, error_code)                                  \
870
    do {                                                       \
871
        if (bad) {                                             \
872
	    ERN(error_code);                                   \
873
        }                                                      \
874
    } while(0)
875
876
877
// Propagate an error up the stack as with ERP if the result of 'call' is not
878
// INTERP_OK
879
#define CHP(call)                                                  \
880
    do {                                                           \
881
	int CHP__status = (call);                                  \
882
        if (CHP__status != INTERP_OK) {                            \
883
	    ERP(CHP__status);                                      \
884
        }                                                          \
885
    } while(0)
886
887
888
// oword warnings
889
#define OERR(fmt, ...)                                      \
890
    do {						    \
891
	if (FEATURE(OWORD_WARNONLY))			    \
892
	    fprintf(stderr,fmt, ## __VA_ARGS__);	    \
893
	else						    \
894
	    ERS(fmt, ## __VA_ARGS__);			    \
895
    } while(0)
896
897
898
//
899
// The traverse (in the active plane) to the location of the canned cycle
900
// is different on the first repeat vs on all the following repeats.
901
//
902
// The first traverse happens in the CURRENT_CC plane (which was raised to
903
// the R plane earlier, if needed), followed by a traverse down to the R
904
// plane.
905
//
906
// All later positioning moves happen in the CLEAR_CC plane, which is
907
// either the R plane or the OLD_CC plane depending on G98/G99.
908
//
909
910
#define CYCLE_MACRO(call) for (repeat = block->l_number; \
911
                               repeat > 0; \
912
                               repeat--) \
913
     { \
914
       aa = (aa + aa_increment); \
915
       bb = (bb + bb_increment); \
916
       if(radius_increment) { \
917
           double radius, theta; \
918
           CHKS((bb == 0 && aa == 0), _("Incremental motion with polar coordinates is indeterminate when at the origin")); \
919
           theta = atan2(bb, aa); \
920
           radius = hypot(bb, aa) + radius_increment; \
921
           aa = radius * cos(theta); \
922
           bb = radius * sin(theta); \
923
       } \
924
       if(theta_increment) { \
925
           double radius, theta; \
926
           CHKS((bb == 0 && aa == 0), _("Incremental motion with polar coordinates is indeterminate when at the origin")); \
927
           theta = atan2(bb, aa) + theta_increment; \
928
           radius = hypot(bb, aa); \
929
           aa = radius * cos(theta); \
930
           bb = radius * sin(theta); \
931
       } \
932
       if ((repeat == block->l_number) && (current_cc > r)) { \
933
         cycle_traverse(block, plane, aa, bb, current_cc); \
934
         cycle_traverse(block, plane, aa, bb, r); \
935
       } else { \
936
         /* we must be at CLEAR_CC already */ \
937
         cycle_traverse(block, plane, aa, bb, clear_cc); \
938
         if (clear_cc > r) { \
939
           cycle_traverse(block, plane, aa, bb, r); \
940
         } \
941
       } \
942
       CHP(call); \
943
     }
944
945
946
#endif // INTERP_INTERNAL_HH