diff --git a/g2core/Makefile b/g2core/Makefile old mode 100755 new mode 100644 index e4928c15..94aa4a1f --- a/g2core/Makefile +++ b/g2core/Makefile @@ -52,14 +52,17 @@ NEEDS_PRINTF_FLOAT=1 # Now invoke the Motate compile system include $(MOTATE_PATH)/Motate.mk -ifeq ($(DEBUG),1) - DEVICE_DEFINES += DEBUG=1 -endif -ifeq ($(DEBUG),2) - DEVICE_DEFINES += DEBUG=1 IN_DEBUGGER=1 -endif -ifeq ($(DEBUG),3) - DEVICE_DEFINES += DEBUG=1 IN_DEBUGGER=1 DEBUG_SEMIHOSTING=1 +ifeq ($(DEBUG),0) + DEVICE_DEFINES += DEBUG=0 IN_DEBUGGER=0 +endif +ifeq ($(DEBUG),1) + DEVICE_DEFINES += DEBUG=1 IN_DEBUGGER=0 +endif +ifeq ($(DEBUG),2) + DEVICE_DEFINES += DEBUG=1 IN_DEBUGGER=1 endif +#ifeq ($(DEBUG),3) +# DEVICE_DEFINES += DEBUG=1 IN_DEBUGGER=1 DEBUG_SEMIHOSTING=1 +#endif # *** EOF *** diff --git a/g2core/alarm.cpp b/g2core/alarm.cpp index b98e1ff2..5b3c0856 100644 --- a/g2core/alarm.cpp +++ b/g2core/alarm.cpp @@ -230,7 +230,7 @@ stat_t cm_shutdown(const stat_t status, const char *msg) stat_t cm_panic(const stat_t status, const char *msg) { - _debug_trap(msg); + __debug_trap(msg); if (cm->machine_state == MACHINE_PANIC) { // only do this once return (STAT_OK); diff --git a/g2core/g2core.cppproj b/g2core/g2core.cppproj index a4704359..b67c56bb 100644 --- a/g2core/g2core.cppproj +++ b/g2core/g2core.cppproj @@ -1177,7 +1177,7 @@ bin\Makeblock-v9\ True - CONFIG=Makeblock COLOR=0 VERBOSE=1 + CONFIG=Makeblock COLOR=0 VERBOSE=1 DEBUG=2 clean CONFIG=Makeblock Makefile diff --git a/g2core/main.cpp b/g2core/main.cpp index 5ea91111..f3ff45aa 100644 --- a/g2core/main.cpp +++ b/g2core/main.cpp @@ -50,17 +50,19 @@ stat_t status_code; // allocate a variable for the ritorno macro -/************* System Globals For Diagnostics ****************/ +/************* System Globals For Debugging and Diagnostics ****************/ +// See also: util.h for debugging and diagnostics // Using motate pins for profiling -// see https://github.com/synthetos/g2/wiki/Using-Pin-Changes-for-Timing-(and-light-debugging) +// Usage: https://github.com/synthetos/g2/wiki/Using-Pin-Changes-for-Timing-(and-light-debugging) using namespace Motate; OutputPin debug_pin1; OutputPin debug_pin2; OutputPin debug_pin3; -//OutputPin debug_pin4; +OutputPin debug_pin4; +// or these to disable the pin //OutputPin<-1> debug_pin1; //OutputPin<-1> debug_pin2; //OutputPin<-1> debug_pin3; @@ -72,7 +74,7 @@ using namespace Motate; extern OutputPin debug_pin1; extern OutputPin debug_pin2; extern OutputPin debug_pin3; -//extern OutputPin debug_pin4; +extern OutputPin debug_pin4; //extern OutputPin<-1> debug_pin1; //extern OutputPin<-1> debug_pin2; diff --git a/g2core/plan_exec.cpp b/g2core/plan_exec.cpp index 377a7ad3..a2a53804 100644 --- a/g2core/plan_exec.cpp +++ b/g2core/plan_exec.cpp @@ -166,14 +166,11 @@ static stat_t _plan_aline(mpBuf_t *bf, float entry_velocity) mpBlockRuntimeBuf_t* block = mr->p; // set a local planning block so it doesn't change on you mp_calculate_ramps(block, bf, entry_velocity); // (which it will if you don't do this) -#ifdef IN_DEBUGGER // DIAGNOSTIC - if (block->exit_velocity > block->cruise_velocity) { - __asm__("BKPT"); // exit > cruise after calculate_block - } - if (block->head_length < 0.00001 && block->body_length < 0.00001 && block->tail_length < 0.00001) { - __asm__("BKPT"); // zero or negative length block - } -#endif + __debug_trap_if_true((block->exit_velocity > block->cruise_velocity), + "_plan_line() exit velocity > cruise velocity after calculate_ramps()"); + + __debug_trap_if_true((block->head_length < 0.00001 && block->body_length < 0.00001 && block->tail_length < 0.00001), + "_plan_line() zero or negative length block after calculate_ramps()"); bf->buffer_state = MP_BUFFER_PLANNED; //...here bf->plannable = false; @@ -259,10 +256,7 @@ stat_t mp_exec_move() // first-time operations if (bf->buffer_state != MP_BUFFER_RUNNING) { if ((bf->buffer_state < MP_BUFFER_PREPPED) && (cm->motion_state == MOTION_RUN)) { -#ifdef IN_DEBUGGER - __asm__("BKPT"); // mp_exec_move() buffer is not prepped -#endif - // IMPORTANT: We can't rpt_exception from here! + __debug_trap("mp_exec_move() buffer is not prepped"); // IMPORTANT: can't rpt_exception from here! st_prep_null(); return (STAT_NOOP); } @@ -274,9 +268,7 @@ stat_t mp_exec_move() if (bf->buffer_state == MP_BUFFER_PREPPED) { if (cm->motion_state == MOTION_RUN) { -#ifdef IN_DEBUGGER -// __asm__("BKPT"); // we are running but don't have a block planned -#endif + __debug_trap("mp_exec_move() don't have a block planned"); // IMPORTANT: can't rpt_exception from here! } // We need to have it planned. We don't want to do this here, as it // might already be happening in a lower interrupt. @@ -885,7 +877,7 @@ static stat_t _exec_aline_head(mpBuf_t *bf) _init_forward_diffs(mr->entry_velocity, mr->r->cruise_velocity); // <-- sets inital segment_velocity } if (mr->segment_time < MIN_SEGMENT_TIME) { - _debug_trap("mr->segment_time < MIN_SEGMENT_TIME"); + __debug_trap("mr->segment_time < MIN_SEGMENT_TIME (head)"); return(STAT_OK); // exit without advancing position, say we're done } mr->section = SECTION_HEAD; @@ -930,7 +922,7 @@ static stat_t _exec_aline_body(mpBuf_t *bf) mr->segment_velocity = mr->r->cruise_velocity; mr->segment_count = (uint32_t)mr->segments; if (mr->segment_time < MIN_SEGMENT_TIME) { - _debug_trap("mr->segment_time < MIN_SEGMENT_TIME"); + __debug_trap("mr->segment_time < MIN_SEGMENT_TIME (body)"); return(STAT_OK); // exit without advancing position, say we're done } @@ -971,7 +963,7 @@ static stat_t _exec_aline_tail(mpBuf_t *bf) _init_forward_diffs(mr->r->cruise_velocity, mr->r->exit_velocity); // <-- sets inital segment_velocity } if (mr->segment_time < MIN_SEGMENT_TIME) { - _debug_trap("mr->segment_time < MIN_SEGMENT_TIME"); + __debug_trap("mr->segment_time < MIN_SEGMENT_TIME (tail)"); return(STAT_OK); // exit without advancing position, say we're done // return(STAT_MINIMUM_TIME_MOVE); // exit without advancing position } diff --git a/g2core/plan_line.cpp b/g2core/plan_line.cpp index 99ad3328..c9e3ca32 100644 --- a/g2core/plan_line.cpp +++ b/g2core/plan_line.cpp @@ -36,7 +36,6 @@ #include "util.h" #include "spindle.h" #include "settings.h" - #include "xio.h" // using Motate::Timeout; @@ -55,7 +54,9 @@ static void _calculate_jerk(mpBuf_t* bf); static void _calculate_vmaxes(mpBuf_t* bf, const float axis_length[], const float axis_square[]); static void _calculate_junction_vmax(mpBuf_t* bf); + #ifdef __PLANNER_DIAGNOSTICS +#pragma GCC push_options #pragma GCC optimize("O0") // this pragma is required to force the planner to actually set these unused values static void _set_bf_diagnostics(mpBuf_t* bf) { UPDATE_BF_DIAGNOSTICS(bf); @@ -65,6 +66,7 @@ static void _set_bf_diagnostics(mpBuf_t* bf) { static void _set_bf_diagnostics(mpBuf_t* bf) {} #endif + /* Runtime-specific setters and getters * * mp_zero_segment_velocity() - correct velocity in last segment for reporting purposes diff --git a/g2core/plan_zoid.cpp b/g2core/plan_zoid.cpp index 2a6cc99a..a91562cf 100644 --- a/g2core/plan_zoid.cpp +++ b/g2core/plan_zoid.cpp @@ -31,11 +31,11 @@ #include "planner.h" #include "report.h" #include "util.h" -#include "xio.h" // only need for DIAGNOSTICS +//#include "xio.h" // only need for_ramp_exit_logger // DIAGNOSTICS -stat_t _exit_logger(mpBuf_t* bf, const char *msg) +stat_t _ramp_exit_logger(mpBuf_t* bf, const char *msg) { #ifdef __PLANNER_DIAGNOSTICS if (mp_runtime_is_idle()) { // normally the runtime keeps this value fresh @@ -44,32 +44,23 @@ stat_t _exit_logger(mpBuf_t* bf, const char *msg) } #endif - #ifdef IN_DEBUGGER -// insert logger functions here -//static char logbuf[128]; -//static void _logger(const char *msg, const mpBuf_t *bf) // LOG_RETURN with full state dump -//{ -// sprintf(logbuf, "[%2d] %s (%d) mt:%5.2f, L:%1.3f [%1.3f, %1.3f, %1.3f] V:[%1.2f, %1.2f, %1.2f]\n", -// bf->buffer_number, msg, bf->hint, (bf->block_time * 60000), -// bf->length, bf->head_length, bf->body_length, bf->tail_length, -// bf->pv->exit_velocity, bf->cruise_velocity, bf->exit_velocity); -// xio_writeline(logbuf); -//} - #endif +/* insert logger functions here if needed: + // LOG_RETURN with full state dump + #if IN_DEBUGGER == 1 + + static char logbuf[128]; + + sprintf(logbuf, "[%2d] %s (%d) mt:%5.2f, L:%1.3f [%1.3f, %1.3f, %1.3f] V:[%1.2f, %1.2f, %1.2f]\n", + bf->buffer_number, msg, bf->hint, (bf->block_time * 60000), + bf->length, bf->head_length, bf->body_length, bf->tail_length, + bf->pv->exit_velocity, bf->cruise_velocity, bf->exit_velocity); + xio_writeline(logbuf); + #endif +*/ return (STAT_OK); } -#ifndef IN_DEBUGGER -#define TRAP_ZERO(t,m) -#else -#define TRAP_ZERO(t, m) \ - if (fp_ZERO(t)) { \ - rpt_exception(STAT_MINIMUM_LENGTH_MOVE, m); \ - _debug_trap(m); \ - } -#endif - // END DIAGNOSTICS /* local functions */ @@ -134,8 +125,8 @@ stat_t mp_calculate_ramps(mpBlockRuntimeBuf_t* block, mpBuf_t* bf, const float e bf->hint = COMMAND_BLOCK; return (STAT_NOOP); // NOOP status is informative, not actionable } - TRAP_ZERO(bf->length, "zoid() got L=0"); //+++++ Move this outside of zoid - TRAP_ZERO(bf->cruise_velocity, "zoid() got Vc=0"); // move this outside + __debug_trap_if_zero(bf->length, "mp_calculate_ramps() - got L=0"); + __debug_trap_if_zero(bf->cruise_velocity, "mp_calculate_ramps() - got Vc=0"); // Timings from *here* @@ -171,7 +162,7 @@ stat_t mp_calculate_ramps(mpBlockRuntimeBuf_t* block, mpBuf_t* bf, const float e block->body_length = bf->length; block->body_time = block->body_length / block->cruise_velocity; bf->block_time = block->body_time; - return (_exit_logger(bf, "1c")); + return (_ramp_exit_logger(bf, "1c")); } else { // degrade the hint to MIXED_ACCELERATION bf->hint = MIXED_ACCELERATION; @@ -203,7 +194,7 @@ stat_t mp_calculate_ramps(mpBlockRuntimeBuf_t* block, mpBuf_t* bf, const float e block->body_time = block->body_length / block->cruise_velocity; block->tail_time = block->tail_length * 2 / (block->exit_velocity + block->cruise_velocity); bf->block_time = block->body_time + block->tail_time; - return (_exit_logger(bf, "2d")); + return (_ramp_exit_logger(bf, "2d")); } // PERFECT_DECELERATION (1d) single tail segment (deltaV == delta_vmax) @@ -213,7 +204,7 @@ stat_t mp_calculate_ramps(mpBlockRuntimeBuf_t* block, mpBuf_t* bf, const float e block->cruise_velocity = entry_velocity; block->tail_time = block->tail_length * 2 / (block->exit_velocity + block->cruise_velocity); bf->block_time = block->tail_time; - return (_exit_logger(bf, "1d")); + return (_ramp_exit_logger(bf, "1d")); } // Reset entry_changed. We won't likely be changing the next block's entry velocity. @@ -246,7 +237,7 @@ stat_t mp_calculate_ramps(mpBlockRuntimeBuf_t* block, mpBuf_t* bf, const float e block->cruise_velocity = block->exit_velocity; block->head_time = (block->head_length * 2.0) / (entry_velocity + block->cruise_velocity); bf->block_time = block->head_time; - return (_exit_logger(bf, "1a")); + return (_ramp_exit_logger(bf, "1a")); } else { // it's hit the cusp @@ -271,7 +262,7 @@ stat_t mp_calculate_ramps(mpBlockRuntimeBuf_t* block, mpBuf_t* bf, const float e block->head_time = (block->head_length * 2.0) / (entry_velocity + block->cruise_velocity); block->body_time = block->body_length / block->cruise_velocity; bf->block_time = block->head_time + block->body_time; - return (_exit_logger(bf, "2a")); + return (_ramp_exit_logger(bf, "2a")); } } } @@ -303,7 +294,7 @@ stat_t mp_calculate_ramps(mpBlockRuntimeBuf_t* block, mpBuf_t* bf, const float e bf->block_time = block->head_time + block->body_time + block->tail_time; bf->hint = ASYMMETRIC_BUMP; - return (_exit_logger(bf, "2c")); + return (_ramp_exit_logger(bf, "2c")); } // *** Rate-Limited-Fit cases (3) *** @@ -312,14 +303,8 @@ stat_t mp_calculate_ramps(mpBlockRuntimeBuf_t* block, mpBuf_t* bf, const float e // Rate-limited asymmetric cases (3) // compute meet velocity to see if the cruise velocity rises above the entry and/or exit velocities block->cruise_velocity = _get_meet_velocity(entry_velocity, block->exit_velocity, bf->length, bf, block); -#if (0) - TRAP_ZERO(block->cruise_velocity, "zoid() Vc=0 asymmetric HT case"); -#else - if (fp_ZERO(block->cruise_velocity)) { -// return (STAT_MINIMUM_LENGTH_MOVE); // This error case needs to be recovered upstream - __asm__("BKPT"); - } -#endif + __debug_trap_if_zero(block->cruise_velocity, "mp_calculate_ramps() Vc=0 asymmetric HT case"); + // We now store the head/tail lengths we computed in _get_meet_velocity. // treat as a full up and down (head and tail) bf->hint = ASYMMETRIC_BUMP; @@ -337,7 +322,7 @@ stat_t mp_calculate_ramps(mpBlockRuntimeBuf_t* block, mpBuf_t* bf, const float e block->tail_time = (block->tail_length * 2.0) / (block->exit_velocity + block->cruise_velocity); } bf->block_time = block->head_time + block->body_time + block->tail_time; - return (_exit_logger(bf, "3c")); // 550us worst case + return (_ramp_exit_logger(bf, "3c")); // 550us worst case } /**** Planner helpers **** diff --git a/g2core/planner.cpp b/g2core/planner.cpp index 42ecc046..be0e5bef 100644 --- a/g2core/planner.cpp +++ b/g2core/planner.cpp @@ -62,7 +62,7 @@ #include "report.h" #include "util.h" #include "json_parser.h" -#include "xio.h" // DIAGNOSTIC - only needed if xio_writeline() direct prints are used +#include "xio.h" // Allocate planner structures diff --git a/g2core/planner.h b/g2core/planner.h index e90db105..606c2785 100644 --- a/g2core/planner.h +++ b/g2core/planner.h @@ -226,23 +226,6 @@ typedef enum { // code blocks for planning and trapezoid ge ASYMMETRIC_BUMP, // (Ve != Vx) < Vc } blockHint; -/* -typedef enum { - ZOID_EXIT_NULL = 0, - ZOID_EXIT_1a, - ZOID_EXIT_1c, - ZOID_EXIT_1d, - ZOID_EXIT_2a, - ZOID_EXIT_2c, - ZOID_EXIT_2d, - ZOID_EXIT_3c, - ZOID_EXIT_3s, - ZOID_EXIT_3s2, - ZOID_EXIT_3d2, - ZOID_EXIT_3a2 -} zoidExitPoint; -*/ - /*** Most of these factors are the result of a lot of tweaking. Change with caution.***/ #define PLANNER_QUEUE_SIZE ((uint8_t)48) // Suggest 12 min. Limit is 255 @@ -292,7 +275,7 @@ typedef enum { #define Veq2_lo 1.0 #define VELOCITY_ROUGHLY_EQ(v0,v1) ( (v0 > Vthr2) ? fabs(v0-v1) < Veq2_hi : fabs(v0-v1) < Veq2_lo ) -/* Diagnostics */ +/* Planner Diagnostics */ //#define __PLANNER_DIAGNOSTICS // comment this out to drop diagnostics diff --git a/g2core/stepper.cpp b/g2core/stepper.cpp index d8777402..870072d0 100644 --- a/g2core/stepper.cpp +++ b/g2core/stepper.cpp @@ -44,18 +44,9 @@ #include "MotateDebug.h" -/* Note: stepper_debug statements removed 1/16/17 in SHA eb0905ccae03c04f99e6f471cbe029002f0324c6. See earlier commits to recover -// Unless debugging, this should always read "#if 0 && ..." -// DON'T COMMIT with anything else! -// -#if 0 && (IN_DEBUGGER == 1) -template -void stepper_debug(const char (&str)[len]) { Motate::debug.write(str); }; -#else -template -void stepper_debug(const char (&str)[len]) { ; }; -#endif -*/ +/* Note: stepper_debug statements removed 1/16/17 in SHA eb0905ccae03c04f99e6f471cbe029002f0324c6. + * See earlier commits to recover + */ /**** Allocate structures ****/ @@ -67,9 +58,6 @@ static stRunSingleton_t st_run; static void _load_move(void); -// handy macro -//#define _f_to_period(f) (uint16_t)((float)F_CPU / (float)f) - /**** Setup motate ****/ using namespace Motate; diff --git a/g2core/util.h b/g2core/util.h index 75471031..1c4913e7 100644 --- a/g2core/util.h +++ b/g2core/util.h @@ -50,24 +50,6 @@ using Motate::SysTickTimer; /****** Global Scope Variables and Functions ******/ -//*** debug utilities *** - -#pragma GCC push_options -#pragma GCC optimize ("O0") -//#pragma GCC reset_options -inline void _debug_trap(const char *reason) { - // We might be able to put a print here, but it MIGHT interrupt other output - // and might be deep in an ISR, so we had better just _NOP() and hope for the best. - __NOP(); -#ifdef IN_DEBUGGER - __asm__("BKPT"); -#endif -} -#pragma GCC reset_options - -void LAGER(const char * msg); -void LAGER_cm(const char * msg); - //*** vector utilities *** extern float vector[AXES]; // vector of axes for passing to subroutines @@ -178,4 +160,79 @@ inline T avg(const T a,const T b) {return (a+b)/2; } // return count_>1 ? (hold=*t, *t=*(t+(count_-1)), *(t+(count_-1))=hold), c_strreverse(t+1, count_-2), count_ : count_; //} +/*** Debug and DIAGNOSTICS *** + * + * This section collects debug and DIAGNOSTIC functions used by the project. + * + * The debug levels are set in the build line and may be one of: + * - debug is off, IN_DEBUGGER == 0 (See Makefile for the logic) + * DEBUG=0 - debug is off, IN_DEBUGGER == 0 + * DEBUG=1 - debug is on, IN_DEBUGGER == 0 + * DEBUG=2 - debug is on, IN_DEBUGGER == 1. Requires HW debugger to be connected + * DEBUG=3 - debug is on, IN_DEBUGGER == 1. Requires HW debugger and Semihosting to be enabled and running in the debugger + * + * These settings are applied in the Makefile. + * In addition, MotateDebug.h contains the bulk of the Semihosting definitions + * + * The *reason value is provided as it will be shown in the __asm__("BKPT") backtrace, + * or on the __NOP() if a breakpoint is set + * + * Try to use the functions provided below for debug statements to keep the code clean. If these + * are insufficient you can bracket diagnostics like so to enable then for any non-zero debug level: + * + #if IN_DEBUGGER == 1 + if (block->exit_velocity > block->cruise_velocity) { + __asm__("BKPT"); // exit > cruise after calculate_block + } + #endif + * + * ...or add a new debug functions to the ones below + */ + +/* + * _debug_trap() - trap unconditionally + * _debug_trap_if_zero() - trap if floating point value is zero + * _debug_trap_if_true() - trap if condition is true + * + * The 'reason' value will display in GDB (but maybe not in AS7), and can also be passed + * to a downstream logger if these are introduced into the function. + * + * Note that it may be possible to print or generate exceptions in _debug_trap(), but + * it MIGHT interrupt other output, or might have been called deep in an ISR, + * so we had better just _NOP() and hope for the best. + */ +#pragma GCC push_options +#pragma GCC optimize ("O0") + +inline void __debug_trap(const char *reason) { + __NOP(); +#if IN_DEBUGGER == 1 + __asm__("BKPT"); +#endif +} + +inline void __debug_trap_if_zero(float value, const char *reason) { + if (fp_ZERO(value)) { + __NOP(); +#if IN_DEBUGGER == 1 + __asm__("BKPT"); +#endif + } +} + +inline void __debug_trap_if_true(bool condition, const char *reason) { + if (condition) { + __NOP(); +#if IN_DEBUGGER == 1 + __asm__("BKPT"); +#endif + } +} + +#pragma GCC reset_options + +void LAGER(const char * msg); +void LAGER_cm(const char * msg); + + #endif // End of include guard: UTIL_H_ONCE diff --git a/g2core/xio.cpp b/g2core/xio.cpp old mode 100755 new mode 100644 index 8068a421..d67fc25d --- a/g2core/xio.cpp +++ b/g2core/xio.cpp @@ -600,7 +600,7 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { char c = _data[_scan_offset]; if (c == 0) { - _debug_trap("scan ran into NULL"); + __debug_trap("_scanBuffer() scan ran into NULL"); flush(); // consider the connection and all data trashed return false; } @@ -624,7 +624,7 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { ends_line = true; // _at_start_of_line is already true, this is not the first. } } - // prevent going furnther if we are ignoring + // prevent going further if we are ignoring else if (_ignore_until_next_line) { // don't do anything @@ -747,14 +747,14 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { // Either way, _scan_offset is one past the end, so we don't care which. if (_data[_line_start_offset] == 0) { - _debug_trap("read ran into NULL"); + __debug_trap("readline() read ran into NULL"); } // scan past any leftover CR or LF from the previous line while ((_data[_line_start_offset] == '\n') || (_data[_line_start_offset] == '\r')) { _line_start_offset = (_line_start_offset+1)&(_size-1); if (_scan_offset == _line_start_offset) { - _debug_trap("read ran into scan (1)"); + __debug_trap("readline() read ran into scan (1)"); } } @@ -802,7 +802,7 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { if (_data[_read_offset] == 0) { - _debug_trap("read ran into NULL"); + __debug_trap("readline() read ran into NULL"); } // scan past any leftover CR or LF from the previous line @@ -810,7 +810,7 @@ struct LineRXBuffer : RXBuffer<_size, owner_type, char> { while ((c == '\n') || (c == '\r')) { _read_offset = (_read_offset+1)&(_size-1); if (_scan_offset == _read_offset) { - _debug_trap("read ran into scan (2)"); + __debug_trap("readline() read ran into scan (2)"); } // this also counts as the beginning of a line _skip_sections.skip(_read_offset);