GCC Code Coverage Report
Directory: emc/rs274ngc/ Exec Total Coverage
File: emc/rs274ngc/interp_namedparams.cc Lines: 162 357 45.4 %
Date: 2016-10-27 Branches: 73 337 21.7 %

Line Exec Source
1
/********************************************************************
2
* Description: interp_namedparams.cc
3
*
4
* collect all code related to named parameter handling
5
*
6
* Author: mostly K. Lerman
7
* rewrite by Michael Haberler to use STL containers
8
* License: GPL Version 2
9
* System: Linux
10
*
11
* Copyright (c) 2004 All rights reserved.
12
*
13
* Last change: Juli 2011
14
********************************************************************/
15
#ifndef _GNU_SOURCE
16
#define _GNU_SOURCE
17
#endif
18
19
#include "python_plugin.hh"
20
#include <boost/python/dict.hpp>
21
#include <boost/python/extract.hpp>
22
#include <boost/python/list.hpp>
23
#include <boost/python/tuple.hpp>
24
namespace bp = boost::python;
25
26
#include <unistd.h>
27
#include <stdio.h>
28
#include <stdlib.h>
29
#include <math.h>
30
#include <string.h>
31
#include <ctype.h>
32
#include <sys/types.h>
33
#include <sys/stat.h>
34
#include <sstream>
35
#include <map>
36
37
#include "rs274ngc.hh"
38
#include "rs274ngc_return.hh"
39
#include "interp_internal.hh"
40
#include "rs274ngc_interp.hh"
41
#include "inifile.hh"
42
43
// for HAL pin variables
44
#include "hal.h"
45
#include "hal/hal_priv.h"
46
47
enum predefined_named_parameters {
48
    NP_LINE,
49
    NP_MOTION_MODE,
50
    NP_PLANE,
51
    NP_CCOMP,
52
    NP_METRIC,
53
    NP_IMPERIAL,
54
    NP_ABSOLUTE,
55
    NP_INCREMENTAL,
56
    NP_INVERSE_TIME,
57
    NP_UNITS_PER_MINUTE,
58
    NP_UNITS_PER_REV,
59
    NP_COORD_SYSTEM,
60
    NP_TOOL_OFFSET,
61
    NP_RETRACT_R_PLANE,
62
    NP_RETRACT_OLD_Z,
63
    NP_SPINDLE_RPM_MODE,
64
    NP_SPINDLE_CSS_MODE,
65
    NP_IJK_ABSOLUTE_MODE,
66
    NP_LATHE_DIAMETER_MODE,
67
    NP_LATHE_RADIUS_MODE,
68
    NP_SPINDLE_ON,
69
    NP_SPINDLE_CW,
70
    NP_MIST,
71
    NP_FLOOD,
72
    NP_SPEED_OVERRIDE,
73
    NP_FEED_OVERRIDE,
74
    NP_ADAPTIVE_FEED,
75
    NP_FEED_HOLD,
76
    NP_FEED,
77
    NP_RPM,
78
    NP_CURRENT_TOOL,
79
    NP_SELECTED_POCKET,
80
    NP_CURRENT_POCKET,
81
    NP_X,
82
    NP_Y,
83
    NP_Z,
84
    NP_A,
85
    NP_B,
86
    NP_C,
87
    NP_U,
88
    NP_V,
89
    NP_W,
90
    NP_VALUE,
91
    NP_CALL_LEVEL,
92
    NP_REMAP_LEVEL,
93
    NP_SELECTED_TOOL,
94
    NP_VALUE_RETURNED,
95
    NP_TASK,
96
};
97
98
/****************************************************************************/
99
100
/*! read_named_parameter
101
102
Returned Value: int
103
   If read_integer_value returns an error code, this returns that code.
104
   If any of the following errors occur, this returns the error code shown.
105
   Otherwise, this returns INTERP_OK.
106
   1. The first character read is not a <:
107
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
108
   2. The named parameter string is not terminated by >:
109
      NCE_NAMED_PARAMETER_NOT_TERSINATED
110
   3. The named parameter has not been defined before use:
111
      NCE_NAMED_PARAMETER_NOT_DEFINED
112
113
Side effects:
114
   The value of the given parameter is put into what double_ptr points at.
115
   The counter is reset to point to the first character after the
116
   characters which make up the value.
117
118
Called by:  read_parameter
119
120
This attempts to read the value of a parameter out of the line,
121
starting at the index given by the counter.
122
123
According to the RS274/NGC manual [NCMS, p. 62], the characters following
124
# may be any "parameter expression". Thus, the following are legal
125
and mean the same thing (the value of the parameter whose number is
126
stored in parameter 2):
127
  ##2
128
  #[#2]
129
130
131
ADDED by K. Lerman
132
Named parameters are now supported.
133
#<_abcd> is a parameter with name "abcd" of global scope
134
#<abce> is a named parameter of local scope.
135
136
*/
137
138
2936
int Interp::read_named_parameter(
139
				 char *line,   //!< string: line of RS274/NGC code being processed
140
				 int *counter, //!< pointer to a counter for position on the line
141
				 double *double_ptr,   //!< pointer to double to be read
142
				 double *parameters,   //!< array of system parameters
143
				 bool check_exists)    //!< test for existence, not value
