GCC Code Coverage Report
Directory: emc/rs274ngc/ Exec Total Coverage
File: emc/rs274ngc/interp_read.cc Lines: 545 724 75.3 %
Date: 2016-10-27 Branches: 444 970 45.8 %

Line Exec Source
1
/********************************************************************
2
* Description: interp_read.cc
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
* Last change:
13
********************************************************************/
14
#ifndef _GNU_SOURCE
15
#define _GNU_SOURCE
16
#endif
17
#include <unistd.h>
18
#include <stdio.h>
19
#include <stdlib.h>
20
#include <math.h>
21
#include <string.h>
22
#include <ctype.h>
23
#include <sys/types.h>
24
#include <sys/stat.h>
25
#include <sstream>
26
#include "rs274ngc.hh"
27
#include "rs274ngc_return.hh"
28
#include "interp_internal.hh"
29
#include "rs274ngc_interp.hh"
30
#include "rtapi_math.h"
31
#include <cmath>
32
33
/****************************************************************************/
34
35
/*! read_a
36
37
Returned Value: int
38
   If read_real_value returns an error code, this returns that code.
39
   If any of the following errors occur, this returns the error code shown.
40
   Otherwise, it returns INTERP_OK.
41
   1. The first character read is not a:
42
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
43
   2. An a_coordinate has already been inserted in the block:
44
      NCE_MULTIPLE_A_WORDS_ON_ONE_LINE.
45
   3. A values are not allowed: NCE_CANNOT_USE_A_WORD.
46
47
Side effects:
48
   counter is reset.
49
   The a_flag in the block is turned on.
50
   An a_number is inserted in the block.
51
52
Called by: read_one_item
53
54
When this function is called, counter is pointing at an item on the
55
line that starts with the character 'a', indicating an a_coordinate
56
setting. The function reads characters which tell how to set the
57
coordinate, up to the start of the next item or the end of the line.
58
The counter is then set to point to the character following.
59
60
The value may be a real number or something that evaluates to a
61
real number, so read_real_value is used to read it. Parameters
62
may be involved.
63
64
If the AA compiler flag is defined, the a_flag in the block is turned
65
on and the a_number in the block is set to the value read. If the
66
AA flag is not defined, (i) if the AXIS_ERROR flag is defined, that means
67
A values are not allowed, and an error value is returned, (ii) if the
68
AXIS_ERROR flag is not defined, nothing is done.
69
70
*/
71
72
3
int Interp::read_a(char *line,   //!< string: line of RS274/NGC code being processed
73
                  int *counter, //!< pointer to a counter for position on the line
74
                  block_pointer block,  //!< pointer to a block being filled from the line
75
                  double *parameters)   //!< array of system parameters
