@@ -474,6 +474,43 @@ extern void emcTaskQueueTaskPlanSynchCmd();
474474
475475static EMC_TASK_INTERP interpResumeState = EMC_TASK_INTERP ::IDLE ;
476476static int programStartLine = 0 ; // which line to run program from
477+ // RUN FROM LINE (issue #246): 1 from an AUTO_RUN with a start line until the
478+ // skip ends. While it is set, nothing a skipped line produces -- at any call
479+ // level -- may leave interp_list: a queue-busting wait inside a remap or
480+ // subroutine used to send the queued commands to the machine before the skip
481+ // discarded them, so skipped code half-executed. Read by the interpreter as
482+ // #<_task_skipping> so a remap can skip its own side effects.
483+ extern int _task_skipping; // defined in the interpreter library
484+
485+ static void skip_end (void )
486+ {
487+ if (!_task_skipping) return ;
488+ _task_skipping = 0 ;
489+ programStartLine = 0 ;
490+ }
491+
492+ static void skip_reset (void )
493+ {
494+ _task_skipping = 0 ;
495+ }
496+
497+ // Discard what a skipped line queued: report operator messages (as the skip
498+ // always did), then clear.
499+ static void skip_discard (void )
500+ {
501+ while (interp_list.len () > 0 ) {
502+ auto cmd = interp_list.get ();
503+ if (!cmd) break ;
504+ switch (cmd->_type ) {
505+ case EMC_OPERATOR_ERROR_TYPE :
506+ emcOperatorError (" %s" , static_cast <EMC_OPERATOR_ERROR *>(cmd.get ())->error );
507+ break ;
508+ default :
509+ break ;
510+ }
511+ }
512+ interp_list.clear ();
513+ }
477514// how long the interp list can be
478515
479516int stepping = 0 ;
@@ -495,48 +532,13 @@ static NML_INTERP_LIST mdi_input_queue;
495532#define MAX_MDI_QUEUE 10
496533static int max_mdi_queued_commands = MAX_MDI_QUEUE ;
497534
498- /*
499- checkInterpList(NML_INTERP_LIST *il, EMC_STAT *stat) takes a pointer
500- to an interpreter list and a pointer to the EMC status, pops each NML
501- message off the list, and checks it against limits, resource availability,
502- etc. in the status.
503-
504- It returns 0 if all messages check out, -1 if any of them fail. If one
505- fails, the rest of the list is not checked.
506- */
507- static int checkInterpList (NML_INTERP_LIST * il, EMC_STAT * /* stat*/ )
508- {
509- while (il->len () > 0 ) {
510- auto cmd = il->get ();
511-
512- switch (cmd->_type ) {
513-
514- case EMC_OPERATOR_ERROR_TYPE : {
515- auto error_msg = static_cast <EMC_OPERATOR_ERROR *>(cmd.get ());
516- emcOperatorError (" %s" , error_msg->error );
517- break ;
518- }
519-
520- // FIXME: there was limit checking tests below, see if they were needed
521- case EMC_TRAJ_LINEAR_MOVE_TYPE :
522- break ;
523-
524- case EMC_TRAJ_CIRCULAR_MOVE_TYPE :
525- break ;
526-
527- default :
528- break ;
529- }
530- }
531-
532- return 0 ;
533- }
534535extern int emcTaskMopup ();
535536
536537void readahead_reading (void )
537538{
538539 int readRetval;
539540 int execRetval;
541+ int skipYield = 0 ; // a wait was met while skipping: stop reading this cycle
540542
541543 if (interp_list.len () <= emc_task_interp_max_len) {
542544 int count = 0 ;
@@ -582,6 +584,25 @@ void readahead_reading(void)
582584
583585 emcTaskPlanCommand ((char *) &emcStatus->task .
584586 command);
587+ // RUN FROM LINE: the skip ends before the first
588+ // main-program line at or after the start line runs --
589+ // also when the line before it never ran at level 0
590+ // (start line 1, a %-headed file).
591+ if (_task_skipping && programStartLine > 0
592+ && emcTaskPlanLevel () == 0
593+ && emcStatus->task .readLine >= programStartLine) {
594+ CANON_UPDATE_END_POINT (emcStatus->motion .traj .actualPosition .tran .x ,
595+ emcStatus->motion .traj .actualPosition .tran .y ,
596+ emcStatus->motion .traj .actualPosition .tran .z ,
597+ emcStatus->motion .traj .actualPosition .a ,
598+ emcStatus->motion .traj .actualPosition .b ,
599+ emcStatus->motion .traj .actualPosition .c ,
600+ emcStatus->motion .traj .actualPosition .u ,
601+ emcStatus->motion .traj .actualPosition .v ,
602+ emcStatus->motion .traj .actualPosition .w );
603+ emcTaskPlanSynch ();
604+ skip_end ();
605+ }
585606 // and execute it
586607 execRetval = emcTaskPlanExecute (NULL );
587608 // line number may need update after
@@ -598,6 +619,12 @@ void readahead_reading(void)
598619 || execRetval == INTERP_EXIT ) {
599620 emcStatus->task .interpState =
600621 EMC_TASK_INTERP ::WAITING ;
622+ } else if (execRetval == INTERP_EXECUTE_FINISH && _task_skipping) {
623+ // RUN FROM LINE: a wait inside skipped code must not send
624+ // the skipped commands to the machine. Discard below, do
625+ // not wait, re-read nothing; one wait per task cycle.
626+ emcStatus->task .input_timeout = 0 ;
627+ skipYield = 1 ;
601628 } else if (execRetval == INTERP_EXECUTE_FINISH ) {
602629 // INTERP_EXECUTE_FINISH signifies
603630 // that no more reading should be done until
@@ -621,24 +648,13 @@ void readahead_reading(void)
621648 // throw the results away if we're supposed to
622649 // read
623650 // through it
624- if ( programStartLine != 0 &&
625- emcTaskPlanLevel () == 0 &&
626- ( programStartLine < 0 ||
627- emcTaskPlanLine () <= programStartLine )) {
628- // we're stepping over lines, so check them
629- // for
630- // limits, etc. and clear then out
631- if (0 != checkInterpList (&interp_list,
632- emcStatus)) {
633- // problem with actions, so do same as we
634- // did
635- // for a bad read from emcTaskPlanRead()
636- // above
637- emcStatus->task .interpState =
638- EMC_TASK_INTERP ::WAITING ;
639- }
640- // and clear it regardless
641- interp_list.clear ();
651+ if (_task_skipping) {
652+ // RUN FROM LINE: every block executed while skipping,
653+ // at any call level, is discarded before anything can
654+ // send it (formerly: only main-program lines, after the
655+ // whole line -- remap/subroutine bodies leaked out at
656+ // their waits). Operator messages are still shown.
657+ skip_discard ();
642658 }
643659
644660 if (emcStatus->task .readLine < programStartLine &&
@@ -663,10 +679,12 @@ void readahead_reading(void)
663679 // reset programStartLine so we don't fall into our stepping routines
664680 // if we happen to execute lines before the current point later (due to subroutines).
665681 programStartLine = 0 ;
682+ skip_end ();
666683 }
667684 }
668685
669686 if (count++ < emc_task_interp_max_len
687+ && !skipYield
670688 && emcStatus->task .interpState == EMC_TASK_INTERP ::READING
671689 && interp_list.len () <= emc_task_interp_max_len * 2 /3 ) {
672690 goto interpret_again;
@@ -777,6 +795,7 @@ void readahead_waiting(void)
777795 emcStatus->task .interpState = EMC_TASK_INTERP ::IDLE ;
778796 }
779797 emcStatus->task .readLine = 0 ;
798+ skip_reset (); // run over: never carry "skipping" into MDI or the next run
780799 } else {
781800 // still executing
782801 }
@@ -2188,6 +2207,7 @@ static int emcTaskIssueCommand(NMLmsg * cmd)
21882207
21892208 case EMC_TASK_ABORT_TYPE :
21902209 // abort everything
2210+ skip_reset ();
21912211 emcTaskAbort ();
21922212 // KLUDGE call motion abort before state restore to make absolutely sure no
21932213 // stray restore commands make it down to motion
@@ -2440,6 +2460,8 @@ static int emcTaskIssueCommand(NMLmsg * cmd)
24402460 }
24412461 run_msg = reinterpret_cast <EMC_TASK_PLAN_RUN *>(cmd);
24422462 programStartLine = run_msg->line ;
2463+ skip_reset ();
2464+ _task_skipping = (programStartLine != 0 );
24432465 emcStatus->task .interpState = EMC_TASK_INTERP ::READING ;
24442466 emcStatus->task .task_paused = 0 ;
24452467 retval = 0 ;
0 commit comments