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