76
{
77
  double value;
78
79
3
  CHKS((line[*counter] != 'a'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
80
3
  *counter = (*counter + 1);
81
3
  CHKS((block->a_flag), NCE_MULTIPLE_A_WORDS_ON_ONE_LINE);
82
3
  CHP(read_real_value(line, counter, &value, parameters));
83
3
  block->a_flag = true;
84
3
  block->a_number = value;
85
3
  return INTERP_OK;
86
}
87
88
89
/****************************************************************************/
90
91
/*! read_atan
92
93
Returned Value: int
94
   If read_real_expression returns an error code, this returns that code.
95
   If any of the following errors occur, this returns the error code shown.
96
   Otherwise, it returns INTERP_OK.
97
   1. The first character to read is not a slash:
98
      NCE_SLASH_MISSING_AFTER_FIRST_ATAN_ARGUMENT
99
   2. The second character to read is not a left bracket:
100
      NCE_LEFT_BRACKET_MISSING_AFTER_SLASH_WITH_ATAN
101
102
Side effects:
103
   The computed value is put into what double_ptr points at.
104
   The counter is reset to point to the first character after the
105
   characters which make up the value.
106
107
Called by:
108
   read_unary
109
110
When this function is called, the characters "atan" and the first
111
argument have already been read, and the value of the first argument
112
is stored in double_ptr.  This function attempts to read a slash and
113
the second argument to the atan function, starting at the index given
114
by the counter and then to compute the value of the atan operation
115
applied to the two arguments.  The computed value is inserted into
116
what double_ptr points at.
117
118
The computed value is in the range from -180 degrees to +180 degrees.
119
The range is not specified in the RS274/NGC manual [NCMS, page 51],
120
although using degrees (not radians) is specified.
121
122
*/
123
124
int Interp::read_atan(char *line,        //!< string: line of RS274/NGC code being processed
125
                     int *counter,      //!< pointer to a counter for position on line
126
                     double *double_ptr,        //!< pointer to double to be read
127
                     double *parameters)        //!< array of system parameters
128
{
129
  double argument2;
130
131
  CHKS((line[*counter] != '/'), NCE_SLASH_MISSING_AFTER_FIRST_ATAN_ARGUMENT);
132
  *counter = (*counter + 1);
133
  CHKS((line[*counter] != '['),
134
      NCE_LEFT_BRACKET_MISSING_AFTER_SLASH_WITH_ATAN);
135
  CHP(read_real_expression(line, counter, &argument2, parameters));
136
  *double_ptr = atan2(*double_ptr, argument2);  /* value in radians */
137
  *double_ptr = ((*double_ptr * 180.0) / M_PIl);   /* convert to degrees */
138
  return INTERP_OK;
139
}
140
141
/****************************************************************************/
142
143
/*! read_b
144
145
Returned Value: int
146
   If read_real_value returns an error code, this returns that code.
147
   If any of the following errors occur, this returns the error code shown.
148
   Otherwise, it returns INTERP_OK.
149
   1. The first character read is not b:
150
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
151
   2. A b_coordinate has already been inserted in the block:
152
      NCE_MULTIPLE_B_WORDS_ON_ONE_LINE.
153
   3. B values are not allowed: NCE_CANNOT_USE_B_WORD
154
155
Side effects:
156
   counter is reset.
157
   The b_flag in the block is turned on.
158
   A b_number is inserted in the block.
159
160
Called by: read_one_item
161
162
When this function is called, counter is pointing at an item on the
163
line that starts with the character 'b', indicating a b_coordinate
164
setting. The function reads characters which tell how to set the
165
coordinate, up to the start of the next item or the end of the line.
166
The counter is then set to point to the character following.
167
168
The value may be a real number or something that evaluates to a
169
real number, so read_real_value is used to read it. Parameters
170
may be involved.
171
172
If the BB compiler flag is defined, the b_flag in the block is turned
173
on and the b_number in the block is set to the value read. If the
174
BB flag is not defined, (i) if the AXIS_ERROR flag is defined, that means
175
B values are not allowed, and an error value is returned, (ii) if the
176
AXIS_ERROR flag is not defined, nothing is done.
177
178
*/
179
180
int Interp::read_b(char *line,   //!< string: line of RS274/NGC code being processed
181
                  int *counter, //!< pointer to a counter for position on the line
182
                  block_pointer block,  //!< pointer to a block being filled from the line
183
                  double *parameters)   //!< array of system parameters
184
{
185
  double value;
186
187
  CHKS((line[*counter] != 'b'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
188
  *counter = (*counter + 1);
189
  CHKS((block->b_flag), NCE_MULTIPLE_B_WORDS_ON_ONE_LINE);
190
  CHP(read_real_value(line, counter, &value, parameters));
191
  block->b_flag = true;
192
  block->b_number = value;
193
  return INTERP_OK;
194
}
195
196
/****************************************************************************/
197
198
/*! read_c
199
200
Returned Value: int
201
   If read_real_value returns an error code, this returns that code.
202
   If any of the following errors occur, this returns the error code shown.
203
   Otherwise, it returns INTERP_OK.
204
   1. The first character read is not c:
205
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
206
   2. An c_coordinate has already been inserted in the block:
207
      NCE_MULTIPLE_C_WORDS_ON_ONE_LINE
208
   3. C values are not allowed: NCE_CANNOT_USE_C_WORD
209
210
Side effects:
211
   counter is reset.
212
   The c_flag in the block is turned on.
213
   A c_number is inserted in the block.
214
215
Called by: read_one_item
216
217
When this function is called, counter is pointing at an item on the
218
line that starts with the character 'c', indicating an c_coordinate
219
setting. The function reads characters which tell how to set the
220
coordinate, up to the start of the next item or the end of the line.
221
The counter is then set to point to the character following.
222
223
The value may be a real number or something that evaluates to a
224
real number, so read_real_value is used to read it. Parameters
225
may be involved.
226
227
If the CC compiler flag is defined, the c_flag in the block is turned
228
on and the c_number in the block is set to the value read. If the
229
CC flag is not defined, (i) if the AXIS_ERROR flag is defined, that means
230
C values are not allowed, and an error value is returned, (ii) if the
231
AXIS_ERROR flag is not defined, nothing is done.
232
233
*/
234
235
int Interp::read_c(char *line,   //!< string: line of RS274/NGC code being processed
236
                  int *counter, //!< pointer to a counter for position on the line
237
                  block_pointer block,  //!< pointer to a block being filled from the line
238
                  double *parameters)   //!< array of system parameters
239
{
240
  double value;
241
242
  CHKS((line[*counter] != 'c'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
243
  *counter = (*counter + 1);
244
  CHKS((block->c_flag), NCE_MULTIPLE_C_WORDS_ON_ONE_LINE);
245
  CHP(read_real_value(line, counter, &value, parameters));
246
  block->c_flag = true;
247
  block->c_number = value;
248
  return INTERP_OK;
249
}
250
251
/****************************************************************************/
252
253
/*! read_comment
254
255
Returned Value: int
256
  If any of the following errors occur, this returns the error code shown.
257
   Otherwise, it returns INTERP_OK.
258
   1. The first character read is not '(' ,
259
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
260
261
Side effects:
262
   The counter is reset to point to the character following the comment.
263
   The comment string, without parentheses, is copied into the comment
264
   area of the block.
265
266
Called by: read_one_item
267
268
When this function is called, counter is pointing at an item on the
269
line that starts with the character '(', indicating a comment is
270
beginning. The function reads characters of the comment, up to and
271
including the comment closer ')'.
272
273
It is expected that the format of a comment will have been checked (by
274
read_text or read_keyboard_line) and bad format comments will
275
have prevented the system from getting this far, so that this function
276
can assume a close parenthesis will be found when an open parenthesis
277
has been found, and that comments are not nested.
278
279
The "parameters" argument is not used in this function. That argument is
280
present only so that this will have the same argument list as the other
281
"read_XXX" functions called using a function pointer by read_one_item.
282
283
*/
284
285
1295
int Interp::read_comment(char *line,     //!< string: line of RS274 code being processed
286
                        int *counter,   //!< pointer to a counter for position on the line
287
                        block_pointer block,    //!< pointer to a block being filled from the line
288
                        double *parameters)     //!< array of system parameters
289
{
290
  int n;
291
292
1295
  CHKS((line[*counter] != '('), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
293
1295
  (*counter)++;
294
33763
  for (n = 0; line[*counter] != ')'; (*counter)++, n++) {
295
32468
    block->comment[n] = line[*counter];
296
  }
297
1295
  block->comment[n] = 0;
298
1295
  (*counter)++;
299
1295
  return INTERP_OK;
300
}
301
302
// A semicolon marks the beginning of a comment.  The comment goes to
303
// the end of the line.
304
305
163
int Interp::read_semicolon(char *line,     //!< string: line of RS274 code being processed
306
                           int *counter,   //!< pointer to a counter for position on the line
307
                           block_pointer block,    //!< pointer to a block being filled from the line
308
                           double *parameters)     //!< array of system parameters
309
{
310
    char *s;
311
163
    CHKS((line[*counter] != ';'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
312
163
    (*counter) = strlen(line);
313
    // pass unmutilated line to convert_comment - FIXME access to _setup
314
326
    if (( s = strchr(_setup.linetext,';')) != NULL)
315
163
	CHP(convert_comment(s+1, false));
316
    return INTERP_OK;
317
}
318
319
/****************************************************************************/
320
321
/*! read_d
322
323
Returned Value: int
324
   If read_integer_value returns an error code, this returns that code.
325
   If any of the following errors occur, this returns the error code shown.
326
   Otherwise, it returns INTERP_OK.
327
   1. The first character read is not d:
328
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
329
   2. A d_number has already been inserted in the block:
330
      NCE_MULTIPLE_D_WORDS_ON_ONE_LINE
331
332
Side effects:
333
   counter is reset to the character following the tool number.
334
   A d_number is inserted in the block.
335
336
Called by: read_one_item
337
338
When this function is called, counter is pointing at an item on the
339
line that starts with the character 'd', indicating an index into a
340
table of tool diameters.  The function reads characters which give the
341
(integer) value of the index. The value may not be more than
342
_setup.tool_max and may not be negative, but it may be zero. The range
343
is checked here.
344
345
read_integer_value allows a minus sign, so a check for a negative value
346
is made here, and the parameters argument is also needed.
347
348
*/
349
350
62
int Interp::read_d(char *line,   //!< string: line of RS274 code being processed
351
                  int *counter, //!< pointer to a counter for position on the line
352
                  block_pointer block,  //!< pointer to a block being filled from the line
353
                  double *parameters)   //!< array of system parameters
354
{
355
  double value;
356
357
62
  CHKS((line[*counter] != 'd'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
358
62
  *counter = (*counter + 1);
359
62
  CHKS((block->d_flag), NCE_MULTIPLE_D_WORDS_ON_ONE_LINE);
360
62
  CHP(read_real_value(line, counter, &value, parameters));
361
62
  block->d_number_float = value;
362
62
  block->d_flag = true;
363
62
  return INTERP_OK;
364
}
365
366
/****************************************************************************/
367
368
/*! read_e
369
370
Returned Value: int
371
   If read_real_value returns an error code, this returns that code.
372
   If any of the following errors occur, this returns the error code shown.
373
   Otherwise, it returns INTERP_OK.
374
   1. The first character read is not e:
375
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
376
   2. A e value has already been inserted in the block:
377
      NCE_MULTIPLE_E_WORDS_ON_ONE_LINE
378
379
Side effects:
380
   counter is reset to point to the first character following the e value.
381
   The e value setting is inserted in block.
382
383
Called by: read_one_item
384
385
When this function is called, counter is pointing at an item on the
386
line that starts with the character 'e', indicating a e value
387
setting. The function reads characters which tell how to set the e
388
value, up to the start of the next item or the end of the line. This
389
information is inserted in the block.
390
391
E codes are used for:
392
Infeed/Outfeed angle specification with G76
393
394
*/
395
396
1
int Interp::read_e(char *line,   //!< string: line of RS274/NGC code being processed
397
                  int *counter, //!< pointer to a counter for position on the line
398
                  block_pointer block,  //!< pointer to a block being filled from the line
399
                  double *parameters)   //!< array of system parameters
400
{
401
  double value;
402
403
1
  CHKS((line[*counter] != 'e'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
404
1
  *counter = (*counter + 1);
405
1
  CHKS((block->e_flag), NCE_MULTIPLE_E_WORDS_ON_ONE_LINE);
406
1
  CHP(read_real_value(line, counter, &value, parameters));
407
1
  block->e_flag = true;
408
1
  block->e_number = value;
409
1
  return INTERP_OK;
410
}
411
412
413
/****************************************************************************/
414
415
/*! read_f
416
417
Returned Value: int
418
   If read_real_value returns an error code, this returns that code.
419
   If any of the following errors occur, this returns the error code shown.
420
   Otherwise, it returns INTERP_OK.
421
   1. The first character read is not f:
422
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
423
   2. An f_number has already been inserted in the block:
424
      NCE_MULTIPLE_F_WORDS_ON_ONE_LINE
425
   3. The f_number is negative: NCE_NEGATIVE_F_WORD_USED
426
427
Side effects:
428
   counter is reset to point to the first character following the f_number.
429
   The f_number is inserted in block and the f_flag is set.
430
431
Called by: read_one_item
432
433
When this function is called, counter is pointing at an item on the
434
line that starts with the character 'f'. The function reads characters
435
which tell how to set the f_number, up to the start of the next item
436
or the end of the line. This information is inserted in the block.
437
438
The value may be a real number or something that evaluates to a real
439
number, so read_real_value is used to read it. Parameters may be
440
involved, so the parameters argument is required. The value is always
441
a feed rate.
442
443
*/
444
445
586
int Interp::read_f(char *line,   //!< string: line of RS274 code being processed
446
                  int *counter, //!< pointer to a counter for position on the line
447
                  block_pointer block,  //!< pointer to a block being filled from the line
448
                  double *parameters)   //!< array of system parameters
449
{
450
  double value;
451
452
586
  CHKS((line[*counter] != 'f'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
453
586
  *counter = (*counter + 1);
454
586
  CHKS((block->f_flag), NCE_MULTIPLE_F_WORDS_ON_ONE_LINE);
455
586
  CHP(read_real_value(line, counter, &value, parameters));
456
586
  CHKS((value < 0.0), NCE_NEGATIVE_F_WORD_USED);
457
586
  block->f_number = value;
458
586
  block->f_flag = true;
459
586
  return INTERP_OK;
460
}
461
462
/****************************************************************************/
463
464
/*! read_g
465
466
Returned Value: int
467
   If read_real_value returns an error code, this returns that code.
468
   If any of the following errors occur, this returns the error code shown.
469
   Otherwise, it returns INTERP_OK.
470
   1. The first character read is not g:
471
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
472
   2. The value is negative: NCE_NEGATIVE_G_CODE_USED
473
   3. The value differs from a number ending in an even tenth by more
474
      than 0.0001: NCE_G_CODE_OUT_OF_RANGE
475
   4. The value is greater than 99.9: NCE_G_CODE_OUT_OF_RANGE
476
   5. The value is not the number of a valid g code: NCE_UNKNOWN_G_CODE_USED
477
   6. Another g code from the same modal group has already been
478
      inserted in the block: NCE_TWO_G_CODES_USED_FROM_SAME_MODAL_GROUP
479
480
Side effects:
481
   counter is reset to the character following the end of the g_code.
482
   A g code is inserted as the value of the appropriate mode in the
483
   g_modes array in the block.
484
   The g code counter in the block is increased by 1.
485
486
Called by: read_one_item
487
488
When this function is called, counter is pointing at an item on the
489
line that starts with the character 'g', indicating a g_code.  The
490
function reads characters which tell how to set the g_code.
491
492
The RS274/NGC manual [NCMS, page 51] allows g_codes to be represented
493
by expressions and provide [NCMS, 71 - 73] that a g_code must evaluate
494
to to a number of the form XX.X (59.1, for example). The manual does not
495
say how close an expression must come to one of the allowed values for
496
it to be legitimate. Is 59.099999 allowed to mean 59.1, for example?
497
In the interpreter, we adopt the convention that the evaluated number
498
for the g_code must be within 0.0001 of a value of the form XX.X
499
500
To simplify the handling of g_codes, we convert them to integers by
501
multiplying by 10 and rounding down or up if within 0.001 of an
502
integer. Other functions that deal with g_codes handle them
503
symbolically, however. The symbols are defined in rs274NGC.hh
504
where G_1 is 10, G_83 is 830, etc.
505
506
This allows any number of g_codes on one line, provided that no two
507
are in the same modal group.
508
509
This allows G80 on the same line as one other g_code with the same
510
mode. If this happens, the G80 is simply ignored.
511
512
*/
513
514
1995
int Interp::read_g(char *line,   //!< string: line of RS274/NGC code being processed
515
                  int *counter, //!< pointer to a counter for position on the line
516
                  block_pointer block,  //!< pointer to a block being filled from the line
517
                  double *parameters)   //!< array of system parameters
518
{
519
  double value_read;
520
  int value;
521
  int mode;
522
523
1995
  CHKS((line[*counter] != 'g'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
524
1995
  *counter = (*counter + 1);
525
1995
  CHP(read_real_value(line, counter, &value_read, parameters));
526
1995
  value_read = (10.0 * value_read);
527
1995
  value = (int) floor(value_read);
528
529
1995
  if ((value_read - value) > 0.999)
530
    value = (int) ceil(value_read);
531
1995
  else if ((value_read - value) > 0.001)
532
    ERS(NCE_G_CODE_OUT_OF_RANGE);
533
534
1995
  CHKS((value > 999), NCE_G_CODE_OUT_OF_RANGE);
535
1995
  CHKS((value < 0), NCE_NEGATIVE_G_CODE_USED);
536
  // mode = usercode_mgroup(&(_setup),value);
537
  // if (mode != -1) {
538
539
1995
 remap_pointer r = _setup.g_remapped[value];
540
1995
  if (r) {
541
      mode =  r->modal_group;
542
      CHKS ((mode < 0),"BUG: G remapping: modal group < 0"); // real bad
543
544
      CHKS((block->g_modes[mode] != -1),
545
	   NCE_TWO_G_CODES_USED_FROM_SAME_MODAL_GROUP);
546
      block->g_modes[mode] = value;
547
      return INTERP_OK;
548
  }
549
1995
  mode = _gees[value];
550
1995
  CHKS((mode == -1), NCE_UNKNOWN_G_CODE_USED);
551
1995
  if ((value == G_80) && (block->g_modes[mode] != -1));
552
  else {
553
1995
    if (block->g_modes[mode] == G_80);
554
    else {
555
1995
      CHKS((block->g_modes[mode] != -1),
556
          NCE_TWO_G_CODES_USED_FROM_SAME_MODAL_GROUP);
557
    }
558
1995
    block->g_modes[mode] = value;
559
  }
560
  return INTERP_OK;
561
}
562
563
/****************************************************************************/
564
565
/*! read_h
566
567
Returned Value: int
568
   If read_integer_value returns an error code, this returns that code.
569
   If any of the following errors occur, this returns the error code shown.
570
   Otherwise, it returns INTERP_OK.
571
   1. The first character read is not h:
572
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
573
   2. An h_number has already been inserted in the block:
574
      NCE_MULTIPLE_H_WORDS_ON_ONE_LINE
575
   3. The value is negative: NCE_NEGATIVE_H_WORD_TOOL_LENGTH_OFFSET_INDEX_USED
576
   4. The value is greater than _setup.tool_max:
577
      NCE_TOOL_LENGTH_OFFSET_INDEX_TOO_BIG
578
579
Side effects:
580
   counter is reset to the character following the h_number.
581
   An h_number is inserted in the block.
582
583
Called by: read_one_item
584
585
When this function is called, counter is pointing at an item on the
586
line that starts with the character 'h', indicating a tool length
587
offset index.  The function reads characters which give the (integer)
588
value of the tool length offset index (not the actual distance of the
589
offset).
590
591
*/
592
593
1
int Interp::read_h(char *line,   //!< string: line of RS274/NGC code being processed
594
                  int *counter, //!< pointer to a counter for position on the line
595
                  block_pointer block,  //!< pointer to a block being filled from the line
596
                  double *parameters)   //!< array of system parameters
597
{
598
  int value;
599
600
1
  CHKS((line[*counter] != 'h'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
601
1
  *counter = (*counter + 1);
602
1
  CHKS((block->h_flag), NCE_MULTIPLE_H_WORDS_ON_ONE_LINE);
603
1
  CHP(read_integer_value(line, counter, &value, parameters));
604
1
  CHKS((value < -1), NCE_NEGATIVE_H_WORD_USED);
605
1
  block->h_flag = true;
606
1
  block->h_number = value;
607
1
  return INTERP_OK;
608
}
609
610
/****************************************************************************/
611
612
/*! read_i
613
614
Returned Value: int
615
   If read_real_value returns an error code, this returns that code.
616
   If any of the following errors occur, this returns the error code shown.
617
   Otherwise, it returns INTERP_OK.
618
   1. The first character read is not i:
619
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
620
   2. An i_coordinate has already been inserted in the block:
621
      NCE_MULTIPLE_I_WORDS_ON_ONE_LINE
622
623
Side effects:
624
   counter is reset.
625
   The i_flag in the block is turned on.
626
   An i_coordinate setting is inserted in the block.
627
628
Called by: read_one_item
629
630
When this function is called, counter is pointing at an item on the
631
line that starts with the character 'i', indicating a i_coordinate
632
setting. The function reads characters which tell how to set the
633
coordinate, up to the start of the next item or the end of the line.
634
This information is inserted in the block. The counter is then set to
635
point to the character following.
636
637
The value may be a real number or something that evaluates to a
638
real number, so read_real_value is used to read it. Parameters
639
may be involved.
640
641
*/
642
643
399
int Interp::read_i(char *line,   //!< string: line of RS274 code being processed
644
                  int *counter, //!< pointer to a counter for position on the line
645
                  block_pointer block,  //!< pointer to a block being filled from the line
646
                  double *parameters)   //!< array of system parameters
647
{
648
  double value;
649
650
399
  CHKS((line[*counter] != 'i'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
651
399
  *counter = (*counter + 1);
652
399
  CHKS((block->i_flag), NCE_MULTIPLE_I_WORDS_ON_ONE_LINE);
653
399
  CHP(read_real_value(line, counter, &value, parameters));
654
399
  block->i_flag = true;
655
399
  block->i_number = value;
656
399
  return INTERP_OK;
657
}
658
659
/****************************************************************************/
660
661
/*! read_integer_unsigned
662
663
Returned Value: int
664
   If any of the following errors occur, this returns the error shown.
665
   Otherwise, INTERP_OK is returned.
666
   1. The first character is not a digit: NCE_BAD_FORMAT_UNSIGNED_INTEGER
667
   2. sscanf fails: NCE_SSCANF_FAILED
668
669
Side effects:
670
   The number read from the line is put into what integer_ptr points at.
671
672
Called by: read_n_number
673
674
This reads an explicit unsigned (positive) integer from a string,
675
starting from the position given by *counter. It expects to find one
676
or more digits. Any character other than a digit terminates reading
677
the integer. Note that if the first character is a sign (+ or -),
678
an error will be reported (since a sign is not a digit).
679
680
*/
681
682
3
int Interp::read_integer_unsigned(char *line,    //!< string: line of RS274 code being processed
683
                                 int *counter,  //!< pointer to a counter for position on the line
684
                                 int *integer_ptr)      //!< pointer to the value being read
685
{
686
  int n;
687
  char c;
688
689
14
  for (n = *counter;; n++) {
690
14
    c = line[n];
691
14
    if ((c < 48) || (c > 57))
692
      break;
693
  }
694
3
  CHKS((n == *counter), NCE_BAD_FORMAT_UNSIGNED_INTEGER);
695
3
  if (sscanf(line + *counter, "%d", integer_ptr) == 0)
696
    ERS(NCE_SSCANF_FAILED);
697
3
  *counter = n;
698
14
  return INTERP_OK;
699
}
700
701
/****************************************************************************/
702
703
/*! read_integer_value
704
705
Returned Value: int
706
   If read_real_value returns an error code, this returns that code.
707
   If any of the following errors occur, this returns the error code shown.
708
   Otherwise, it returns INTERP_OK.
709
   1. The returned value is not close to an integer:
710
      NCE_NON_INTEGER_VALUE_FOR_INTEGER
711
712
Side effects:
713
   The number read from the line is put into what integer_ptr points at.
714
715
Called by:
716
   read_d
717
   read_l
718
   read_h
719
   read_m
720
   read_parameter
721
   read_parameter_setting
722
   read_t
723
724
This reads an integer (positive, negative or zero) from a string,
725
starting from the position given by *counter. The value being
726
read may be written with a decimal point or it may be an expression
727
involving non-integers, as long as the result comes out within 0.0001
728
of an integer.
729
730
This proceeds by calling read_real_value and checking that it is
731
close to an integer, then returning the integer it is close to.
732
733
*/
734
735
5012
int Interp::read_integer_value(char *line,       //!< string: line of RS274/NGC code being processed
736
                              int *counter,     //!< pointer to a counter for position on the line
737
                              int *integer_ptr, //!< pointer to the value being read
738
                              double *parameters)       //!< array of system parameters
739
{
740
  double float_value;
741
742
5012
  CHP(read_real_value(line, counter, &float_value, parameters));
743
5009
  *integer_ptr = (int) floor(float_value);
744
5009
  if ((float_value - *integer_ptr) > 0.9999) {
745
    *integer_ptr = (int) ceil(float_value);
746
5009
  } else if ((float_value - *integer_ptr) > 0.0001)
747
    ERS(NCE_NON_INTEGER_VALUE_FOR_INTEGER);
748
  return INTERP_OK;
749
}
750
751
/****************************************************************************/
752
753
/*! read_items
754
755
Returned Value: int
756
   If read_n_number or read_one_item returns an error code,
757
   this returns that code.
758
   Otherwise, it returns INTERP_OK.
759
760
Side effects:
761
   One line of RS274 code is read and data inserted into a block.
762
   The counter which is passed around among the readers is initialized.
763
   System parameters may be reset.
764
765
Called by: parse_line
766
767
*/
768
769
9455
int Interp::read_items(block_pointer block,      //!< pointer to a block being filled from the line
770
                      char *line,       //!< string: line of RS274/NGC code being processed
771
                      double *parameters)   //!< array of system parameters
772
{
773
  int counter;
774
  int length;
775
776
9455
  length = strlen(line);
777
9455
  counter = 0;
778
779
9455
  if (line[counter] == '/')     /* skip the slash character if first */
780
    counter++;
781
782
9455
  if (line[counter] == 'n') {
783
2
    CHP(read_n_number(line, &counter, block));
784
  }
785
786
9455
  if (line[counter] == 'o')
787
 /* Handle 'o' explicitly here. Default is
788
    to read letters via pointer calls to related
789
    reader functions. 'o' control lines have their
790
    own commands and command handlers. */
791
  {
792
3249
      CHP(read_o(line, &counter, block, parameters));
793
794
      // if skipping, the conditionals are not evaluated and are therefore unconsumed
795
      // so we can't check the rest of the line.  but don't worry, we'll get it later
796
3249
      if(_setup.skipping_o) return INTERP_OK;
797
798
      // after if [...], etc., nothing is allowed except comments
799
2322
      for (; counter < length;) {
800
282
          if(line[counter] == ';') read_semicolon(line, &counter, block, parameters);
801
282
          else if (line[counter] == '(') read_comment(line, &counter, block, parameters);
802
          else ERS("Unexpected character after O-word");
803
      }
804
      return INTERP_OK;
805
  }
806
807
  // non O-lines
808
809
6206
  if(_setup.skipping_o)
810
  {
811
      // if we are skipping, do NOT evaluate non-olines
812
      return INTERP_OK;
813
  }
814
815
14547
  for (; counter < length;) {
816
10033
    CHP(read_one_item(line, &counter, block, parameters));
817
  }
818
  return INTERP_OK;
819
}
820
821
/****************************************************************************/
822
823
/*! read_j
824
825
Returned Value: int
826
   If read_real_value returns an error code, this returns that code.
827
   If any of the following errors occur, this returns the error code shown.
828
   Otherwise, it returns INTERP_OK.
829
   1. The first character read is not j:
830
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
831
   2. A j_coordinate has already been inserted in the block.
832
      NCE_MULTIPLE_J_WORDS_ON_ONE_LINE
833
834
Side effects:
835
   counter is reset.
836
   The j_flag in the block is turned on.
837
   A j_coordinate setting is inserted in the block.
838
839
Called by: read_one_item
840
841
When this function is called, counter is pointing at an item on the
842
line that starts with the character 'j', indicating a j_coordinate
843
setting. The function reads characters which tell how to set the
844
coordinate, up to the start of the next item or the end of the line.
845
This information is inserted in the block. The counter is then set to
846
point to the character following.
847
848
The value may be a real number or something that evaluates to a real
849
number, so read_real_value is used to read it. Parameters may be
850
involved.
851
852
*/
853
854
455
int Interp::read_j(char *line,   //!< string: line of RS274 code being processed
855
                  int *counter, //!< pointer to a counter for position on the line
856
                  block_pointer block,  //!< pointer to a block being filled from the line
857
                  double *parameters)   //!< array of system parameters
858
{
859
  double value;
860
861
455
  CHKS((line[*counter] != 'j'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
862
455
  *counter = (*counter + 1);
863
455
  CHKS((block->j_flag), NCE_MULTIPLE_J_WORDS_ON_ONE_LINE);
864
455
  CHP(read_real_value(line, counter, &value, parameters));
865
455
  block->j_flag = true;
866
455
  block->j_number = value;
867
455
  return INTERP_OK;
868
}
869
870
/****************************************************************************/
871
872
/*! read_k
873
874
Returned Value: int
875
   If read_real_value returns an error code, this returns that code.
876
   If any of the following errors occur, this returns the error code shown.
877
   Otherwise, it returns INTERP_OK.
878
   1. The first character read is not k:
879
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
880
   2. A k_coordinate has already been inserted in the block:
881
      NCE_MULTIPLE_K_WORDS_ON_ONE_LINE
882
883
Side effects:
884
   counter is reset.
885
   The k_flag in the block is turned on.
886
   A k_coordinate setting is inserted in the block.
887
888
Called by: read_one_item
889
890
When this function is called, counter is pointing at an item on the
891
line that starts with the character 'k', indicating a k_coordinate
892
setting. The function reads characters which tell how to set the
893
coordinate, up to the start of the next item or the end of the line.
894
This information is inserted in the block. The counter is then set to
895
point to the character following.
896
897
The value may be a real number or something that evaluates to a real
898
number, so read_real_value is used to read it. Parameters may be
899
involved.
900
901
*/
902
903
70
int Interp::read_k(char *line,   //!< string: line of RS274 code being processed
904
                  int *counter, //!< pointer to a counter for position on the line
905
                  block_pointer block,  //!< pointer to a block being filled from the line
906
                  double *parameters)   //!< array of system parameters
907
{
908
  double value;
909
910
70
  CHKS((line[*counter] != 'k'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
911
70
  *counter = (*counter + 1);
912
70
  CHKS((block->k_flag), NCE_MULTIPLE_K_WORDS_ON_ONE_LINE);
913
70
  CHP(read_real_value(line, counter, &value, parameters));
914
70
  block->k_flag = true;
915
70
  block->k_number = value;
916
70
  return INTERP_OK;
917
}
918
919
/****************************************************************************/
920
921
/*! read_l
922
923
Returned Value: int
924
   If read_integer_value returns an error code, this returns that code.
925
   If any of the following errors occur, this returns the error code shown.
926
   Otherwise, it returns INTERP_OK.
927
   1. The first character read is not l:
928
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
929
   2. An l_number has already been inserted in the block:
930
      NCE_MULTIPLE_L_WORDS_ON_ONE_LINE
931
   3. the l_number is negative: NCE_NEGATIVE_L_WORD_USED
932
933
Side effects:
934
   counter is reset to the character following the l number.
935
   An l code is inserted in the block as the value of l.
936
937
Called by: read_one_item
938
939
When this function is called, counter is pointing at an item on the
940
line that starts with the character 'l', indicating an L code.
941
The function reads characters which give the (integer) value of the
942
L code.
943
944
L codes are used for:
945
1. the number of times a canned cycle should be repeated.
946
2. a key with G10.
947
948
*/
949
950
78
int Interp::read_l(char *line,   //!< string: line of RS274/NGC code being processed
951
                  int *counter, //!< pointer to a counter for position on the line
952
                  block_pointer block,  //!< pointer to a block being filled from the line
953
                  double *parameters)   //!< array of system parameters
954
{
955
  int value;
956
957
78
  CHKS((line[*counter] != 'l'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
958
78
  *counter = (*counter + 1);
959
78
  CHKS((block->l_number > -1), NCE_MULTIPLE_L_WORDS_ON_ONE_LINE);
960
78
  CHP(read_integer_value(line, counter, &value, parameters));
961
78
  CHKS((value < 0), NCE_NEGATIVE_L_WORD_USED);
962
78
  block->l_number = value;
963
78
  block->l_flag = true;
964
78
  return INTERP_OK;
965
}
966
967
/****************************************************************************/
968
969
/*! read_n_number
970
971
Returned Value: int
972
   If read_integer_unsigned returns an error code, this returns that code.
973
   If any of the following errors occur, this returns the error code shown.
974
   Otherwise, it returns INTERP_OK.
975
   1. The first character read is not n:
976
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
977
   2. The line number is too large (more than 99999):
978
      NCE_LINE_NUMBER_GREATER_THAN_99999
979
980
Side effects:
981
   counter is reset to the character following the line number.
982
   A line number is inserted in the block.
983
984
Called by: read_items
985
986
When this function is called, counter is pointing at an item on the
987
line that starts with the character 'n', indicating a line number.
988
The function reads characters which give the (integer) value of the
989
line number.
990
991
Note that extra initial zeros in a line number will not cause the
992
line number to be too large.
993
994
*/
995
996
2
int Interp::read_n_number(char *line, //!< string: line of RS274    code being processed
997
                          int *counter,       //!< pointer to a counter for position on the line
998
                          block_pointer block)        //!< pointer to a block being filled from the line
999
{
1000
  int value;
1001
1002
2
  CHKS(((line[*counter] != 'n') && (line[*counter] != 'o')),
1003
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1004
2
  *counter = (*counter + 1);
1005
2
  CHP(read_integer_unsigned(line, counter, &value));
1006
  /* This next test is problematic as many CAM systems will exceed this !
1007
  CHKS((value > 99999), NCE_LINE_NUMBER_GREATER_THAN_99999); */
1008
2
  block->n_number = value;
1009
1010
  // accept & ignore fractional line numbers
1011
2
  if (line[*counter] == '.') {
1012
1
      *counter = (*counter + 1);
1013
1
      CHP(read_integer_unsigned(line, counter, &value));
1014
  }
1015
  return INTERP_OK;
1016
}
1017
1018
/****************************************************************************/
1019
1020
/*! read_m
1021
1022
Returned Value:
1023
   If read_integer_value returns an error code, this returns that code.
1024
   If any of the following errors occur, this returns the error code shown.
1025
   Otherwise, it returns INTERP_OK.
1026
   1. The first character read is not m:
1027
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
1028
   2. The value is negative: NCE_NEGATIVE_M_CODE_USED
1029
   3. The value is greater than 199: NCE_M_CODE_GREATER_THAN_199
1030
   4. The m code is not known to the system: NCE_UNKNOWN_M_CODE_USED
1031
   5. Another m code in the same modal group has already been read:
1032
      NCE_TWO_M_CODES_USED_FROM_SAME_MODAL_GROUP
1033
1034
Side effects:
1035
   counter is reset to the character following the m number.
1036
   An m code is inserted as the value of the appropriate mode in the
1037
   m_modes array in the block.
1038
   The m code counter in the block is increased by 1.
1039
1040
Called by: read_one_item
1041
1042
When this function is called, counter is pointing at an item on the
1043
line that starts with the character 'm', indicating an m code.
1044
The function reads characters which give the (integer) value of the
1045
m code.
1046
1047
read_integer_value allows a minus sign, so a check for a negative value
1048
is needed here, and the parameters argument is also needed.
1049
1050
*/
1051
1052
67
int Interp::read_m(char *line,   //!< string: line of RS274 code being processed
1053
                  int *counter, //!< pointer to a counter for position on the line
1054
                  block_pointer block,  //!< pointer to a block being filled from the line
1055
                  double *parameters)   //!< array of system parameters
1056
{
1057
  int value;
1058
  int mode;
1059
1060
67
  CHKS((line[*counter] != 'm'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1061
67
  *counter = (*counter + 1);
1062
67
  CHP(read_integer_value(line, counter, &value, parameters));
1063
67
  CHKS((value < 0), NCE_NEGATIVE_M_CODE_USED);
1064
1065
67
  remap_pointer r = _setup.m_remapped[value];
1066
67
  if (r) {
1067
      mode =  r->modal_group;
1068
      CHKS ((mode < 0),"BUG: M remapping: modal group < 0");
1069
      CHKS ((mode > 10),"BUG: M remapping: modal group > 10");
1070
1071
      CHKS((block->m_modes[mode] != -1),
1072
	   NCE_TWO_M_CODES_USED_FROM_SAME_MODAL_GROUP);
1073
      block->m_modes[mode] = value;
1074
      block->m_count++;
1075
      return INTERP_OK;
1076
  }
1077
1078
67
  CHKS((value > 199), NCE_M_CODE_GREATER_THAN_199,value);
1079
67
  mode = _ems[value];
1080
67
  CHKS((mode == -1), NCE_UNKNOWN_M_CODE_USED,value);
1081
67
  CHKS((block->m_modes[mode] != -1),
1082
      NCE_TWO_M_CODES_USED_FROM_SAME_MODAL_GROUP);
1083
67
  block->m_modes[mode] = value;
1084
67
  block->m_count++;
1085
67
  if (value >= 100 && value < 200) {
1086
    block->user_m = 1;
1087
  }
1088
  return INTERP_OK;
1089
}
1090
1091
/****************************************************************************/
1092
1093
/*! read_one_item
1094
1095
Returned Value: int
1096
   If a reader function which is called returns an error code, that
1097
   error code is returned.
1098
   If any of the following errors occur, this returns the error code shown.
1099
   Otherwise, it returns INTERP_OK.
1100
   1. the first character read is not a known character for starting a
1101
   word: NCE_BAD_CHARACTER_USED
1102
1103
Side effects:
1104
   This function reads one item from a line of RS274/NGC code and inserts
1105
   the information in a block. System parameters may be reset.
1106
1107
Called by: read_items.
1108
1109
When this function is called, the counter is set so that the position
1110
being considered is the first position of a word. The character at
1111
that position must be one known to the system.  In this version those
1112
characters are: a,b,c,d,f,g,h,i,j,k,l,m,n,p,q,r,s,t,x,y,z,(,#,;.
1113
However, read_items calls read_n_number directly if the first word
1114
begins with n, so no read function is included in the "_readers" array
1115
for the letter n. Thus, if an n word is encountered in the middle of
1116
a line, this function reports NCE_BAD_CHARACTER_USED.
1117
1118
The function looks for a letter or special character and matches it to
1119
a pointer to a function in _readers[] - The position of the function
1120
pointers in the array match their ASCII number.
1121
Once the character has been matched, the function calls a selected function
1122
according to what the letter or character is.  The selected function will
1123
be responsible to consider all the characters that comprise the remainder
1124
of the item, and reset the pointer so that it points to the next character
1125
after the end of the item (which may be the end of the line or the first
1126
character of another item).
1127
1128
After an item is read, the counter is set at the index of the
1129
next unread character. The item data is stored in the block.
1130
1131
It is expected that the format of a comment will have been checked;
1132
this is being done by close_and_downcase. Bad format comments will
1133
have prevented the system from getting this far, so that this function
1134
can assume a close parenthesis will be found when an open parenthesis
1135
has been found, and that comments are not nested.
1136
1137
*/
1138
1139
10033
int Interp::read_one_item(
1140
    char *line,    //!< string: line of RS274/NGC code being processed
1141
    int *counter,  //!< pointer to a counter for position on the line
1142
    block_pointer block,   //!< pointer to a block being filled from the line
1143
    double * parameters) /* array of system parameters  */
1144
{
1145
  read_function_pointer function_pointer;
1146
  char letter;
1147
1148
10033
  letter = line[*counter];      /* check if in array range */
1149
10033
  CHKS(((letter < ' ') || (letter > 'z')),
1150
	_("Bad character '\\%03o' used"), (unsigned char)letter);
1151
10033
  function_pointer = _readers[(int) letter]; /* Find the function pointer in the array */
1152
10033
  CHKS((function_pointer == 0),
1153
	(!isprint(letter) || isspace(letter)) ?
1154
	    _("Bad character '\\%03o' used") : _("Bad character '%c' used"), letter);
1155
10033
  CHP((*this.*function_pointer)(line, counter, block, parameters)); /* Call the function */
1156
  return INTERP_OK;
1157
}
1158
1159
/****************************************************************************/
1160
1161
/*! read_operation
1162
1163
Returned Value: int
1164
   If any of the following errors occur, this returns the error code shown.
1165
   Otherwise, it returns INTERP_OK.
1166
   1. The operation is unknown:
1167
      NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_A
1168
      NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_M
1169
      NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_O
1170
      NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_X
1171
      NCE_UNKNOWN_OPERATION
1172
   2. The line ends without closing the expression: NCE_UNCLOSED_EXPRESSION
1173
1174
Side effects:
1175
   An integer representing the operation is put into what operation points
1176
   at.  The counter is reset to point to the first character after the
1177
   operation.
1178
1179
Called by: read_real_expression
1180
1181
This expects to be reading a binary operation (+, -, /, *, **, and,
1182
mod, or, xor) or a right bracket (]). If one of these is found, the
1183
value of operation is set to the symbolic value for that operation.
1184
If not, an error is reported as described above.
1185
1186
*/
1187
1188
7844
int Interp::read_operation(char *line,   //!< string: line of RS274/NGC code being processed
1189
                          int *counter, //!< pointer to a counter for position on the line
1190
                          int *operation)       //!< pointer to operation to be read
1191
{
1192
  char c;
1193
1194
7844
  c = line[*counter];
1195
7844
  *counter = (*counter + 1);
1196
7844
  switch (c) {
1197
  case '+':
1198
640
    *operation = PLUS;
1199
640
    break;
1200
  case '-':
1201
1126
    *operation = MINUS;
1202
1126
    break;
1203
  case '/':
1204
582
    *operation = DIVIDED_BY;
1205
582
    break;
1206
  case '*':
1207
490
    if (line[*counter] == '*') {
1208
      *operation = POWER;
1209
      *counter = (*counter + 1);
1210
    } else
1211
490
      *operation = TIMES;
1212
    break;
1213
  case ']':
1214
4509
    *operation = RIGHT_BRACKET;
1215
4509
    break;
1216
  case 'a':
1217
    if ((line[*counter] == 'n') && (line[(*counter) + 1] == 'd')) {
1218
      *operation = AND2;
1219
      *counter = (*counter + 2);
1220
    } else
1221
      ERS(NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_A);
1222
    break;
1223
  case 'm':
1224
    if ((line[*counter] == 'o') && (line[(*counter) + 1] == 'd')) {
1225
      *operation = MODULO;
1226
      *counter = (*counter + 2);
1227
    } else
1228
      ERS(NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_M);
1229
    break;
1230
  case 'o':
1231
    if (line[*counter] == 'r') {
1232
      *operation = NON_EXCLUSIVE_OR;
1233
      *counter = (*counter + 1);
1234
    } else
1235
      ERS(NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_O);
1236
    break;
1237
  case 'x':
1238
    if ((line[*counter] == 'o') && (line[(*counter) + 1] == 'r')) {
1239
      *operation = EXCLUSIVE_OR;
1240
      *counter = (*counter + 2);
1241
    } else
1242
      ERS(NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_X);
1243
    break;
1244
1245
      /* relational operators */
1246
    case 'e':
1247
276
      if(line[*counter] == 'q')
1248
	{
1249
276
	  *operation = EQ;
1250
276
	  *counter = (*counter + 1);
1251
	}
1252
      else
1253
        ERS(NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_E);
1254
276
      break;
1255
    case 'n':
1256
117
      if(line[*counter] == 'e')
1257
	{
1258
117
	  *operation = NE;
1259
117
	  *counter = (*counter + 1);
1260
	}
1261
      else
1262
        ERS(NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_N);
1263
117
      break;
1264
    case 'g':
1265
5
      if(line[*counter] == 'e')
1266
	{
1267
	  *operation = GE;
1268
	  *counter = (*counter + 1);
1269
	}
1270
5
      else if(line[*counter] == 't')
1271
	{
1272
5
	  *operation = GT;
1273
5
	  *counter = (*counter + 1);
1274
	}
1275
      else
1276
        ERS(NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_G);
1277
      break;
1278
    case 'l':
1279
99
      if(line[*counter] == 'e')
1280
	{
1281
73
	  *operation = LE;
1282
73
	  *counter = (*counter + 1);
1283
	}
1284
26
      else if(line[*counter] == 't')
1285
	{
1286
26
	  *operation = LT;
1287
26
	  *counter = (*counter + 1);
1288
	}
1289
      else
1290
        ERS(NCE_UNKNOWN_OPERATION_NAME_STARTING_WITH_L);
1291
      break;
1292
1293
  case 0:
1294
    ERS(NCE_UNCLOSED_EXPRESSION);
1295
  default:
1296
    ERS(NCE_UNKNOWN_OPERATION);
1297
  }
1298
  return INTERP_OK;
1299
}
1300
1301
/****************************************************************************/
1302
1303
/*! read_operation_unary
1304
1305
Returned Value: int
1306
   If the operation is not a known unary operation, this returns one of
1307
   the following error codes:
1308
   NCE_UNKNOWN_WORD_STARTING_WITH_A
1309
   NCE_UNKNOWN_WORD_STARTING_WITH_C
1310
   NCE_UNKNOWN_WORD_STARTING_WITH_E
1311
   NCE_UNKNOWN_WORD_STARTING_WITH_F
1312
   NCE_UNKNOWN_WORD_STARTING_WITH_L
1313
   NCE_UNKNOWN_WORD_STARTING_WITH_R
1314
   NCE_UNKNOWN_WORD_STARTING_WITH_S
1315
   NCE_UNKNOWN_WORD_STARTING_WITH_T
1316
   NCE_UNKNOWN_WORD_WHERE_UNARY_OPERATION_COULD_BE
1317
   Otherwise, this returns INTERP_OK.
1318
1319
Side effects:
1320
   An integer code for the name of the operation read from the
1321
   line is put into what operation points at.
1322
   The counter is reset to point to the first character after the
1323
   characters which make up the operation name.
1324
1325
Called by:
1326
   read_unary
1327
1328
This attempts to read the name of a unary operation out of the line,
1329
starting at the index given by the counter. Known operations are:
1330
abs, acos, asin, atan, cos, exp, fix, fup, ln, round, sin, sqrt, tan.
1331
1332
*/
1333
1334
322
int Interp::read_operation_unary(char *line,     //!< string: line of RS274/NGC code being processed
1335
                                int *counter,   //!< pointer to a counter for position on the line
1336
                                int *operation) //!< pointer to operation to be read
1337
{
1338
  char c;
1339
1340
322
  c = line[*counter];
1341
322
  *counter = (*counter + 1);
1342
322
  switch (c) {
1343
  case 'a':
1344
21
    if ((line[*counter] == 'b') && (line[(*counter) + 1] == 's')) {
1345
      *operation = ABS;
1346
      *counter = (*counter + 2);
1347
21
    } else if (strncmp((line + *counter), "cos", 3) == 0) {
1348
      *operation = ACOS;
1349
      *counter = (*counter + 3);
1350
21
    } else if (strncmp((line + *counter), "sin", 3) == 0) {
1351
21
      *operation = ASIN;
1352
21
      *counter = (*counter + 3);
1353
    } else if (strncmp((line + *counter), "tan", 3) == 0) {
1354
      *operation = ATAN;
1355
      *counter = (*counter + 3);
1356
    } else
1357
      ERS(NCE_UNKNOWN_WORD_STARTING_WITH_A);
1358
    break;
1359
  case 'c':
1360
84
    if ((line[*counter] == 'o') && (line[(*counter) + 1] == 's')) {
1361
84
      *operation = COS;
1362
84
      *counter = (*counter + 2);
1363
    } else
1364
      ERS(NCE_UNKNOWN_WORD_STARTING_WITH_C);
1365
84
    break;
1366
  case 'e':
1367
14
    if ((line[*counter] == 'x') && (line[(*counter) + 1] == 'p')) {
1368
      *operation = EXP;
1369
      *counter = (*counter + 2);
1370
14
    } else if (    (line[*counter]     == 'x')
1371
14
                && (line[*counter + 1] == 'i')
1372
14
                && (line[*counter + 2] == 's')
1373
14
                && (line[*counter + 3] == 't')
1374
14
                && (line[*counter + 4] == 's')
1375
             ) {
1376
14
      *counter = (*counter + 5);
1377
14
      *operation = EXISTS;
1378
    } else {
1379
      ERS(NCE_UNKNOWN_WORD_STARTING_WITH_E);
1380
    }
1381
    break;
1382
  case 'f':
1383
5
    if ((line[*counter] == 'i') && (line[(*counter) + 1] == 'x')) {
1384
      *operation = FIX;
1385
      *counter = (*counter + 2);
1386
5
    } else if ((line[*counter] == 'u') && (line[(*counter) + 1] == 'p')) {
1387
4
      *operation = FUP;
1388
4
      *counter = (*counter + 2);
1389
    } else
1390
1
      ERS(NCE_UNKNOWN_WORD_STARTING_WITH_F);
1391
    break;
1392
  case 'l':
1393
    if (line[*counter] == 'n') {
1394
      *operation = LN;
1395
      *counter = (*counter + 1);
1396
    } else
1397
      ERS(NCE_UNKNOWN_WORD_STARTING_WITH_L);
1398
    break;
1399
  case 'r':
1400
    if (strncmp((line + *counter), "ound", 4) == 0) {
1401
      *operation = ROUND;
1402
      *counter = (*counter + 4);
1403
    } else
1404
      ERS(NCE_UNKNOWN_WORD_STARTING_WITH_R);
1405
    break;
1406
  case 's':
1407
198
    if ((line[*counter] == 'i') && (line[(*counter) + 1] == 'n')) {
1408
63
      *operation = SIN;
1409
63
      *counter = (*counter + 2);
1410
135
    } else if (strncmp((line + *counter), "qrt", 3) == 0) {
1411
135
      *operation = SQRT;
1412
135
      *counter = (*counter + 3);
1413
    } else
1414
      ERS(NCE_UNKNOWN_WORD_STARTING_WITH_S);
1415
    break;
1416
  case 't':
1417
    if ((line[*counter] == 'a') && (line[(*counter) + 1] == 'n')) {
1418
      *operation = TAN;
1419
      *counter = (*counter + 2);
1420
    } else
1421
      ERS(NCE_UNKNOWN_WORD_STARTING_WITH_T);
1422
    break;
1423
  default:
1424
    ERS(NCE_UNKNOWN_WORD_WHERE_UNARY_OPERATION_COULD_BE);
1425
  }
1426
  return INTERP_OK;
1427
}
1428
1429
/****************************************************************************/
1430
1431
/* read_o
1432
1433
Returned Value: int
1434
   If read_real_value returns an error code, this returns that code.
1435
   If any of the following errors occur, this returns the error code shown.
1436
   Otherwise, it returns RS274NGC_OK.
1437
   1. The first character read is not o:
1438
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
1439
1440
Side effects:
1441
   counter is reset to point to the first character following the p value.
1442
   The p value setting is inserted in block.
1443
1444
Called by: read_one_item
1445
1446
When this function is called, counter is pointing at an item on the
1447
line that starts with the character 'o', indicating a o value
1448
setting. The function reads characters which tell how to set the o
1449
value, up to the start of the next item or the end of the line. This
1450
information is inserted in the block.
1451
1452
O codes are used for:
1453
1.  sub
1454
2.  endsub
1455
3.  call
1456
4.  do
1457
5.  while
1458
6.  if
1459
7.  elseif
1460
8.  else
1461
9.  endif
1462
10. break
1463
11. continue
1464
12. endwhile
1465
13. return
1466
1467
Labels (o-words) are of local scope except for sub, endsub, and call which
1468
are of global scope.
1469
1470
Named o-words and scoping of o-words are implemented now.
1471
Numeric o-words get converted to strings. Global o-words are stored as
1472
just the string. Local o-words are stored as the name (o-word) of the
1473
sub containing the o-word, followed by a '#', followed by the local o-word.
1474
If the local o-word is not contained within a sub, then the sub name is null
1475
and the o-word just begins with a '#'.
1476
1477
It has been a pain to do this because o-words are used as integers all over
1478
the place.
1479
!!!KL the code could use some cleanup.
1480
1481
*/
1482
1483
3249
int Interp::read_o(    /* ARGUMENTS                                     */
1484
 char * line,         /* string: line of RS274/NGC code being processed */
1485
 int * counter,       /* pointer to a counter for position on the line  */
1486
 block_pointer block, /* pointer to a block being filled from the line  */
1487
 double * parameters) /* array of system parameters                     */
1488
{
1489
  static char name[] = "read_o";
1490
  double value;
1491
  int param_cnt;
1492
  char oNameBuf[LINELEN+1];
1493
  const char *subName;
1494
  char fullNameBuf[2*LINELEN+1];
1495
  int oNumber;
1496
  extern const char *o_ops[];
1497
1498
3249
  CHKS((line[*counter] != 'o'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1499
1500
  // changed spec so we now read an expression
1501
  // so... we can have a parameter contain a function pointer!
1502
3249
  *counter += 1;
1503
1504
3249
  logDebug("In: %s line:%d |%s|", name, block->line_number, line);
1505
1506
3249
  if(line[*counter] == '<')
1507
  {
1508
2352
      read_name(line, counter, oNameBuf);
1509
  }
1510
  else
1511
  {
1512
897
     CHP(read_integer_value(line, counter, &oNumber,
1513
                            parameters));
1514
897
     sprintf(oNameBuf, "%d", oNumber);
1515
  }
1516
1517
  // We stash the text the offset part of setup
1518
1519
#define CMP(txt) (strncmp(line+*counter, txt, strlen(txt)) == 0 && (*counter += strlen(txt)))
1520
  // characterize the type of o-word
1521
1522
3249
  if(CMP("sub"))
1523
393
    block->o_type = O_sub;
1524
2856
  else if(CMP("endsub"))
1525
388
    block->o_type = O_endsub;
1526
2468
  else if(CMP("call"))
1527
1136
    block->o_type = O_call;
1528
1332
  else if(CMP("do"))
1529
75
    block->o_type = O_do;
1530
1257
  else if(CMP("while"))
1531
98
    block->o_type = O_while;
1532
1159
  else if(CMP("repeat"))
1533
    block->o_type = O_repeat;
1534
1159
  else if(CMP("if"))
1535
434
    block->o_type = O_if;
1536
725
  else if(CMP("elseif"))
1537
    block->o_type = O_elseif;
1538
725
  else if(CMP("else"))
1539
256
    block->o_type = O_else;
1540
469
  else if(CMP("endif"))
1541
431
    block->o_type = O_endif;
1542
38
  else if(CMP("break"))
1543
5
    block->o_type = O_break;
1544
33
  else if(CMP("continue"))
1545
    block->o_type = O_continue;
1546
33
  else if(CMP("endwhile"))
1547
22
    block->o_type = O_endwhile;
1548
11
  else if(CMP("endrepeat"))
1549
    block->o_type = O_endrepeat;
1550
11
  else if(CMP("return"))
1551
11
    block->o_type = O_return;
1552
  else
1553
    block->o_type = O_none;
1554
1555
  // we now have it characterized
1556
  // now create the text of the oword
1557
1558
3249
  switch(block->o_type)
1559
    {
1560
      // the global cases first
1561
    case O_sub:
1562
    case O_endsub:
1563
    case O_call:
1564
    case O_return:
1565
1928
	block->o_name = strstore(oNameBuf);
1566
1928
	logDebug("global case:|%s|", block->o_name);
1567
	break;
1568
1569
      // the remainder are local cases
1570
    default:
1571
1321
      if(_setup.call_level)
1572
	{
1573
936
	  subName = _setup.sub_context[_setup.call_level].subName;
1574
936
	  logDebug("inside a call[%d]:|%s|", _setup.call_level, subName);
1575
	}
1576
385
      else if(_setup.defining_sub)
1577
	{
1578
62
	  subName = _setup.sub_name;
1579
62
	  logDebug("defining_sub:|%s|", subName);
1580
	}
1581
      else
1582
	{
1583
323
	  subName = "";
1584
323
	  logDebug("not defining_sub:|%s|", subName);
1585
	}
1586
1321
      sprintf(fullNameBuf, "%s#%s", subName, oNameBuf);
1587
1321
      block->o_name = strstore(fullNameBuf);
1588
1321
      logDebug("local case:|%s|", block->o_name);
1589
    }
1590
3249
  logDebug("o_type:%s o_name: %s  line:%d %s", o_ops[block->o_type], block->o_name,
1591
	   block->line_number, line);
1592
1593
3249
  if (block->o_type == O_sub)
1594
    {
1595
393
      block->o_type = O_sub;
1596
    }
1597
  // in terms of execution endsub and return do the same thing
1598
2856
  else if ((block->o_type == O_endsub) || (block->o_type == O_return))
1599
    {
1600
444
	if ((_setup.skipping_o != 0) &&
1601
45
	    (0 != strcmp(_setup.skipping_o, block->o_name))) {
1602
	    return INTERP_OK;
1603
	}
1604
1605
	// optional return value expression
1606
392
	if (line[*counter] == '[') {
1607
6
	    CHP(read_real_expression(line, counter, &value, parameters));
1608
6
	    logOword("%s %s value %lf",
1609
		     (block->o_type == O_endsub) ? "endsub" : "return",
1610
		     block->o_name,
1611
		     value);
1612
6
	    _setup.return_value = value;
1613
6
	    _setup.value_returned = 1;
1614
	} else {
1615
386
	    _setup.return_value = 0;
1616
386
	    _setup.value_returned = 0;
1617
	}
1618
    }
1619
2457
  else if(_setup.defining_sub == 1)
1620
    {
1621
      // we can not evaluate expressions -- so just skip on out
1622
67
      block->o_type = O_none;
1623
    }
1624
2390
  else if(block->o_type == O_call)
1625
    {
1626
      // we need to NOT evaluate parameters if skipping
1627
      // skipping never ends on a "call"
1628
1131
      if(_setup.skipping_o != 0)
1629
      {
1630
768
          block->o_type = O_none;
1631
768
          return INTERP_OK;
1632
      }
1633
1634
      // convey starting state for call_fsm() to handle this call
1635
      // convert_remapped_code() might change this to CS_REMAP
1636
363
      block->call_type = is_pycallable(&_setup,  OWORD_MODULE, block->o_name) ?
1637
363
	  CT_PYTHON_OWORD_SUB : CT_NGC_OWORD_SUB;
1638
1639
2087
      for(param_cnt=0;(line[*counter] == '[') || (line[*counter] == '(');)
1640
	{
1641
1361
	  if(line[*counter] == '(')
1642
	    {
1643
1
	      CHP(read_comment(line, counter, block, parameters));
1644
	      continue;
1645
	    }
1646
1360
	  logDebug("counter[%d] rest of line:|%s|", *counter,
1647
		   line+*counter);
1648
1360
	  CHKS((param_cnt >= INTERP_SUB_PARAMS),
1649
	      NCE_TOO_MANY_SUBROUTINE_PARAMETERS);
1650
1360
	  CHP(read_real_expression(line, counter, &value, parameters));
1651
1360
	  block->params[param_cnt] = value;
1652
1360
	  param_cnt++;
1653
	}
1654
363
      logDebug("set arg params:%d", param_cnt);
1655
363
      block->param_cnt = param_cnt;
1656
1657
      // zero the remaining params
1658
9893
      for(;param_cnt < INTERP_SUB_PARAMS; param_cnt++)
1659
	{
1660
9530
	  block->params[param_cnt] = 0.0;
1661
	}
1662
    }
1663
1259
  else if(block->o_type == O_do)
1664
    {
1665
75
      block->o_type = O_do;
1666
    }
1667
1184
  else if(block->o_type == O_while)
1668
    {
1669
      // TESTME !!!KL -- should not eval expressions if skipping ???
1670
100
      if((_setup.skipping_o != 0) &&
1671
3
	 (0 != strcmp(_setup.skipping_o, block->o_name)))
1672
      {
1673
	    return INTERP_OK;
1674
      }
1675
1676
97
      block->o_type = O_while;
1677
97
      CHKS((line[*counter] != '['),
1678
	    _("Left bracket missing after 'while'"));
1679
97
      CHP(read_real_expression(line, counter, &value, parameters));
1680
97
      _setup.test_value = value;
1681
    }
1682
1087
  else if(block->o_type == O_repeat)
1683
      {
1684
          // TESTME !!!KL -- should not eval expressions if skipping ???
1685
          if((_setup.skipping_o != 0) &&
1686
	     (0 != strcmp(_setup.skipping_o, block->o_name)))
1687
          {
1688
	    return INTERP_OK;
1689
          }
1690
1691
          block->o_type = O_repeat;
1692
          CHKS((line[*counter] != '['),
1693
               _("Left bracket missing after 'repeat'"));
1694
          CHP(read_real_expression(line, counter, &value, parameters));
1695
          _setup.test_value = value;
1696
      }
1697
1087
  else if(block->o_type == O_if)
1698
    {
1699
      // TESTME !!!KL -- should not eval expressions if skipping ???
1700
405
      if((_setup.skipping_o != 0) &&
1701
	 (0 != strcmp(_setup.skipping_o, block->o_name)))
1702
      {
1703
	    return INTERP_OK;
1704
      }
1705
1706
405
      block->o_type = O_if;
1707
405
      CHKS((line[*counter] != '['),
1708
	    _("Left bracket missing after 'if'"));
1709
405
      CHP(read_real_expression(line, counter, &value, parameters));
1710
405
      _setup.test_value = value;
1711
    }
1712
682
  else if(block->o_type == O_elseif)
1713
    {
1714
      // TESTME !!!KL -- should not eval expressions if skipping ???
1715
      if((_setup.skipping_o != 0) &&
1716
	 (0 != strcmp(_setup.skipping_o, block->o_name)))
1717
      {
1718
	    return INTERP_OK;
1719
      }
1720
1721
      block->o_type = O_elseif;
1722
      CHKS((line[*counter] != '['),
1723
	    _("Left bracket missing after 'elseif'"));
1724
      CHP(read_real_expression(line, counter, &value, parameters));
1725
      _setup.test_value = value;
1726
    }
1727
682
  else if(block->o_type == O_else)
1728
    {
1729
255
      block->o_type = O_else;
1730
    }
1731
427
  else if(block->o_type == O_endif)
1732
    {
1733
402
      block->o_type = O_endif;
1734
    }
1735
25
  else if(block->o_type == O_break)
1736
    {
1737
4
      block->o_type = O_break;
1738
    }
1739
21
  else if(block->o_type == O_continue)
1740
    {
1741
      block->o_type = O_continue;
1742
    }
1743
21
  else if(block->o_type == O_endwhile)
1744
    {
1745
21
      block->o_type = O_endwhile;
1746
    }
1747
  else if(block->o_type == O_endrepeat)
1748
      {
1749
          block->o_type = O_endrepeat;
1750
      }
1751
  else
1752
    {
1753
      // not legal
1754
      block->o_type = O_none;
1755
      ERS(NCE_UNKNOWN_COMMAND_IN_O_LINE);
1756
    }
1757
1758
  return INTERP_OK;
1759
}
1760
1761
1762
/****************************************************************************/
1763
1764
/*! read_p
1765
1766
Returned Value: int
1767
   If read_real_value returns an error code, this returns that code.
1768
   If any of the following errors occur, this returns the error code shown.
1769
   Otherwise, it returns INTERP_OK.
1770
   1. The first character read is not p:
1771
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
1772
   2. A p value has already been inserted in the block:
1773
      NCE_MULTIPLE_P_WORDS_ON_ONE_LINE
1774
1775
Side effects:
1776
   counter is reset to point to the first character following the p value.
1777
   The p value setting is inserted in block.
1778
1779
Called by: read_one_item
1780
1781
When this function is called, counter is pointing at an item on the
1782
line that starts with the character 'p', indicating a p value
1783
setting. The function reads characters which tell how to set the p
1784
value, up to the start of the next item or the end of the line. This
1785
information is inserted in the block.
1786
1787
P codes are used for:
1788
1. Dwell time in canned cycles g82, G86, G88, G89 [NCMS pages 98 - 100].
1789
2. A key with G10 [NCMS, pages 9, 10].
1790
1791
*/
1792
1793
72
int Interp::read_p(char *line,   //!< string: line of RS274/NGC code being processed
1794
                  int *counter, //!< pointer to a counter for position on the line
1795
                  block_pointer block,  //!< pointer to a block being filled from the line
1796
                  double *parameters)   //!< array of system parameters
1797
{
1798
  double value;
1799
1800
72
  CHKS((line[*counter] != 'p'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1801
72
  *counter = (*counter + 1);
1802
72
  CHKS((block->p_number > -1.0), NCE_MULTIPLE_P_WORDS_ON_ONE_LINE);
1803
72
  CHP(read_real_value(line, counter, &value, parameters));
1804
  // FMP removed check for negatives, since we may want them for
1805
  // user-defined codes
1806
  // CHKS((value < 0.0), NCE_NEGATIVE_P_WORD_USED);
1807
72
  block->p_number = value;
1808
72
  block->p_flag = true;
1809
72
  return INTERP_OK;
1810
}
1811
1812
6959
int Interp::read_name(
1813
    char *line,   //!< string: line of RS274/NGC code being processed
1814
    int *counter, //!< pointer to a counter for position on the line
1815
    char *nameBuf)   //!< pointer to name to be read
1816
{
1817
1818
6959
  int done = 0;
1819
  int i;
1820
1821
6959
  CHKS(((line[*counter] != '<') && !isalpha(line[*(counter)])),
1822
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1823
1824
  // skip over the '<'
1825
6959
  *counter = (*counter + 1);
1826
1827
44688
  for(i=0; (i<LINELEN) && (line[*counter]); i++)
1828
  {
1829
44687
      if(line[*counter] == '>')
1830
      {
1831
6958
          nameBuf[i] = 0; // terminate the name
1832
6958
          *counter = (*counter + 1);
1833
6958
          done = 1;
1834
6958
          break;
1835
      }
1836
37729
      nameBuf[i] = line[*counter];
1837
37729
      *counter = (*counter + 1);
1838
  }
1839
1840
  // !!!KL need to rename the error message and change text
1841
6959
  CHKS((!done), NCE_NAMED_PARAMETER_NOT_TERMINATED);
1842
1843
  return INTERP_OK;
1844
}
1845
1846
1847
1848
1849
/****************************************************************************/
1850
1851
/*! read_parameter
1852
1853
Returned Value: int
1854
   If read_integer_value returns an error code, this returns that code.
1855
   If any of the following errors occur, this returns the error code shown.
1856
   Otherwise, this returns INTERP_OK.
1857
   1. The first character read is not # :
1858
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
1859
   2. The parameter number is out of bounds:
1860
      NCE_PARAMETER_NUMBER_OUT_OF_RANGE
1861
1862
Side effects:
1863
   The value of the given parameter is put into what double_ptr points at.
1864
   The counter is reset to point to the first character after the
1865
   characters which make up the value.
1866
1867
Called by:  read_real_value
1868
1869
This attempts to read the value of a parameter out of the line,
1870
starting at the index given by the counter.
1871
1872
According to the RS274/NGC manual [NCMS, p. 62], the characters following
1873
# may be any "parameter expression". Thus, the following are legal
1874
and mean the same thing (the value of the parameter whose number is
1875
stored in parameter 2):
1876
  ##2
1877
  #[#2]
1878
1879
Parameter setting is done in parallel, not sequentially. For example
1880
if #1 is 5 before the line "#1=10 #2=#1" is read, then after the line
1881
is is executed, #1 is 10 and #2 is 5. If parameter setting were done
1882
sequentially, the value of #2 would be 10 after the line was executed.
1883
1884
ADDED by K. Lerman
1885
Named parameters are now supported.
1886
#[abcd] is a parameter with name "abcd"
1887
#[#2] is NOT a named parameter.
1888
When a [ is seen after a #, if the next char is not a #, it is a named
1889
parameter.
1890
1891
*/
1892
1893
6442
int Interp::read_parameter(
1894
    char *line,   //!< string: line of RS274/NGC code being processed
1895
    int *counter, //!< pointer to a counter for position on the line
1896
    double *double_ptr,   //!< pointer to double to be read
1897
    double *parameters,   //!< array of system parameters
1898
    bool check_exists)    //!< test for existence, not value
1899
{
1900
  int index;
1901
1902
6442
  CHKS((line[*counter] != '#'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1903
1904
6442
  *counter = (*counter + 1);
1905
1906
  // named parameters look like '<letter...>' or '<_.....>'
1907
6442
  if(line[*counter] == '<')
1908
  {
1909
      //_setup.stack_index = 0; -- reminder of variable we need
1910
      // find the matching string (if any) -- or create it
1911
      // then get the value and store it
1912
2936
      CHP(read_named_parameter(line, counter, double_ptr, parameters,
1913
	      check_exists));
1914
  }
1915
  else
1916
  {
1917
3506
      CHP(read_integer_value(line, counter, &index, parameters));
1918
3503
      if(check_exists)
1919
      {
1920
6
	  *double_ptr = index >= 1 && index < RS274NGC_MAX_PARAMETERS;
1921
6
	  return INTERP_OK;
1922
      }
1923
3497
      CHKS(((index < 1) || (index >= RS274NGC_MAX_PARAMETERS)),
1924
          NCE_PARAMETER_NUMBER_OUT_OF_RANGE);
1925
3496
      CHKS(((index >= 5420) && (index <= 5428) && (_setup.cutter_comp_side)),
1926
           _("Cannot read current position with cutter radius compensation on"));
1927
3496
      *double_ptr = parameters[index];
1928
  }
1929
  return INTERP_OK;
1930
}
1931
1932
14
int Interp::read_bracketed_parameter(
1933
    char *line,   //!< string: line of RS274/NGC code being processed
1934
    int *counter, //!< pointer to a counter for position on the line
1935
    double *double_ptr,   //!< pointer to double to be read
1936
    double *parameters,   //!< array of system parameters
1937
    bool check_exists)    //!< test for existence, not value
1938
{
1939
14
  CHKS((line[*counter] != '['), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
1940
14
  *counter = (*counter + 1);
1941
14
  CHKS((line[*counter] != '#'), _("Expected # reading parameter"));
1942
13
  CHP(read_parameter(line, counter, double_ptr, parameters, check_exists));
1943
9
  CHKS((line[*counter] != ']'), _("Expected ] reading bracketed parameter"));
1944
7
  *counter = (*counter + 1);
1945
7
  return INTERP_OK;
1946
}
1947
1948
1949
/****************************************************************************/
1950
1951
/*! read_parameter_setting
1952
1953
Returned Value: int
1954
   If read_real_value or read_integer_value returns an error code,
1955
   this returns that code.
1956
   If any of the following errors occur, this returns the error code shown.
1957
   Otherwise, it returns INTERP_OK.
1958
   1. The first character read is not # :
1959
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
1960
   2. The parameter index is out of range: PARAMETER_NUMBER_OUT_OF_RANGE
1961
   3. An equal sign does not follow the parameter expression:
1962
      NCE_EQUAL_SIGN_MISSING_IN_PARAMETER_SETTING
1963
1964
Side effects:
1965
   counter is reset to the character following the end of the parameter
1966
   setting. The parameter whose index follows "#" is set to the
1967
   real value following "=".
1968
1969
Called by: read_one_item
1970
1971
When this function is called, counter is pointing at an item on the
1972
line that starts with the character '#', indicating a parameter
1973
setting when found by read_one_item.  The function reads characters
1974
which tell how to set the parameter.
1975
1976
Any number of parameters may be set on a line. If parameters set early
1977
on the line are used in expressions farther down the line, the
1978
parameters have their old values, not their new values. This is
1979
usually called setting parameters in parallel.
1980
1981
Parameter setting is not clearly described in [NCMS, pp. 51 - 62]: it is
1982
not clear if more than one parameter setting per line is allowed (any
1983
number is OK in this implementation). The characters immediately following
1984
the "#" must constitute a "parameter expression", but it is not clear
1985
what that is. Here we allow any expression as long as it evaluates to
1986
an integer.
1987
1988
Parameters are handled in the interpreter by having a parameter table
1989
and a parameter buffer as part of the machine settings. The parameter
1990
table is passed to the reading functions which need it. The parameter
1991
buffer is used directly by functions that need it. Reading functions
1992
may set parameter values in the parameter buffer. Reading functions
1993
may obtain parameter values; these come from parameter table.
1994
1995
The parameter buffer has three parts: (i) a counter for how many
1996
parameters have been set while reading the current line (ii) an array
1997
of the indexes of parameters that have been set while reading the
1998
current line, and (iii) an array of the values for the parameters that
1999
have been set while reading the current line; the nth value
2000
corresponds to the nth index. Any given index will appear once in the
2001
index number array for each time the parameter with that index is set
2002
on a line. There is no point in setting the same parameter more than
2003
one on a line because only the last setting of that parameter will
2004
take effect.
2005
2006
The syntax recognized by this this function is # followed by an
2007
integer expression (explicit integer or expression evaluating to an
2008
integer) followed by = followed by a real value (number or
2009
expression).
2010
2011
Note that # also starts a bunch of characters which represent a parameter
2012
to be evaluated. That situation is handled by read_parameter.
2013
2014
*/
2015
2016
2125
int Interp::read_parameter_setting(
2017
    char *line,   //!< string: line of RS274/NGC code being processed
2018
    int *counter, //!< pointer to a counter for position on the line
2019
    block_pointer block,  //!< pointer to a block being filled from the line
2020
    double *parameters)   //!< array of system parameters
2021
{
2022
  static char name[] = "read_parameter_setting";
2023
  int index;
2024
  double value;
2025
  char *param;
2026
  const char *dup;
2027
2028
2125
  CHKS((line[*counter] != '#'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
2029
2125
  *counter = (*counter + 1);
2030
2031
  // named parameters look like '<letter...>' or '<_letter.....>'
2032
2125
  if((line[*counter] == '<') || isalpha(line[*(counter)]))
2033
  {
2034
1671
      CHP(read_named_parameter_setting(line, counter, &param, parameters));
2035
2036
1671
      CHKS((line[*counter] != '='),
2037
          NCE_EQUAL_SIGN_MISSING_IN_PARAMETER_SETTING);
2038
1671
      *counter = (*counter + 1);
2039
1671
      CHP(read_real_value(line, counter, &value, parameters));
2040
2041
1671
      logDebug("setting up named param[%d]:|%s| value:%lf",
2042
               _setup.named_parameter_occurrence, param, value);
2043
2044
1671
      dup = strstore(param); // no more need to free this
2045
1671
      if(dup == 0)
2046
      {
2047
          ERS(NCE_OUT_OF_MEMORY);
2048
      }
2049
1671
      logDebug("%s |%s|", name,  dup);
2050
1671
      _setup.named_parameters[_setup.named_parameter_occurrence] = dup;
2051
2052
1671
      _setup.named_parameter_values[_setup.named_parameter_occurrence] = value;
2053
1671
      _setup.named_parameter_occurrence++;
2054
1671
      logDebug("done setting up named param[%d]:|%s| value:%lf",
2055
               _setup.named_parameter_occurrence, param, value);
2056
  }
2057
  else
2058
  {
2059
454
      CHP(read_integer_value(line, counter, &index, parameters));
2060
454
      CHKS(((index < 1) || (index >= RS274NGC_MAX_PARAMETERS)),
2061
          NCE_PARAMETER_NUMBER_OUT_OF_RANGE);
2062
454
      CHKS((isreadonly(index)), NCE_PARAMETER_NUMBER_READONLY);
2063
454
      CHKS((line[*counter] != '='),
2064
          NCE_EQUAL_SIGN_MISSING_IN_PARAMETER_SETTING);
2065
454
      *counter = (*counter + 1);
2066
454
      CHP(read_real_value(line, counter, &value, parameters));
2067
451
      _setup.parameter_numbers[_setup.parameter_occurrence] = index;
2068
451
      _setup.parameter_values[_setup.parameter_occurrence] = value;
2069
451
      _setup.parameter_occurrence++;
2070
  }
2071
  return INTERP_OK;
2072
}
2073
2074
/****************************************************************************/
2075
2076
/*! read_named_parameter_setting
2077
2078
Returned Value: int
2079
   If read_real_value or read_integer_value returns an error code,
2080
   this returns that code.
2081
   If any of the following errors occur, this returns the error code shown.
2082
   Otherwise, it returns INTERP_OK.
2083
   1. The first character read is not # :
2084
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
2085
   2. The parameter index is out of range: PARAMETER_NUMBER_OUT_OF_RANGE
2086
   3. An equal sign does not follow the parameter expression:
2087
      NCE_EQUAL_SIGN_MISSING_IN_PARAMETER_SETTING
2088
2089
Side effects:
2090
   counter is reset to the character following the end of the parameter
2091
   setting. The parameter whose index follows "#" is set to the
2092
   real value following "=".
2093
2094
Called by: read_parameter_setting
2095
2096
When this function is called, counter is pointing at an item on the
2097
line that starts with the character '#', indicating a parameter
2098
setting when found by read_one_item.  The function reads characters
2099
which tell how to set the parameter.
2100
2101
Any number of parameters may be set on a line. If parameters set early
2102
on the line are used in expressions farther down the line, the
2103
parameters have their old values, not their new values. This is
2104
usually called setting parameters in parallel.
2105
2106
Parameter setting is not clearly described in [NCMS, pp. 51 - 62]: it is
2107
not clear if more than one parameter setting per line is allowed (any
2108
number is OK in this implementation). The characters immediately following
2109
the "#" must constitute a "parameter expression", but it is not clear
2110
what that is. Here we allow any expression as long as it evaluates to
2111
an integer.
2112
2113
Parameters are handled in the interpreter by having a parameter table
2114
and a parameter buffer as part of the machine settings. The parameter
2115
table is passed to the reading functions which need it. The parameter
2116
buffer is used directly by functions that need it. Reading functions
2117
may set parameter values in the parameter buffer. Reading functions
2118
may obtain parameter values; these come from parameter table.
2119
2120
The parameter buffer has three parts: (i) a counter for how many
2121
parameters have been set while reading the current line (ii) an array
2122
of the indexes of parameters that have been set while reading the
2123
current line, and (iii) an array of the values for the parameters that
2124
have been set while reading the current line; the nth value
2125
corresponds to the nth index. Any given index will appear once in the
2126
index number array for each time the parameter with that index is set
2127
on a line. There is no point in setting the same parameter more than
2128
one on a line because only the last setting of that parameter will
2129
take effect.
2130
2131
The syntax recognized by this this function is # followed by an
2132
integer expression (explicit integer or expression evaluating to an
2133
integer) followed by = followed by a real value (number or
2134
expression).
2135
2136
Note that # also starts a bunch of characters which represent a parameter
2137
to be evaluated. That situation is handled by read_parameter.
2138
2139
*/
2140
2141
1671
int Interp::read_named_parameter_setting(
2142
    char *line,   //!< string: line of RS274/NGC code being processed
2143
    int *counter, //!< pointer to a counter for position on the line
2144
    char **param,  //!< pointer to the char * to be returned
2145
    double *parameters)   //!< array of system parameters
2146
{
2147
  static char name[] = "read_named_parameter_setting";
2148
  int status;
2149
  static char paramNameBuf[LINELEN+1];
2150
2151
1671
  *param = paramNameBuf;
2152
2153
1671
  logDebug("entered %s", name);
2154
1671
  CHKS(((line[*counter] != '<') && !isalpha(line[*(counter)])),
2155
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
2156
2157
1671
  status=read_name(line, counter, paramNameBuf);
2158
1671
  CHP(status);
2159
2160
1671
  logDebug("%s: returned(%d) from read_name:|%s|", name, status, paramNameBuf);
2161
2162
1671
  status = add_named_param(paramNameBuf);
2163
1671
  CHP(status);
2164
1671
  logDebug("%s: returned(%d) from add_named_param:|%s|", name, status, paramNameBuf);
2165
2166
  // the rest of the work is done in read_parameter_setting
2167
2168
  return INTERP_OK;
2169
}
2170
2171
/****************************************************************************/
2172
2173
/*! read_q
2174
2175
Returned Value: int
2176
   If read_real_value returns an error code, this returns that code.
2177
   If any of the following errors occur, this returns the error code shown.
2178
   Otherwise, it returns INTERP_OK.
2179
   1. The first character read is not q:
2180
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
2181
   2. A q value has already been inserted in the block:
2182
      NCE_MULTIPLE_Q_WORDS_ON_ONE_LINE
2183
2184
Side effects:
2185
   counter is reset to point to the first character following the q value.
2186
   The q value setting is inserted in block.
2187
2188
Called by: read_one_item
2189
2190
When this function is called, counter is pointing at an item on the
2191
line that starts with the character 'q', indicating a q value
2192
setting. The function reads characters which tell how to set the q
2193
value, up to the start of the next item or the end of the line. This
2194
information is inserted in the block.
2195
2196
Q is used only in the G87 canned cycle [NCMS, page 98], where it must
2197
be positive.
2198
2199
*/
2200
2201
4
int Interp::read_q(char *line,   //!< string: line of RS274/NGC code being processed
2202
                  int *counter, //!< pointer to a counter for position on the line
2203
                  block_pointer block,  //!< pointer to a block being filled from the line
2204
                  double *parameters)   //!< array of system parameters
2205
{
2206
  double value;
2207
2208
4
  CHKS((line[*counter] != 'q'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
2209
4
  *counter = (*counter + 1);
2210
4
  CHKS((block->q_number > -1.0), NCE_MULTIPLE_Q_WORDS_ON_ONE_LINE);
2211
4
  CHP(read_real_value(line, counter, &value, parameters));
2212
  // FMP removed check for negatives, since we may want them for
2213
  // user-defined codes
2214
  // CHKS((value <= 0.0), NCE_NEGATIVE_OR_ZERO_Q_VALUE_USED);
2215
4
  block->q_number = value;
2216
4
  block->q_flag = true;
2217
4
  return INTERP_OK;
2218
}
2219
2220
/****************************************************************************/
2221
2222
/*! read_r
2223
2224
Returned Value: int
2225
   If read_real_value returns an error code, this returns that code.
2226
   If any of the following errors occur, this returns the error code shown.
2227
   Otherwise, it returns INTERP_OK.
2228
   1. The first character read is not r:
2229
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
2230
   2. An r_number has already been inserted in the block:
2231
      NCE_MULTIPLE_R_WORDS_ON_ONE_LINE
2232
2233
Side effects:
2234
   counter is reset.
2235
   The r_flag in the block is turned on.
2236
   The r_number is inserted in the block.
2237
2238
Called by: read_one_item
2239
2240
When this function is called, counter is pointing at an item on the
2241
line that starts with the character 'r'. The function reads characters
2242
which tell how to set the coordinate, up to the start of the next item
2243
or the end of the line. This information is inserted in the block. The
2244
counter is then set to point to the character following.
2245
2246
An r number indicates the clearance plane in canned cycles.
2247
An r number may also be the radius of an arc.
2248
2249
The value may be a real number or something that evaluates to a
2250
real number, so read_real_value is used to read it. Parameters
2251
may be involved.
2252
2253
*/
2254
2255
68
int Interp::read_r(char *line,   //!< string: line of RS274 code being processed
2256
                  int *counter, //!< pointer to a counter for position on the line
2257
                  block_pointer block,  //!< pointer to a block being filled from the line
2258
                  double *parameters)   //!< array of system parameters
2259
{
2260
  double value;
2261
2262
68
  CHKS((line[*counter] != 'r'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
2263
68
  *counter = (*counter + 1);
2264
68
  CHKS((block->r_flag), NCE_MULTIPLE_R_WORDS_ON_ONE_LINE);
2265
68
  CHP(read_real_value(line, counter, &value, parameters));
2266
68
  block->r_flag = true;
2267
68
  block->r_number = value;
2268
68
  return INTERP_OK;
2269
}
2270
2271
/****************************************************************************/
2272
2273
/*! read_real_expression
2274
2275
Returned Value: int
2276
   If any of the following functions returns an error code,
2277
   this returns that code.
2278
     read_real_value
2279
     read_operation
2280
     execute_binary
2281
   If any of the following errors occur, this returns the error shown.
2282
   Otherwise, it returns INTERP_OK.
2283
   1. The first character is not [ :
2284
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
2285
2286
Side effects:
2287
   The number read from the line is put into what value_ptr points at.
2288
   The counter is reset to point to the first character after the real
2289
   expression.
2290
2291
Called by:
2292
 read_atan
2293
 read_real_value
2294
 read_unary
2295
2296
Example 1: [2 - 3 * 4 / 5] means [2 - [[3 * 4] / 5]] and equals -0.4.
2297
2298
Segmenting Expressions -
2299
2300
The RS274/NGC manual, section 3.5.1.1 [NCMS, page 50], provides for
2301
using square brackets to segment expressions.
2302
2303
Binary Operations -
2304
2305
The RS274/NGC manual, section 3.5.1.1, discusses expression evaluation.
2306
The manual provides for eight binary operations: the four basic
2307
mathematical operations (addition, subtraction, multiplication,
2308
division), three logical operations (non-exclusive ||, exclusive ||,
2309
and AND2) and the modulus operation. The manual does not explicitly call
2310
these "binary" operations, but implicitly recognizes that they are
2311
binary. We have added the "power" operation of raising the number
2312
on the left of the operation to the power on the right; this is
2313
needed for many basic machining calculations.
2314
2315
There are two groups of binary operations given in the manual. If
2316
operations are strung together as shown in Example 1, operations in
2317
the first group are to be performed before operations in the second
2318
group. If an expression contains more than one operation from the same
2319
group (such as * and / in Example 1), the operation on the left is
2320
performed first. The first group is: multiplication (*), division (/),
2321
and modulus (MOD). The second group is: addition(+), subtraction (-),
2322
logical non-exclusive || (||), logical exclusive || (XOR), and logical
2323
&& (AND2). We have added a third group with higher precedence than
2324
the first group. The third group contains only the power (**)
2325
operation.
2326
2327
The logical operations and modulus are apparently to be performed on
2328
any real numbers, not just on integers or on some other data type.
2329
2330
Unary Operations -
2331
2332
The RS274/NGC manual, section 3.5.1.2, provides for fifteen unary
2333
mathematical operations. Two of these, BIN and BCD, are apparently for
2334
converting between decimal and hexadecimal number representation,
2335
although the text is not clear. These have not been implemented, since
2336
we are not using any hexadecimal numbers. The other thirteen unary
2337
operations have been implemented: absolute_value, arc_cosine, arc_sine,
2338
arc_tangent, cosine, e_raised_to, fix_down, fix_up, natural_log_of,
2339
round, sine, square_root, tangent.
2340
2341
The manual section 3.5.1.2 [NCMS, page 51] requires the argument to
2342
all unary operations (except atan) to be in square brackets.  Thus,
2343
for example "sin[90]" is allowed in the interpreter, but "sin 90" is
2344
not. The atan operation must be in the format "atan[..]/[..]".
2345
2346
Production Rule Definitions in Terms of Tokens -
2347
2348
The following is a production rule definition of what this RS274NGC
2349
interpreter recognizes as valid combinations of symbols which form a
2350
recognized real_value (the top of this production hierarchy).
2351
2352
The notion of "integer_value" is used in the interpreter. Below it is
2353
defined as a synonym for real_value, but in fact a constraint is added
2354
which cannot be readily written in a production language.  An
2355
integer_value is a real_value which is very close to an integer.
2356
Integer_values are needed for array and table indices and (when
2357
divided by 10) for the values of M codes and G codes. All numbers
2358
(including integers) are read as real numbers and stored as doubles.
2359
If an integer_value is required in some situation, a test for being
2360
close to an integer is applied to the number after it is read.
2361
2362
2363
arc_tangent_combo = arc_tangent expression divided_by expression .
2364
2365
binary_operation1 = divided_by | modulo | power | times .
2366
2367
binary_operation2 = and | exclusive_or | minus |  non_exclusive_or | plus .
2368
2369
combo1 = real_value { binary_operation1 real_value } .
2370
2371
digit = zero | one | two | three | four | five | six | seven |eight | nine .
2372
2373
expression =
2374
   left_bracket
2375
   (unary_combo | (combo1 { binary_operation2 combo1 }))
2376
   right_bracket .
2377
2378
integer_value = real_value .
2379
2380
ordinary_unary_combo =  ordinary_unary_operation expression .
2381
2382
ordinary_unary_operation =
2383
   absolute_value | arc_cosine | arc_sine | cosine | e_raised_to |
2384
   fix_down | fix_up | natural_log_of | round | sine | square_root | tangent .
2385
2386
parameter_index = integer_value .
2387
2388
parameter_value = parameter_sign  parameter_index .
2389
2390
real_number =
2391
   [ plus | minus ]
2392
   (( digit { digit } decimal_point {digit}) | ( decimal_point digit {digit})).
2393
2394
real_value =
2395
   real_number | expression | parameter_value | unary_combo.
2396
2397
unary_combo = ordinary_unary_combo | arc_tangent_combo .
2398
2399
2400
Production Tokens in Terms of Characters -
2401
2402
absolute_value   = 'abs'
2403
and              = 'and'
2404
arc_cosine       = 'acos'
2405
arc_sine         = 'asin'
2406
arc_tangent      = 'atan'
2407
cosine           = 'cos'
2408
decimal_point    = '.'
2409
divided_by       = '/'
2410
eight            = '8'
2411
exclusive_or     = 'xor'
2412
e_raised_to      = 'exp'
2413
five             = '5'
2414
fix_down         = 'fix'
2415
fix_up           = 'fup'
2416
four             = '4'
2417
left_bracket     = '['
2418
minus            = '-'
2419
modulo           = 'mod'
2420
natural_log_of   = 'ln'
2421
nine             = '9'
2422
non_exclusive_or = 'or'
2423
one              = '1'
2424
parameter_sign   = '#'
2425
plus             = '+'
2426
power            = '**'
2427
right_bracket    = ']'
2428
round            = 'round'
2429
seven            = '7'
2430
sine             = 'sin'
2431
six              = '6'
2432
square_root      = 'sqrt'
2433
tangent          = 'tan'
2434
three            = '3'
2435
times            = '*'
2436
two              = '2'
2437
zero             = '0'
2438
2439
When this function is called, the counter should be set at a left
2440
bracket. The function reads up to and including the right bracket
2441
which closes the expression.
2442
2443
The basic form of an expression is: [v1 bop v2 bop ... vn], where the
2444
vi are real_values and the bops are binary operations. The vi may be
2445
numbers, parameters, expressions, or unary functions. Because some
2446
bops are to be evaluated before others, for understanding the order of
2447
evaluation, it is useful to rewrite the general form collecting any
2448
subsequences of bops of the same precedence. For example, suppose the
2449
expression is: [9+8*7/6+5-4*3**2+1]. It may be rewritten as:
2450
[9+[8*7/6]+5-[4*[3**2]]+1] to show how it should be evaluated.
2451
2452
The manual provides that operations of the same precedence should be
2453
processed left to right.
2454
2455
The first version of this function is commented out. It is suitable
2456
for when there are only two precendence levels. It is an improvement
2457
over the version used in interpreters before 2000, but not as general
2458
as the second version given here.
2459
2460
The first version of this function reads the first value and the first
2461
operation in the expression. Then it calls either read_rest_bop1 or
2462
read_rest_bop2 according to whether the first operation is a bop1 or a
2463
bop2.  Read_rest_bop1 resets the next_operation to either a right
2464
bracket or a bop2. If it is reset to a bop2, read_rest_bop2 is called
2465
when read_rest_bop1 returns.
2466
2467
*/
2468
2469
#ifdef UNDEFINED
2470
int Interp::read_real_expression(char *line,     //!< string: line of RS274/NGC code being processed
2471
                                int *counter,   //!< pointer to a counter for position on the line
2472
                                double *value,  //!< pointer to double to be read
2473
                                double *parameters)     //!< array of system parameters
2474
{
2475
  static char name[] = "read_real_expression";
2476
  int next_operation;
2477
  int status;
2478
2479
  CHKS((line[*counter] != '['), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
2480
  *counter = (*counter + 1);
2481
  CHP(read_real_value(line, counter, value, parameters));
2482
  CHP(read_operation(line, counter, &next_operation));
2483
  if (next_operation == RIGHT_BRACKET); /* nothing to do */
2484
  else if (next_operation < AND2) {     /* next operation is a bop1, times-like */
2485
    CHP(read_rest_bop1(line, counter, value, &next_operation, parameters));
2486
    if (next_operation == RIGHT_BRACKET);       /* next_operation has been reset */
2487
    else                        /* next_operation is now a bop2, plus-like */
2488
      CHP(read_rest_bop2(line, counter, value, next_operation, parameters));
2489
  } else                        /* next operation is a bop2, plus-like */
2490
    CHP(read_rest_bop2(line, counter, value, next_operation, parameters));
2491
  return INTERP_OK;
2492
}
2493
#endif
2494
2495
/****************************************************************************/
2496
2497
/*! read_real_expression
2498
2499
The following version is stack-based and fully general. It is the
2500
classical stack-based version with left-to-right evaluation of
2501
operations of the same precedence. Separate stacks are used for
2502
operations and values, and the stacks are made with arrays
2503
rather than lists, but those are implementation details. Pushing
2504
and popping are implemented by increasing or decreasing the
2505
stack index.
2506
2507
Additional levels of precedence may be defined easily by changing the
2508
precedence function. The size of MAX_STACK should always be at least
2509
as large as the number of precedence levels used. We are currently
2510
using four precedence levels (for right-bracket, plus-like operations,
2511
times-like operations, and power).
2512
2513
N.B.: We are now using six levels (right-bracket, logical operations,
2514
relational operations, plus-like operations, times-like operations, and
2515
power).
2516
2517
*/
2518
2519
#define MAX_STACK 7
2520
2521
4509
int Interp::read_real_expression(char *line,     //!< string: line of RS274/NGC code being processed
2522
                                int *counter,   //!< pointer to a counter for position on the line
2523
                                double *value,  //!< pointer to double to be computed
2524
                                double *parameters)     //!< array of system parameters
2525
{
2526
  double values[MAX_STACK];
2527
  int operators[MAX_STACK];
2528
  int stack_index;
2529
2530
4509
  CHKS((line[*counter] != '['), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
2531
4509
  *counter = (*counter + 1);
2532
4509
  CHP(read_real_value(line, counter, values, parameters));
2533
4509
  CHP(read_operation(line, counter, operators));
2534
  stack_index = 1;
2535
7842
  for (; operators[0] != RIGHT_BRACKET;) {
2536
3335
    CHP(read_real_value(line, counter, values + stack_index, parameters));
2537
3335
    CHP(read_operation(line, counter, operators + stack_index));
2538
6670
    if (precedence(operators[stack_index]) >
2539
3335
        precedence(operators[stack_index - 1]))
2540
348
      stack_index++;
2541
    else {                      /* precedence of latest operator is <= previous precedence */
2542
2543
6670
      for (; precedence(operators[stack_index]) <=
2544
3335
           precedence(operators[stack_index - 1]);) {
2545
3335
        CHP(execute_binary((values + stack_index - 1),
2546
                           operators[stack_index - 1],
2547
                           (values + stack_index)));
2548
3333
        operators[stack_index - 1] = operators[stack_index];
2549
3681
        if ((stack_index > 1) &&
2550
348
            (precedence(operators[stack_index - 1]) <=
2551
348
             precedence(operators[stack_index - 2])))
2552
          stack_index--;
2553
        else
2554
          break;
2555
      }
2556
    }
2557
  }
2558
4507
  *value = values[0];
2559
4507
  return INTERP_OK;
2560
}
2561
2562
2563
/****************************************************************************/
2564
2565
/*! read_real_number
2566
2567
Returned Value: int
2568
   If any of the following errors occur, this returns the error shown.
2569
   Otherwise, it returns INTERP_OK.
2570
   1. The first character is not "+", "-", "." or a digit:
2571
      NCE_BAD_NUMBER_FORMAT
2572
   2. No digits are found after the first character and before the
2573
      end of the line or the next character that cannot be part of a real:
2574
      NCE_NO_DIGITS_FOUND_WHERE_REAL_NUMBER_SHOULD_BE
2575
   3. sscanf fails: NCE_SSCANF_FAILED
2576
2577
Side effects:
2578
   The number read from the line is put into what double_ptr points at.
2579
   The counter is reset to point to the first character after the real.
2580
2581
Called by:  read_real_value
2582
2583
This attempts to read a number out of the line, starting at the index
2584
given by the counter. It stops when the first character that cannot
2585
be part of the number is found.
2586
2587
The first character may be a digit, "+", "-", or "."
2588
Every following character must be a digit or "." up to anything
2589
that is not a digit or "." (a second "." terminates reading).
2590
2591
This function is not called if the first character is NULL, so it is
2592
not necessary to check that.
2593
2594
The temporary insertion of a NULL character on the line is to avoid
2595
making a format string like "%3lf" which the LynxOS compiler cannot
2596
handle.
2597
2598
*/
2599
2600
12474
int Interp::read_real_number(char *line, //!< string: line of RS274/NGC code being processed
2601
                            int *counter,       //!< pointer to a counter for position on the line
2602
                            double *double_ptr) //!< pointer to double to be read
2603
{
2604
  char *start;
2605
  size_t after;
2606
2607
12474
  start = line + *counter;
2608
2609
12474
  after = strspn(start, "+-");
2610
12474
  after = strspn(start+after, "0123456789.") + after;
2611
2612
24948
  std::string st(start, start+after);
2613
24948
  std::stringstream s(st);
2614
  double val;
2615
24949
  if(!(s >> val)) ERS(_("bad number format (conversion failed) parsing '%s'"), st.c_str());
2616
12473
  if(s.get() != std::char_traits<char>::eof()) ERS(_("bad number format (trailing characters) parsing '%s'"), st.c_str());
2617
2618
12473
  *double_ptr = val;
2619
12473
  *counter = start + after - line;
2620
  //fprintf(stderr, "got %f   rest of line=%s\n", val, line+*counter);
2621
24947
  return INTERP_OK;
2622
}
2623
2624
/****************************************************************************/
2625
2626
/*! read_real_value
2627
2628
Returned Value: int
2629
   If one of the following functions returns an error code,
2630
   this returns that code.
2631
      read_real_expression
2632
      read_parameter
2633
      read_unary
2634
      read_real_number
2635
   If no characters are found before the end of the line this
2636
   returns NCE_NO_CHARACTERS_FOUND_IN_READING_REAL_VALUE.
2637
   Otherwise, this returns INTERP_OK.
2638
2639
Side effects:
2640
   The value read from the line is put into what double_ptr points at.
2641
   The counter is reset to point to the first character after the
2642
   characters which make up the value.
2643
2644
Called by:
2645
   read_a
2646
   read_b
2647
   read_c
2648
   read_f
2649
   read_g
2650
   read_i
2651
   read_integer_value
2652
   read_j
2653
   read_k
2654
   read_p
2655
   read_parameter_setting
2656
   read_q
2657
   read_r
2658
   read_real_expression
2659
   read_s
2660
   read_x
2661
   read_y
2662
   read_z
2663
2664
This attempts to read a real value out of the line, starting at the
2665
index given by the counter. The value may be a number, a parameter
2666
value, a unary function, or an expression. It calls one of four
2667
other readers, depending upon the first character.
2668
2669
*/
2670
2671
21559
int Interp::read_real_value(char *line,  //!< string: line of RS274/NGC code being processed
2672
                           int *counter,        //!< pointer to a counter for position on the line
2673
                           double *double_ptr,  //!< pointer to double to be read
2674
                           double *parameters)  //!< array of system parameters
2675
{
2676
  char c, c1;
2677
2678
21559
  c = line[*counter];
2679
21559
  CHKS((c == 0), NCE_NO_CHARACTERS_FOUND_IN_READING_REAL_VALUE);
2680
2681
21559
  c1 = line[*counter+1];
2682
2683
21559
  if (c == '[')
2684
2334
    CHP(read_real_expression(line, counter, double_ptr, parameters));
2685
19225
  else if (c == '#')
2686
  {
2687
6429
    CHP(read_parameter(line, counter, double_ptr, parameters, false));
2688
  }
2689
12796
  else if (c == '+' && c1 && !isdigit(c1) && c1 != '.')
2690
  {
2691
    (*counter)++;
2692
    CHP(read_real_value(line, counter, double_ptr, parameters));
2693
  }
2694
12796
  else if (c == '-' && c1 && !isdigit(c1) && c1 != '.')
2695
  {
2696
    (*counter)++;
2697
    CHP(read_real_value(line, counter, double_ptr, parameters));
2698
    *double_ptr = -*double_ptr;
2699
  }
2700
12796
  else if ((c >= 'a') && (c <= 'z'))
2701
322
    CHP(read_unary(line, counter, double_ptr, parameters));
2702
  else
2703
12474
    CHP(read_real_number(line, counter, double_ptr));
2704
2705
21546
  CHKS(std::isnan(*double_ptr),
2706
          _("Calculation resulted in 'not a number'"));
2707
43092
  CHKS(std::isinf(*double_ptr),
2708
          _("Calculation resulted in 'infinity'"));
2709
2710
  return INTERP_OK;
2711
}
2712
2713
/****************************************************************************/
2714
2715
/*! read_rest_bop1
2716
2717
Returned Value: int
2718
  If any of the following functions returns an error code,
2719
  this returns that code.
2720
     execute_binary1
2721
     read_real_value
2722
     read_operation
2723
  Otherwise, it returns INTERP_OK.
2724
2725
Side effects:
2726
   The value argument is set to the value of the expression.
2727
   The counter is reset to point to the first character after the real
2728
   expression.
2729
2730
Called by:
2731
  read_real_expression
2732
  read_rest_bop2
2733
2734
The value argument has a value in it when this is called. This repeatedly
2735
gets the next_value and the next_operation, performs the last_operation
2736
on the value and the next_value and resets the last_operation to the
2737
next_operation. Observe that both the value and the last_operation
2738
are passed back to the caller.
2739
2740
This is commented out since it is not used in the uncommented version
2741
of read_real_expression. It has been tested.
2742
2743
*/
2744
2745
#ifdef UNDEFINED
2746
int Interp::read_rest_bop1(char *line,   //!< string: line of RS274/NGC code being processed
2747
                          int *counter, //!< pointer to a counter for position on the line
2748
                          double *value,        //!< pointer to double to be calculated
2749
                          int *last_operation,  //!< last operation read, reset to next operation
2750
                          double *parameters)   //!< array of system parameters
2751
{
2752
  static char name[] = "read_rest_bop1";
2753
  double next_value;
2754
  int next_operation;
2755
  int status;
2756
2757
  for (;;) {
2758
    CHP(read_real_value(line, counter, &next_value, parameters));
2759
    CHP(read_operation(line, counter, &next_operation));
2760
    CHP(execute_binary1(value, *last_operation, &next_value));
2761
    *last_operation = next_operation;
2762
    if (next_operation >= AND2) /* next op is a bop2 or right bracket */
2763
      break;
2764
  }
2765
  return INTERP_OK;
2766
}
2767
#endif
2768
2769
/****************************************************************************/
2770
2771
/*! read_rest_bop2
2772
2773
Returned Value: int
2774
  If any of the following functions returns an error code,
2775
  this returns that code.
2776
     execute_binary2
2777
     read_real_value
2778
     read_operation
2779
     read_rest_bop1
2780
  Otherwise, it returns INTERP_OK.
2781
2782
Side effects:
2783
   The value argument is set to the value of the expression.
2784
   The counter is reset to point to the first character after the real
2785
   expression.
2786
2787
Called by:  read_real_expression
2788
2789
The value argument has a value in it when this is called. This repeatedly
2790
gets the next_value and the next_operation, performs the last_operation
2791
on the value and the next_value and resets the last_operation to the
2792
next_operation. If the next_operation is ever a bop1 read_rest_bop1 is
2793
called to set the next_value.
2794
2795
This is commented out since it is not used in the uncommented version
2796
of read_real_expression. It has been tested.
2797
2798
*/
2799
2800
#ifdef UNDEFINED
2801
int Interp::read_rest_bop2(char *line,   //!< string: line of RS274/NGC code being processed
2802
                          int *counter, //!< pointer to a counter for position on the line
2803
                          double *value,        //!< pointer to double to be calculated
2804
                          int last_operation,   //!< last operation read
2805
                          double *parameters)   //!< array of system parameters
2806
{
2807
  static char name[] = "read_rest_bop2";
2808
  double next_value;
2809
  int next_operation;
2810
  int status;
2811
2812
  for (;; last_operation = next_operation) {
2813
    CHP(read_real_value(line, counter, &next_value, parameters));
2814
    CHP(read_operation(line, counter, &next_operation));
2815
    if (next_operation < AND2) {        /* next operation is a bop1 */
2816
      CHP(read_rest_bop1(line, counter, &next_value,
2817
                         &next_operation, parameters));
2818
    }
2819
    CHP(execute_binary2(value, last_operation, &next_value));
2820
    if (next_operation == RIGHT_BRACKET)
2821
      break;
2822
  }
2823
  return INTERP_OK;
2824
}
2825
#endif
2826
2827
/****************************************************************************/
2828
2829
/*! read_s
2830
2831
Returned Value: int
2832
   If read_real_value returns an error code, this returns that code.
2833
   If any of the following errors occur, this returns the error code shown.
2834
   Otherwise, it returns INTERP_OK.
2835
   1. The first character read is not s:
2836
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
2837
   2. A spindle speed has already been inserted in the block:
2838
      NCE_MULTIPLE_S_WORDS_ON_ONE_LINE
2839
   3. The spindle speed is negative: NCE_NEGATIVE_SPINDLE_SPEED_USED
2840
2841
Side effects:
2842
   counter is reset to the character following the spindle speed.
2843
   A spindle speed setting is inserted in the block.
2844
2845
Called by: read_one_item
2846
2847
When this function is called, counter is pointing at an item on the
2848
line that starts with the character 's', indicating a spindle speed
2849
setting. The function reads characters which tell how to set the spindle
2850
speed.
2851
2852
The value may be a real number or something that evaluates to a
2853
real number, so read_real_value is used to read it. Parameters
2854
may be involved.
2855
2856
*/
2857
2858
7
int Interp::read_s(char *line,   //!< string: line of RS274NGC code being processed
2859
                  int *counter, //!< pointer to a counter for position on the line
2860
                  block_pointer block,  //!< pointer to a block being filled from the line
2861
                  double *parameters)   //!< array of system parameters
2862
{
2863
  double value;
2864
2865
7
  CHKS((line[*counter] != 's'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
2866
7
  *counter = (*counter + 1);
2867
7
  CHKS((block->s_flag), NCE_MULTIPLE_S_WORDS_ON_ONE_LINE);
2868
7
  CHP(read_real_value(line, counter, &value, parameters));
2869
7
  CHKS((value < 0.0), NCE_NEGATIVE_SPINDLE_SPEED_USED);
2870
7
  block->s_number = value;
2871
7
  block->s_flag = true;
2872
7
  return INTERP_OK;
2873
}
2874
2875
/****************************************************************************/
2876
2877
/*! read_t
2878
2879
Returned Value: int
2880
   If read_integer_value returns an error code, this returns that code.
2881
   If any of the following errors occur, this returns the error code shown.
2882
   Otherwise, it returns INTERP_OK.
2883
   1. The first character read is not t:
2884
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
2885
   2. A t_number has already been inserted in the block:
2886
      NCE_MULTIPLE_T_WORDS_ON_ONE_LINE
2887
   3. The t_number is negative: NCE_NEGATIVE_TOOL_ID_USED
2888
2889
Side effects:
2890
   counter is reset to the character following the t_number.
2891
   A t_number is inserted in the block.
2892
2893
Called by: read_one_item
2894
2895
When this function is called, counter is pointing at an item on the
2896
line that starts with the character 't', indicating a tool.
2897
The function reads characters which give the (integer) value of the
2898
tool code.
2899
2900
The value must be an integer or something that evaluates to a
2901
real number, so read_integer_value is used to read it. Parameters
2902
may be involved.
2903
2904
*/
2905
2906
9
int Interp::read_t(char *line,   //!< string: line of RS274/NGC code being processed
2907
                  int *counter, //!< pointer to a counter for position on the line
2908
                  block_pointer block,  //!< pointer to a block being filled from the line
2909
                  double *parameters)   //!< array of system parameters
2910
{
2911
  int value;
2912
2913
9
  CHKS((line[*counter] != 't'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
2914
9
  *counter = (*counter + 1);
2915
9
  CHKS((block->t_flag), NCE_MULTIPLE_T_WORDS_ON_ONE_LINE);
2916
9
  CHP(read_integer_value(line, counter, &value, parameters));
2917
9
  CHKS((value < 0), NCE_NEGATIVE_TOOL_ID_USED);
2918
9
  block->t_number = value;
2919
9
  block->t_flag = true;
2920
9
  return INTERP_OK;
2921
}
2922
2923
/****************************************************************************/
2924
2925
/*! read_text
2926
2927
Returned Value: int
2928
   If close_and_downcase returns an error code, this returns that code.
2929
   If any of the following errors occur, this returns the error code shown.
2930
   Otherwise, this returns:
2931
       a. INTERP_ENDFILE if the percent_flag is true and the only
2932
          non-white character on the line is %,
2933
       b. INTERP_EXECUTE_FINISH if the first character of the
2934
          close_and_downcased line is a slash, and
2935
       c. INTERP_OK otherwise.
2936
   1. The end of the file is found and the percent_flag is true:
2937
      NCE_FILE_ENDED_WITH_NO_PERCENT_SIGN
2938
   2. The end of the file is found and the percent_flag is false:
2939
      NCE_FILE_ENDED_WITH_NO_PERCENT_SIGN_OR_PROGRAM_END
2940
   3. The command argument is not null and is too long or the command
2941
      argument is null and the line read from the file is too long:
2942
      NCE_COMMAND_TOO_LONG
2943
2944
Side effects: See below
2945
2946
Called by:  Interp::read
2947
2948
This reads a line of RS274 code from a command string or a file into
2949
the line array. If the command string is not null, the file is ignored.
2950
2951
If the end of file is reached, an error is returned as described
2952
above. The end of the file should not be reached because (a) if the
2953
file started with a percent line, it must end with a percent line, and
2954
no more reading of the file should occur after that, and (b) if the
2955
file did not start with a percent line, it must have a program ending
2956
command (M2 or M30) in it, and no more reading of the file should
2957
occur after that.
2958
2959
All blank space at the end of a line read from a file is removed and
2960
replaced here with NULL characters.
2961
2962
This then calls close_and_downcase to downcase and remove tabs and
2963
spaces from everything on the line that is not part of a comment. Any
2964
comment is left as is.
2965
2966
The length is set to zero if any of the following occur:
2967
1. The line now starts with a slash, but the second character is NULL.
2968
2. The first character is NULL.
2969
Otherwise, length is set to the length of the line.
2970
2971
An input line is blank if the first character is NULL or it consists
2972
entirely of tabs and spaces and, possibly, a newline before the first
2973
NULL.
2974
2975
Block delete is discussed in [NCMS, page 3] but the discussion makes
2976
no sense. Block delete is handled by having this function return
2977
INTERP_EXECUTE_FINISH if the first character of the
2978
close_and_downcased line is a slash. When the caller sees this,
2979
the caller is expected not to call Interp::execute if the switch
2980
is on, but rather call Interp::read again to overwrite and ignore
2981
what is read here.
2982
2983
The value of the length argument is set to the number of characters on
2984
the reduced line.
2985
2986
*/
2987
2988
11161
int Interp::read_text(
2989
    const char *command,       //!< a string which may have input text, or null
2990
    FILE * inport,     //!< a file pointer for an input file, or null
2991
    char *raw_line,    //!< array to write raw input line into
2992
    char *line,        //!< array for input line to be processed in
2993
    int *length)       //!< a pointer to an integer to be set
2994
{
2995
  int index;
2996
2997
11161
  if (command == NULL) {
2998
11149
    if (fgets(raw_line, LINELEN, inport) == NULL) {
2999
      if(_setup.skipping_to_sub)
3000
      {
3001
        ERS(_("EOF in file:%s seeking o-word: o<%s> from line: %d"),
3002
                 _setup.filename,
3003
                 _setup.skipping_to_sub,
3004
                 _setup.skipping_start);
3005
      }
3006
      if (_setup.percent_flag)
3007
      {
3008
        ERS(NCE_FILE_ENDED_WITH_NO_PERCENT_SIGN);
3009
      }
3010
      else
3011
      {
3012
        ERS(NCE_FILE_ENDED_WITH_NO_PERCENT_SIGN_OR_PROGRAM_END);
3013
      }
3014
    }
3015
11149
    _setup.sequence_number++;   /* moved from version1, was outside if */
3016
11149
    if (strlen(raw_line) == (LINELEN - 1)) { // line is too long. need to finish reading the line to recover
3017
      for (; fgetc(inport) != '\n';) {
3018
      }                         // could also look for EOF
3019
      ERS(NCE_COMMAND_TOO_LONG);
3020
    }
3021
22590
    for (index = (strlen(raw_line) - 1);        // index set on last char
3022
20885
         (index >= 0) && (isspace(raw_line[index]));
3023
         index--) { // remove space at end of raw_line, especially CR & LF
3024
11441
      raw_line[index] = 0;
3025
    }
3026
11149
    strcpy(line, raw_line);
3027
11149
    CHP(close_and_downcase(line));
3028
11149
    if ((line[0] == '%') && (line[1] == 0) && (_setup.percent_flag)) {
3029
1
        FINISH();
3030
1
        return INTERP_ENDFILE;
3031
    }
3032
  } else {
3033
12
    CHKS((strlen(command) >= LINELEN), NCE_COMMAND_TOO_LONG);
3034
12
    strcpy(raw_line, command);
3035
12
    strcpy(line, command);
3036
12
    CHP(close_and_downcase(line));
3037
  }
3038
3039
11160
  _setup.parameter_occurrence = 0;      /* initialize parameter buffer */
3040
3041
11160
  if ((line[0] == 0) || ((line[0] == '/') && (GET_BLOCK_DELETE())))
3042
1705
    *length = 0;
3043
  else
3044
9455
    *length = strlen(line);
3045
3046
  return INTERP_OK;
3047
}
3048
3049
/****************************************************************************/
3050
3051
/*! read_unary
3052
3053
Returned Value: int
3054
   If any of the following functions returns an error code,
3055
   this returns that code.
3056
     execute_unary
3057
     read_atan
3058
     read_operation_unary
3059
     read_real_expression
3060
   If any of the following errors occur, this returns the error code shown.
3061
   Otherwise, it returns INTERP_OK.
3062
   1. the name of the unary operation is not followed by a left bracket:
3063
      NCE_LEFT_BRACKET_MISSING_AFTER_UNARY_OPERATION_NAME
3064
3065
Side effects:
3066
   The value read from the line is put into what double_ptr points at.
3067
   The counter is reset to point to the first character after the
3068
   characters which make up the value.
3069
3070
Called by:  read_real_value
3071
3072
This attempts to read the value of a unary operation out of the line,
3073
starting at the index given by the counter. The atan operation is
3074
handled specially because it is followed by two arguments.
3075
3076
*/
3077
3078
322
int Interp::read_unary(char *line,       //!< string: line of RS274/NGC code being processed
3079
                      int *counter,     //!< pointer to a counter for position on the line
3080
                      double *double_ptr,       //!< pointer to double to be read
3081
                      double *parameters)       //!< array of system parameters
3082
{
3083
  int operation;
3084
3085
322
  CHP(read_operation_unary(line, counter, &operation));
3086
321
  CHKS((line[*counter] != '['),
3087
      NCE_LEFT_BRACKET_MISSING_AFTER_UNARY_OPERATION_NAME);
3088
3089
321
  if (operation == EXISTS)
3090
  {
3091
14
      CHP(read_bracketed_parameter(line, counter, double_ptr, parameters, true));
3092
      return INTERP_OK;
3093
  }
3094
3095
307
  CHP(read_real_expression(line, counter, double_ptr, parameters));
3096
3097
307
  if (operation == ATAN)
3098
    CHP(read_atan(line, counter, double_ptr, parameters));
3099
  else
3100
307
    CHP(execute_unary(double_ptr, operation));
3101
  return INTERP_OK;
3102
}
3103
3104
int Interp::read_u(char *line,   //!< string: line of RS274/NGC code being processed
3105
                  int *counter, //!< pointer to a counter for position on the line
3106
                  block_pointer block,  //!< pointer to a block being filled from the line
3107
                  double *parameters)   //!< array of system parameters
3108
{
3109
  double value;
3110
3111
  CHKS((line[*counter] != 'u'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
3112
  *counter = (*counter + 1);
3113
  CHKS((block->u_flag), _("Multiple U words on one line"));
3114
  CHP(read_real_value(line, counter, &value, parameters));
3115
  block->u_flag = true;
3116
  block->u_number = value;
3117
  return INTERP_OK;
3118
}
3119
3120
int Interp::read_v(char *line,   //!< string: line of RS274/NGC code being processed
3121
                  int *counter, //!< pointer to a counter for position on the line
3122
                  block_pointer block,  //!< pointer to a block being filled from the line
3123
                  double *parameters)   //!< array of system parameters
3124
{
3125
  double value;
3126
3127
  CHKS((line[*counter] != 'v'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
3128
  *counter = (*counter + 1);
3129
  CHKS((block->v_flag), _("Multiple V words on one line"));
3130
  CHP(read_real_value(line, counter, &value, parameters));
3131
  block->v_flag = true;
3132
  block->v_number = value;
3133
  return INTERP_OK;
3134
}
3135
3136
int Interp::read_w(char *line,   //!< string: line of RS274/NGC code being processed
3137
                  int *counter, //!< pointer to a counter for position on the line
3138
                  block_pointer block,  //!< pointer to a block being filled from the line
3139
                  double *parameters)   //!< array of system parameters
3140
{
3141
  double value;
3142
3143
  CHKS((line[*counter] != 'w'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
3144
  *counter = (*counter + 1);
3145
  CHKS((block->w_flag), _("Multiple W words on one line"));
3146
  CHP(read_real_value(line, counter, &value, parameters));
3147
  block->w_flag = true;
3148
  block->w_number = value;
3149
  return INTERP_OK;
3150
}
3151
3152
3153
/****************************************************************************/
3154
3155
/*! read_x
3156
3157
Returned Value: int
3158
   If read_real_value returns an error code, this returns that code.
3159
   If any of the following errors occur, this returns the error code shown.
3160
   Otherwise, it returns INTERP_OK.
3161
   1. The first character read is not x:
3162
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
3163
   2. A x_coordinate has already been inserted in the block:
3164
      NCE_MULTIPLE_X_WORDS_ON_ONE_LINE
3165
3166
Side effects:
3167
   counter is reset.
3168
   The x_flag in the block is turned on.
3169
   An x_number is inserted in the block.
3170
3171
Called by: read_one_item
3172
3173
When this function is called, counter is pointing at an item on the
3174
line that starts with the character 'x', indicating a x_coordinate
3175
setting. The function reads characters which tell how to set the
3176
coordinate, up to the start of the next item or the end of the line.
3177
This information is inserted in the block. The counter is then set to
3178
point to the character following.
3179
3180
The value may be a real number or something that evaluates to a
3181
real number, so read_real_value is used to read it. Parameters
3182
may be involved.
3183
3184
*/
3185
3186
1259
int Interp::read_x(char *line,   //!< string: line of RS274 code being processed
3187
                  int *counter, //!< pointer to a counter for position on the line
3188
                  block_pointer block,  //!< pointer to a block being filled from the line
3189
                  double *parameters)   //!< array of system parameters
3190
{
3191
  double value;
3192
3193
1259
  CHKS((line[*counter] != 'x'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
3194
1259
  *counter = (*counter + 1);
3195
1259
  CHKS((block->x_flag), NCE_MULTIPLE_X_WORDS_ON_ONE_LINE);
3196
1259
  CHP(read_real_value(line, counter, &value, parameters));
3197
1252
  block->x_flag = true;
3198
1252
  if(_setup.lathe_diameter_mode)
3199
  {
3200
    block->x_number = value / 2;
3201
  }else
3202
  {
3203
1252
  block->x_number = value;
3204
  }
3205
  return INTERP_OK;
3206
}
3207
3208
int Interp::read_atsign(char *line, int *counter, block_pointer block,
3209
                        double *parameters) {
3210
    CHKS((line[*counter] != '@'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
3211
    (*counter)++;
3212
    CHP(read_real_value(line, counter, &block->radius, parameters));
3213
    block->radius_flag = true;
3214
    return INTERP_OK;
3215
}
3216
3217
int Interp::read_carat(char *line, int *counter, block_pointer block,
3218
                       double *parameters) {
3219
    CHKS((line[*counter] != '^'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
3220
    (*counter)++;
3221
    CHP(read_real_value(line, counter, &block->theta, parameters));
3222
    block->theta_flag = true;
3223
    return INTERP_OK;
3224
}
3225
3226
3227
3228
/****************************************************************************/
3229
3230
/*! read_y
3231
3232
Returned Value: int
3233
   If read_real_value returns an error code, this returns that code.
3234
   If any of the following errors occur, this returns the error code shown.
3235
   Otherwise, it returns INTERP_OK.
3236
   1. The first character read is not y:
3237
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
3238
   2. A y_coordinate has already been inserted in the block:
3239
      NCE_MULTIPLE_Y_WORDS_ON_ONE_LINE
3240
3241
Side effects:
3242
   counter is reset.
3243
   The y_flag in the block is turned on.
3244
   A y_number is inserted in the block.
3245
3246
Called by: read_one_item
3247
3248
When this function is called, counter is pointing at an item on the
3249
line that starts with the character 'y', indicating a y_coordinate
3250
setting. The function reads characters which tell how to set the
3251
coordinate, up to the start of the next item or the end of the line.
3252
This information is inserted in the block. The counter is then set to
3253
point to the character following.
3254
3255
The value may be a real number or something that evaluates to a
3256
real number, so read_real_value is used to read it. Parameters
3257
may be involved.
3258
3259
*/
3260
3261
1308
int Interp::read_y(char *line,   //!< string: line of RS274 code being processed
3262
                  int *counter, //!< pointer to a counter for position on the line
3263
                  block_pointer block,  //!< pointer to a block being filled from the line
3264
                  double *parameters)   //!< array of system parameters
3265
{
3266
  double value;
3267
3268
1308
  CHKS((line[*counter] != 'y'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
3269
1308
  *counter = (*counter + 1);
3270
1308
  CHKS((block->y_flag), NCE_MULTIPLE_Y_WORDS_ON_ONE_LINE);
3271
1308
  CHP(read_real_value(line, counter, &value, parameters));
3272
1308
  block->y_flag = true;
3273
1308
  block->y_number = value;
3274
1308
  return INTERP_OK;
3275
}
3276
3277
/****************************************************************************/
3278
3279
/*! read_z
3280
3281
Returned Value: int
3282
   If read_real_value returns an error code, this returns that code.
3283
   If any of the following errors occur, this returns the error code shown.
3284
   Otherwise, it returns INTERP_OK.
3285
   1. The first character read is not z:
3286
      NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED
3287
   2. A z_coordinate has already been inserted in the block:
3288
      NCE_MULTIPLE_Z_WORDS_ON_ONE_LINE
3289
3290
Side effects:
3291
   counter is reset.
3292
   The z_flag in the block is turned on.
3293
   A z_number is inserted in the block.
3294
3295
Called by: read_one_item
3296
3297
When this function is called, counter is pointing at an item on the
3298
line that starts with the character 'z', indicating a z_coordinate
3299
setting. The function reads characters which tell how to set the
3300
coordinate, up to the start of the next item or the end of the line.
3301
This information is inserted in the block. The counter is then set to
3302
point to the character following.
3303
3304
The value may be a real number or something that evaluates to a
3305
real number, so read_real_value is used to read it. Parameters
3306
may be involved.
3307
3308
*/
3309
3310
289
int Interp::read_z(char *line,   //!< string: line of RS274 code being processed
3311
                  int *counter, //!< pointer to a counter for position on the line
3312
                  block_pointer block,  //!< pointer to a block being filled from the line
3313
                  double *parameters)   //!< array of system parameters
3314
{
3315
  double value;
3316
3317
289
  CHKS((line[*counter] != 'z'), NCE_BUG_FUNCTION_SHOULD_NOT_HAVE_BEEN_CALLED);
3318
289
  *counter = (*counter + 1);
3319
289
  CHKS((block->z_flag), NCE_MULTIPLE_Z_WORDS_ON_ONE_LINE);
3320
289
  CHP(read_real_value(line, counter, &value, parameters));
3321
289
  block->z_flag = true;
3322
289
  block->z_number = value;
3323
289
  return INTERP_OK;
3324
}
3325
3326
454
bool Interp::isreadonly(int index)
3327
{
3328
  int i;
3329
10896
  for (i=0; i< _n_readonly_parameters; i++) {
3330
10442
    if (_readonly_parameters[i] == index) return 1;
3331
  }
3332
  return 0;
3333
}