144
{
145
    static char name[] = "read_named_parameter";
146
    char paramNameBuf[LINELEN+1];
147
    int exists;
148
    double value;
149
    parameter_map_iterator pi;
150
151
2936
    CHKS((line[*counter] != '<'),
152
	 NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
153
2936
    CHP(read_name(line, counter, paramNameBuf));
154
155
2935
    CHP(find_named_param(paramNameBuf, &exists, &value));
156
2935
    if (check_exists) {
157
3
	*double_ptr = exists ? 1.0 : 0.0;
158
3
	return INTERP_OK;
159
    }
160
2932
    if (exists) {
161
2930
	*double_ptr = value;
162
2930
	return INTERP_OK;
163
    } else {
164
        // do not require named parameters to be defined during a
165
        // subroutine definition:
166
2
        if (_setup.defining_sub)
167
            return INTERP_OK;
168
169
1
	logNP("%s: referencing undefined named parameter '%s' level=%d",
170
	      name, paramNameBuf, (paramNameBuf[0] == '_') ? 0 : _setup.call_level);
171
1
	ERS(_("Named parameter #<%s> not defined"), paramNameBuf);
172
    }
173
    return INTERP_OK;
174
}
175
176
// if the variable is of the form '_ini[section]name', then treat it as
177
// an inifile  variable. Lookup section/name and cache the value
178
// as global and read-only.
179
// the shortest possible ini variable is '_ini[s]n' or 8 chars long .
180
10
int Interp::fetch_ini_param( const char *nameBuf, int *status, double *value)
181
{
182
    char *s;
183
10
    *status = 0;
184
10
    int n = strlen(nameBuf);
185
186
20
     if ((n > 7) &&
187
10
	((s = (char *) strchr(&nameBuf[6],']')) != NULL)) {
188
189
10
	IniFile inifile;
190
	const char *iniFileName;
191
	int retval;
192
10
	int closeBracket = s - nameBuf;
193
194
10
	if ((iniFileName = getenv("INI_FILE_NAME")) == NULL) {
195
	    logNP("warning: referencing ini parameter '%s': no ini file",nameBuf);
196
	    *status = 0;
197
	    return INTERP_OK;
198
	}
199
10
	if (!inifile.Open(iniFileName)) {
200
	    *status = 0;
201
	    ERS(_("cant open ini file '%s'"), iniFileName);
202
	}
203
204
	char capName[LINELEN];
205
206
10
	strncpy(capName, nameBuf, n);
207
10
	capName[n] = '\0';
208
216
	for (char *p = capName; *p != 0; p++)
209
206
	    *p = toupper(*p);
210
10
	capName[closeBracket] = '\0';
211
212
10
	if ((retval = inifile.Find( value, &capName[closeBracket+1], &capName[5])) == 0) {
213
8
	    *status = 1;
214
8
	    inifile.Close();
215
	} else {
216
2
	    inifile.Close();
217
2
	    *status = 0;
218
2
	    ERS(_("Named ini parameter #<%s> not found in inifile '%s': error=0x%x"),
219
		nameBuf, iniFileName, retval);
220
	}
221
    }
222
    return INTERP_OK;
223
}
224
225
// if the variable is of the form '_hal[hal_name]', then treat it as
226
// a HAL pin, signal or param. Lookup value, convert to float, and export as global and read-only.
227
// do not cache.
228
// the shortest possible ini variable is '_hal[x]' or 7 chars long .
229
int Interp::fetch_hal_param( const char *nameBuf, int *status, double *value)
230
{
231
    static int comp_id;
232
    int retval;
233
    int type = 0;
234
    hal_data_u* ptr;
235
    char hal_name[LINELEN];
236
237
    *status = 0;
238
    if (!comp_id) {
239
	char hal_comp[LINELEN];
240
	sprintf(hal_comp,"interp%d",getpid());
241
	comp_id = hal_init(hal_comp); // manpage says: NULL ok - which fails miserably
242
	CHKS(comp_id < 0,_("fetch_hal_param: hal_init(%s): %d"), hal_comp,comp_id);
243
	CHKS((retval = hal_ready(comp_id)), _("fetch_hal_param: hal_ready(): %d"),retval);
244
    }
245
    char *s;
246
    int n = strlen(nameBuf);
247
    if ((n > 6) &&
248
	((s = (char *) strchr(&nameBuf[5],']')) != NULL)) {
249
250
	int closeBracket = s - nameBuf;
251
	hal_pin_t *pin;
252
	hal_sig_t *sig;
253
	hal_param_t *param;
254
255
	strncpy(hal_name, &nameBuf[5], closeBracket);
256
	hal_name[closeBracket - 5] = '\0';
257
	if (nameBuf[closeBracket + 1]) {
258
	    logOword("%s: trailing garbage after closing bracket", hal_name);
259
	    *status = 0;
260
	    ERS("%s: trailing garbage after closing bracket", nameBuf);
261
	}
262
	// the result of these lookups could be cached in the parameter struct, but I'm not sure
263
	// this is a good idea - a removed pin/signal will not be noticed
264
265
	// I dont think that's needed - no change in pins/sigs/params
266
	// rtapi_mutex_get(&(hal_data->mutex));
267
        // rtapi_mutex_give(&(hal_data->mutex));
268
269
	if ((pin = halpr_find_pin_by_name(hal_name)) != NULL) {
270
            if (pin && !pin->signal) {
271
		logOword("%s: no signal connected", hal_name);
272
	    }
273
	    type = pin->type;
274
	    if (pin->signal != 0) {
275
		sig = (hal_sig_t *) SHMPTR(pin->signal);
276
		ptr = (hal_data_u *) SHMPTR(sig->data_ptr);
277
	    } else {
278
		ptr = (hal_data_u *) &(pin->dummysig);
279
	    }
280
	    goto assign;
281
	}
282
	if ((sig = halpr_find_sig_by_name(hal_name)) != NULL) {
283
	    if (!sig->writers)
284
		logOword("%s: signal has no writer", hal_name);
285
	    type = sig->type;
286
	    ptr = (hal_data_u *) SHMPTR(sig->data_ptr);
287
	    goto assign;
288
	}
289
	if ((param = halpr_find_param_by_name(hal_name)) != NULL) {
290
	    type = param->type;
291
	    ptr = (hal_data_u *) SHMPTR(param->data_ptr);
292
	    goto assign;
293
	}
294
	*status = 0;
295
	ERS("Named hal parameter #<%s> not found", nameBuf);
296
    }
297
    return INTERP_OK;
298
299
    assign:
300
    switch (type) {
301
    case HAL_BIT: *value = (double) (ptr->b); break;
302
    case HAL_U32: *value = (double) (ptr->u); break;
303
    case HAL_S32: *value = (double) (ptr->s); break;
304
    case HAL_FLOAT: *value = (double) (ptr->f); break;
305
    }
306
    logOword("%s: value=%f", hal_name, *value);
307
    *status = 1;
308
    return INTERP_OK;
309
}
310
311
8036
int Interp::find_named_param(
312
    const char *nameBuf, //!< pointer to name to be read
313
    int *status,    //!< pointer to return status 1 => found
314
    double *value   //!< pointer to value of found parameter
315
    )
316
{
317
  context_pointer frame;
318
  parameter_map_iterator pi;
319
  int level;
320
321
8036
  level = (nameBuf[0] == '_') ? 0 : _setup.call_level; // determine scope
322
8036
  frame = &_setup.sub_context[level];
323
8036
  *status = 0;
324
325
16072
  pi = frame->named_params.find(nameBuf);
326
16072
  if (pi == frame->named_params.end()) { // not found
327
5075
      int exists = 0;
328
      double inivalue;
329
5075
      if (FEATURE(INI_VARS) && (strncasecmp(nameBuf,"_ini[",5) == 0)) {
330
10
	 fetch_ini_param(nameBuf, &exists, &inivalue);
331
10
	  if (exists) {
332
8
	      logNP("parameter '%s' retrieved from INI: %f",nameBuf,inivalue);
333
8
	      *value = inivalue;
334
8
	      *status = 1;
335
	      parameter_value param;  // cache the value
336
8
	      param.value = inivalue;
337
8
	      param.attr = PA_GLOBAL | PA_READONLY | PA_FROM_INI;
338
8
	      _setup.sub_context[0].named_params[strstore(nameBuf)] = param;
339
	      return INTERP_OK;
340
	  }
341
      }
342
5067
      if (FEATURE(HAL_PIN_VARS) && (strncasecmp(nameBuf,"_hal[",5) == 0)) {
343
	  fetch_hal_param(nameBuf, &exists, &inivalue);
344
	  if (exists) {
345
	      logNP("parameter '%s' retrieved from HAL: %f",nameBuf,inivalue);
346
	      *value = inivalue;
347
	      *status = 1;
348
	      return INTERP_OK;
349
	  }
350
      }
351
5067
      *value = 0.0;
352
5067
      *status = 0;
353
  } else {
354
2961
      parameter_pointer pv = &pi->second;
355
2961
      if (pv->attr & PA_UNSET)
356
	  logNP("warning: referencing unset variable '%s'",nameBuf);
357
2961
      if (pv->attr & PA_USE_LOOKUP) {
358
20
	  CHP(lookup_named_param(nameBuf, pv->value, value));
359
20
	  *status = 1;
360
2941
      } else if (pv->attr & PA_PYTHON) {
361
	  bp::object retval, tupleargs, kwargs;
362
	  bp::list plist;
363
364
	  plist.append(*_setup.pythis); // self
365
	  tupleargs = bp::tuple(plist);
366
	  kwargs = bp::dict();
367
368
	  python_plugin->call(NAMEDPARAMS_MODULE, nameBuf, tupleargs, kwargs, retval);
369
	  CHKS(python_plugin->plugin_status() == PLUGIN_EXCEPTION,
370
	       "named param - pycall(%s):\n%s", nameBuf,
371
	       python_plugin->last_exception().c_str());
372
	  CHKS(retval.ptr() == Py_None, "Python namedparams.%s returns no value", nameBuf);
373
	  if (PyString_Check(retval.ptr())) {
374
	      // returning a string sets the interpreter error message and aborts
375
	      *status = 0;
376
	      char *msg = bp::extract<char *>(retval);
377
	      ERS("%s", msg);
378
	  }
379
	  if (PyInt_Check(retval.ptr())) { // widen
380
	      *value = (double) bp::extract<int>(retval);
381
	      *status = 1;
382
	      return INTERP_OK;
383
	  }
384
	  if (PyFloat_Check(retval.ptr())) {
385
	      *value =  bp::extract<double>(retval);
386
	      *status = 1;
387
	      return INTERP_OK;
388
	  }
389
	  // ok, that callable returned something botched.
390
	  *status = 0;
391
	  PyObject *res_str = PyObject_Str(retval.ptr());
392
	  Py_XDECREF(res_str);
393
	  ERS("Python call %s.%s returned '%s' - expected double, int or string, got %s",
394
	      NAMEDPARAMS_MODULE, nameBuf,
395
	      PyString_AsString(res_str),
396
	      retval.ptr()->ob_type->tp_name);
397
      } else {
398
2941
	  *value = pv->value;
399
2941
	  *status = 1;
400
      }
401
  }
402
  return INTERP_OK;
403
}
404
405
406
5071
int Interp::store_named_param(setup_pointer settings,
407
    const char *nameBuf, //!< pointer to name to be written
408
    double value,   //!< value to be written
409
    int override_readonly  //!< set to true to init a r/o parameter
410
    )
411
{
412
  context_pointer frame;
413
  int level;
414
  parameter_map_iterator pi;
415
416
5071
  level = (nameBuf[0] == '_') ? 0 : _setup.call_level; // determine scope
417
5071
  frame = &settings->sub_context[level];
418
419
10142
  pi = frame->named_params.find(nameBuf);
420
10142
  if (pi == frame->named_params.end()) {
421
      ERS(_("Internal error: Could not assign #<%s>"), nameBuf);
422
  } else {
423
5071
      parameter_pointer pv = &pi->second;
424
425
5071
      CHKS(((pv->attr & PA_GLOBAL)  && level),
426
	   "BUG: variable '%s' marked global, but assigned at level %d", nameBuf, level);
427
428
5071
      if ((pv->attr & PA_READONLY) && !override_readonly) {
429
1
	  ERS(_("Cannot assign to read-only parameter #<%s>"), nameBuf);
430
      } else {
431
5070
	  pv->value = value;
432
5070
	  pv->attr &= ~PA_UNSET;
433
5070
	  logNP("store_named_parameter: level[%d] %s value=%lf",
434
		level, nameBuf, value);
435
      }
436
  }
437
  return INTERP_OK;
438
}
439
440
441
442
5071
int Interp::add_named_param(
443
    const char *nameBuf, //!< pointer to name to be added
444
    int attr) //!< see PA_* defs in interp_internal.hh
445
{
446
  static char name[] = "add_named_param";
447
  int findStatus;
448
  double value;
449
  int level;
450
  parameter_value param;
451
452
  // look it up to see if already exists
453
5071
  CHP(find_named_param(nameBuf, &findStatus, &value));
454
455
5071
  if (findStatus) {
456
9
      logNP("%s: parameter:|%s| already exists", name, nameBuf);
457
      return INTERP_OK;
458
  }
459
5062
  attr |= PA_UNSET;
460
461
5062
  if (nameBuf[0] != '_') {  // local scope
462
1662
      level = _setup.call_level;
463
  } else {
464
3400
      level = 0;    // call level zero is global scope
465
3400
      attr |= PA_GLOBAL;
466
  }
467
5062
  param.value = 0.0;
468
5062
  param.attr = attr;
469
5062
  _setup.sub_context[level].named_params[strstore(nameBuf)] = param;
470
5062
  return INTERP_OK;
471
}
472
473
474
363
int Interp::free_named_parameters(context_pointer frame)
475
{
476
363
    frame->named_params.clear();
477
363
    return INTERP_OK;
478
}
479
480
481
// just a shorthand
482
3400
int Interp::init_readonly_param(
483
    const char *nameBuf, //!< pointer to name to be added
484
    double value,  //!< initial value
485
    int attr)       //!< see PA_* defs in interp_internal.hh
486
{
487
    // static char name[] = "init_readonly_param";
488
3400
    CHKS( add_named_param((char *) nameBuf, PA_READONLY|attr),
489
	  "adding r/o '%s'", nameBuf);
490
3400
    CHKS(store_named_param(&_setup, (char *) nameBuf, value, OVERRIDE_READONLY),
491
	 "storing r/o '%s' %f", nameBuf, value);
492
    return INTERP_OK;
493
}
494
495
496
20
int Interp::lookup_named_param(const char *nameBuf,
497
			   double index,
498
			   double *value)
499
{
500
20
    int cmd = round_to_int(index);
501
502
20
    switch (cmd) {
503
504
	// some active_g_codes fields
505
506
    case NP_LINE: // _line - sequence number
507
8
	*value = _setup.sequence_number;
508
8
	break;
509
510
    case NP_MOTION_MODE: // _motion_mode
511
	*value = _setup.motion_mode;
512
	break;
513
514
    case NP_PLANE: // _plane
515
	switch(_setup.plane) {
516
	case CANON_PLANE_XY:
517
	    *value = G_17;
518
	    break;
519
	case CANON_PLANE_XZ:
520
	    *value = G_18;
521
	    break;
522
	case CANON_PLANE_YZ:
523
	    *value = G_19;
524
	    break;
525
	case CANON_PLANE_UV:
526
	    *value = G_17_1;
527
	    break;
528
	case CANON_PLANE_UW:
529
	    *value = G_18_1;
530
	    break;
531
	case CANON_PLANE_VW:
532
	    *value = G_19_1;
533
	    break;
534
	}
535
	break;
536
537
    case NP_CCOMP: // _ccomp - cutter compensation
538
	*value =
539
	    (_setup.cutter_comp_side == RIGHT) ? G_42 :
540
	(_setup.cutter_comp_side == LEFT) ? G_41 : G_40;
541
	break;
542
543
    case NP_METRIC: // _metric
544
	*value = (_setup.length_units == CANON_UNITS_MM);
545
	break;
546
547
    case NP_IMPERIAL: // _imperial
548
	*value = (_setup.length_units == CANON_UNITS_INCHES);
549
	break;
550
551
    case NP_ABSOLUTE: // _absolute - distance mode
552
	*value = (_setup.distance_mode == MODE_ABSOLUTE);
553
	break;
554
555
    case NP_INCREMENTAL: // _incremental - distance mode
556
	*value = (_setup.distance_mode == MODE_INCREMENTAL);
557
	break;
558
559
    case NP_INVERSE_TIME: // _inverse_time - feed mode
560
	*value = (_setup.feed_mode == INVERSE_TIME);
561
	break;
562
563
    case NP_UNITS_PER_MINUTE: // _units_per_minute - feed mode
564
	*value = (_setup.feed_mode == UNITS_PER_MINUTE);
565
	break;
566
567
    case NP_UNITS_PER_REV: // _units_per_rev - feed mode
568
	*value = (_setup.feed_mode == UNITS_PER_REVOLUTION);
569
	break;
570
571
    case NP_COORD_SYSTEM: // _coord_system - 0-9
572
	*value =
573
	    (_setup.origin_index < 7) ? (530 + (10 * _setup.origin_index)) :
574
	    (584 + _setup.origin_index);
575
	break;
576
577
    case NP_TOOL_OFFSET: // _tool_offset
578
	*value =  (_setup.tool_offset.tran.x || _setup.tool_offset.tran.y || _setup.tool_offset.tran.z ||
579
		   _setup.tool_offset.a || _setup.tool_offset.b || _setup.tool_offset.c ||
580
		   _setup.tool_offset.u || _setup.tool_offset.v || _setup.tool_offset.w) ;
581
	break;
582
583
    case NP_RETRACT_R_PLANE: // _retract_r_plane - G98
584
	*value = (_setup.retract_mode == R_PLANE);
585
	break;
586
587
    case NP_RETRACT_OLD_Z: // _retract_old_z - G99
588
	*value = (_setup.retract_mode == OLD_Z);
589
	break;
590
591
    case NP_SPINDLE_RPM_MODE: // _spindle_rpm_mode G97
592
	*value = (_setup.spindle_mode == CONSTANT_RPM);
593
	break;
594
595
    case NP_SPINDLE_CSS_MODE: // _spindle_css_mode G96
596
	*value = (_setup.spindle_mode == CONSTANT_SURFACE);
597
	break;
598
599
    case NP_IJK_ABSOLUTE_MODE: //_ijk_absolute_mode - G90.1
600
	*value = (_setup.ijk_distance_mode == MODE_ABSOLUTE);
601
	break;
602
603
    case NP_LATHE_DIAMETER_MODE: // _lathe_diameter_mode - G7
604
	*value = _setup.lathe_diameter_mode;
605
	break;
606
607
    case NP_LATHE_RADIUS_MODE: // _lathe_radius_mode - G8
608
	*value = (_setup.lathe_diameter_mode == 0);
609
	break;
610
611
	// some active_m_codes fields
612
613
    case NP_SPINDLE_ON: // _spindle_on
614
	*value = (_setup.spindle_turning != CANON_STOPPED);
615
	break;
616
617
    case NP_SPINDLE_CW: // spindle_cw
618
	*value = (_setup.spindle_turning == CANON_CLOCKWISE);
619
	break;
620
621
    case NP_MIST: // mist
622
	*value = _setup.mist;
623
	break;
624
625
    case NP_FLOOD: // flood
626
	*value = _setup.flood;
627
	break;
628
629
    case NP_SPEED_OVERRIDE: // speed override
630
	*value = _setup.speed_override;
631
	break;
632
633
    case NP_FEED_OVERRIDE: // feed override
634
	*value = _setup.feed_override;
635
	break;
636
637
    case NP_ADAPTIVE_FEED: // adaptive feed
638
	*value = _setup.adaptive_feed;
639
	break;
640
641
    case NP_FEED_HOLD: // feed hold
642
	*value = _setup.feed_hold;
643
	break;
644
645
	// from active_settings:
646
    case NP_FEED: // feed
647
	*value = _setup.feed_rate;
648
	break;
649
650
    case NP_RPM: // speed (rpm)
651
	*value = abs(_setup.speed);
652
	break;
653
654
    case NP_CURRENT_TOOL:
655
	*value = _setup.tool_table[_setup.current_pocket].toolno;
656
	break;
657
658
    case NP_SELECTED_POCKET:
659
	*value = _setup.selected_pocket;
660
	break;
661
662
    case NP_CURRENT_POCKET:
663
	*value = _setup.current_pocket;
664
	break;
665
666
    case NP_SELECTED_TOOL:
667
	*value = _setup.selected_tool;
668
	break;
669
670
    case NP_X:  // current position
671
1
	*value = _setup.current_x;
672
1
	break;
673
674
    case NP_Y:  // current position
675
1
	*value = _setup.current_y;
676
1
	break;
677
678
    case NP_Z:  // current position
679
1
	*value = _setup.current_z;
680
1
	break;
681
682
    case NP_A:  // current position
683
	*value = _setup.AA_current;
684
	break;
685
686
    case NP_B:  // current position
687
	*value = _setup.BB_current;
688
	break;
689
690
    case NP_C:  // current position
691
	*value = _setup.CC_current;
692
	break;
693
694
    case NP_U:  // current position
695
	*value = _setup.u_current;
696
	break;
697
698
    case NP_V:  // current position
699
	*value = _setup.v_current;
700
	break;
701
702
    case NP_W:  // current position
703
	*value = _setup.w_current;
704
	break;
705
706
	// o-word subs may optionally have an
707
	// expression after endsub and return
708
	// this 'function return value' is accessible as '_value'
709
    case NP_VALUE:
710
9
	*value = _setup.return_value;
711
9
	break;
712
713
	// predicate: the last NGC procedure did/did not return a value
714
    case NP_VALUE_RETURNED:
715
	*value = _setup.value_returned;
716
	break;
717
718
    case NP_CALL_LEVEL:
719
	*value = _setup.call_level;
720
	break;
721
722
    case NP_REMAP_LEVEL:
723
	*value = _setup.remap_level;
724
	break;
725
726
    case NP_TASK:
727
	extern int _task;  // zero in gcodemodule, 1 in milltask
728
	*value = _task;
729
	break;
730
731
732
    default:
733
	ERS(_("BUG: lookup_named_param(%s): unhandled index=%fn"),
734
	      nameBuf,index);
735
    }
736
    return INTERP_OK;
737
}
738
739
int Interp::init_python_predef_parameter(const char *name)
740
{
741
    int exists = 0;
742
    double value;
743
    parameter_value param;
744
745
    if (name[0] == '_') { // globals only
746
	find_named_param(name, &exists, &value);
747
	if (exists) {
748
	    fprintf(stderr, "warning: redefining named parameter %s\n",name);
749
	    _setup.sub_context[0].named_params.erase(name);
750
	}
751
	param.value = 0.0;
752
	param.attr = PA_READONLY|PA_PYTHON|PA_GLOBAL;
753
	_setup.sub_context[0].named_params[strstore(name)] = param;
754
    }
755
    return INTERP_OK;
756
}
757
758
68
int Interp::init_named_parameters()
759
{
760
761
// version       major   minor      Note
762
// ------------ -------- ---------- -------------------------------------
763
// M.N.m         M.N     0.m        normal format
764
// M.N.m~xxx     M.N     0.m        pre-release format
765
68
  const char *pkgversion = PACKAGE_VERSION;  //examples: 2.4.6, 2.5.0~pre
766
68
  const char *version_major = "_vmajor";// named_parameter name (use lower case)
767
68
  const char *version_minor = "_vminor";// named_parameter name (use lower case)
768
68
  double vmajor=0.0, vminor=0.0;
769
68
  sscanf(pkgversion, "%lf%lf", &vmajor, &vminor);
770
771
68
  init_readonly_param(version_major,vmajor,0);
772
68
  init_readonly_param(version_minor,vminor,0);
773
774
  // params tagged with PA_USE_LOOKUP will call the lookup_named_param()
775
  // method. The value is used as a index for the switch() statement.
776
777
  // the active_g_codes fields
778
779
  // I guess this is the line number
780
68
  init_readonly_param("_line", NP_LINE, PA_USE_LOOKUP);
781
782
  // any of G1 G2 G3 G5.2 G73 G80 G82 G83 G86 G87 G88 G89
783
  // value is number after 'G' mutiplied by 10 (10,20,30,52..)
784
785
68
  init_readonly_param("_motion_mode", NP_MOTION_MODE, PA_USE_LOOKUP);
786
787
  // G17/18/19/17.1/18.1/19.1 -> return 170/180/190/171/181/191
788
68
  init_readonly_param("_plane", NP_PLANE, PA_USE_LOOKUP);
789
790
  // return 400,410,420 depending if (G40,G41,G42) is on
791
68
  init_readonly_param("_ccomp", NP_CCOMP, PA_USE_LOOKUP);
792
793
  // 1.0 if G21 is on
794
68
  init_readonly_param("_metric", NP_METRIC, PA_USE_LOOKUP);
795
796
  // 1.0 if G20 is on
797
68
  init_readonly_param("_imperial", NP_IMPERIAL, PA_USE_LOOKUP);
798
799
  //1.0 if G90 is on
800
68
  init_readonly_param("_absolute", NP_ABSOLUTE, PA_USE_LOOKUP);
801
802
  //1.0 if G91 is on
803
68
  init_readonly_param("_incremental", NP_INCREMENTAL, PA_USE_LOOKUP);
804
805
  // 1.0 if G93 is on
806
68
  init_readonly_param("_inverse_time", NP_INVERSE_TIME, PA_USE_LOOKUP);
807
808
  // 1.0 if G94 is on
809
68
  init_readonly_param("_units_per_minute", NP_UNITS_PER_MINUTE, PA_USE_LOOKUP);
810
811
  // 1.0 if G95 is on
812
68
  init_readonly_param("_units_per_rev", NP_UNITS_PER_REV, PA_USE_LOOKUP);
813
814
  // 0..9 for G54..G59.3
815
68
  init_readonly_param("_coord_system", NP_COORD_SYSTEM, PA_USE_LOOKUP);
816
817
  // 1.0 if G43 is on
818
68
  init_readonly_param("_tool_offset", NP_TOOL_OFFSET, PA_USE_LOOKUP);
819
820
  // 1 if G98 set
821
68
  init_readonly_param("_retract_r_plane", NP_RETRACT_R_PLANE, PA_USE_LOOKUP);
822
823
  // 1 if G99 set
824
68
  init_readonly_param("_retract_old_z", NP_RETRACT_OLD_Z, PA_USE_LOOKUP);
825
826
  // really esoteric
827
  // init_readonly_param("_control_mode", 110, PA_USE_LOOKUP);
828
829
830
  // 1 if G97 is on
831
68
  init_readonly_param("_spindle_rpm_mode", NP_SPINDLE_RPM_MODE, PA_USE_LOOKUP);
832
833
68
  init_readonly_param("_spindle_css_mode", NP_SPINDLE_CSS_MODE, PA_USE_LOOKUP);
834
835
  // 1 if G90.1 is on
836
68
  init_readonly_param("_ijk_absolute_mode", NP_IJK_ABSOLUTE_MODE, PA_USE_LOOKUP);
837
838
  // 1 if G7 is on
839
68
  init_readonly_param("_lathe_diameter_mode", NP_LATHE_DIAMETER_MODE, PA_USE_LOOKUP);
840
841
  // 1 if G8 is on
842
68
  init_readonly_param("_lathe_radius_mode", NP_LATHE_RADIUS_MODE, PA_USE_LOOKUP);
843
844
845
  // the active_m_codes fields
846
68
  init_readonly_param("_spindle_on", NP_SPINDLE_ON, PA_USE_LOOKUP);
847
68
  init_readonly_param("_spindle_cw", NP_SPINDLE_CW, PA_USE_LOOKUP);
848
849
68
  init_readonly_param("_mist", NP_MIST, PA_USE_LOOKUP);
850
68
  init_readonly_param("_flood", NP_FLOOD, PA_USE_LOOKUP);
851
68
  init_readonly_param("_speed_override", NP_SPEED_OVERRIDE, PA_USE_LOOKUP);
852
68
  init_readonly_param("_feed_override", NP_FEED_OVERRIDE, PA_USE_LOOKUP);
853
68
  init_readonly_param("_adaptive_feed", NP_ADAPTIVE_FEED, PA_USE_LOOKUP);
854
68
  init_readonly_param("_feed_hold", NP_FEED_HOLD, PA_USE_LOOKUP);
855
856
  // active_settings
857
68
  init_readonly_param("_feed", NP_FEED, PA_USE_LOOKUP);
858
68
  init_readonly_param("_rpm", NP_RPM, PA_USE_LOOKUP);
859
860
861
  // tool related
862
68
  init_readonly_param("_current_tool", NP_CURRENT_TOOL, PA_USE_LOOKUP);
863
68
  init_readonly_param("_current_pocket", NP_CURRENT_POCKET, PA_USE_LOOKUP);
864
68
  init_readonly_param("_selected_pocket", NP_SELECTED_POCKET, PA_USE_LOOKUP);
865
68
  init_readonly_param("_selected_tool", NP_SELECTED_TOOL, PA_USE_LOOKUP);
866
867
  // current position - alias to #5420-#5429
868
68
  init_readonly_param("_x", NP_X, PA_USE_LOOKUP);
869
68
  init_readonly_param("_y", NP_Y, PA_USE_LOOKUP);
870
68
  init_readonly_param("_z", NP_Z, PA_USE_LOOKUP);
871
68
  init_readonly_param("_a", NP_A, PA_USE_LOOKUP);
872
68
  init_readonly_param("_b", NP_B, PA_USE_LOOKUP);
873
68
  init_readonly_param("_c", NP_C, PA_USE_LOOKUP);
874
68
  init_readonly_param("_u", NP_U, PA_USE_LOOKUP);
875
68
  init_readonly_param("_v", NP_V, PA_USE_LOOKUP);
876
68
  init_readonly_param("_w", NP_W, PA_USE_LOOKUP);
877
878
  // last (optional) endsub/return value
879
68
  init_readonly_param("_value", NP_VALUE, PA_USE_LOOKUP);
880
881
  // predicate: last NGC procedure did return a value on endsub/return
882
68
  init_readonly_param("_value_returned", NP_VALUE_RETURNED, PA_USE_LOOKUP);
883
884
  // predicate: 1 in milltask instance, 0 in UI - control preview behaviour
885
68
  init_readonly_param("_task", NP_TASK, PA_USE_LOOKUP);
886
887
  // debugging aids
888
68
  init_readonly_param("_call_level", NP_CALL_LEVEL, PA_USE_LOOKUP);
889
68
  init_readonly_param("_remap_level", NP_REMAP_LEVEL, PA_USE_LOOKUP);
890
891
68
  return INTERP_OK;
892
207
}