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, ¶m, 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 |
|
} |