*/ void Assert_Series_Term_Core(REBSER *series) /* ***********************************************************************/ { if (Is_Array_Series(series)) { // REB_END values may not be canonized to zero bytes, check type only if (!IS_END(BLK_SKIP(series, series->tail))) { Debug_Fmt("Unterminated blocklike series detected"); Panic_Series(series); } } else { // Non-REBVAL-bearing series must have their terminal as all 0 bytes int n; for (n = 0; n < SERIES_WIDE(series); n++) { if (0 != series->data[series->tail * SERIES_WIDE(series) + n]) { Debug_Fmt("Non-zero byte in terminator of non-block series"); Panic_Series(series); } } } }
// // Panic_Value_Debug: C // // This is a debug-only "error generator", which will hunt through all the // series allocations and panic on the series that contains the value (if // it can find it). This will allow those using Address Sanitizer or // Valgrind to know a bit more about where the value came from. // // Additionally, if it happens to be a void or trash, LOGIC!, BAR!, or NONE! // it will dump out where the initialization happened if that information // was stored. // ATTRIBUTE_NO_RETURN void Panic_Value_Debug( const RELVAL *v, const char *file, int line ) { REBSER *containing = Try_Find_Containing_Series_Debug(v); printf("PANIC VALUE called from %s:%d\n", file, line); fflush(stdout); switch (VAL_TYPE_RAW(v)) { case REB_MAX_VOID: case REB_BLANK: case REB_LOGIC: case REB_BAR: printf( "REBVAL init on tick #%d at %s:%d\n", cast(unsigned int, v->extra.do_count), v->payload.track.filename, v->payload.track.line ); fflush(stdout); break; } printf("Kind=%d\n", cast(int, VAL_TYPE_RAW(v))); fflush(stdout); if (containing) { printf("Containing series for value pointer found, panicking it:\n"); fflush(stdout); Panic_Series(containing); } printf("No containing series for value...panicking to make stack dump:\n"); fflush(stdout); Panic_Array(EMPTY_ARRAY); }
*/ void Assert_Frame_Core(REBSER *frame) /* ***********************************************************************/ { REBINT n; REBVAL *value; REBSER *words; REBVAL *word; REBINT tail; REBVAL *frame_value; // "FRAME!-typed value" at head of "frame" series frame_value = BLK_HEAD(frame); if (!IS_FRAME(frame_value)) Panic_Series(frame); if ((frame == VAL_SERIES(ROOT_ROOT)) || (frame == Task_Series)) { // !!! Currently it is allowed that the root frames not // have a wordlist. This distinct behavior accomodation is // not worth having the variance of behavior, but since // it's there for now... allow it for just those two. if(!FRM_WORD_SERIES(frame)) return; } value = FRM_VALUES(frame); words = FRM_WORD_SERIES(frame); word = FRM_WORDS(frame); tail = SERIES_TAIL(frame); for (n = 0; n < tail; n++, value++, word++) { if (n == 0) { if ( VAL_WORD_SYM(word) != SYM_SELF && VAL_WORD_SYM(word) != SYM_NOT_USED ) { Debug_Fmt("** First slot in frame is not SELF or null symbol"); Panic_Series(frame); } } if (IS_END(word) || IS_END(value)) { Debug_Fmt( "** Early %s end at index: %d", IS_END(word) ? "word" : "value", n ); Panic_Series(frame); } if (!ANY_WORD(word)) { Debug_Fmt("** Non-word in word list, type: %d\n", VAL_TYPE(word)); Panic_Series(words); } if (!VAL_GET_EXT(word, EXT_WORD_TYPED)) { Debug_Fmt("** Frame words contains non-'typed'-word"); Panic_Series(words); } } if (NOT_END(word) || NOT_END(value)) { Debug_Fmt( "** Missing %s end at index: %d type: %d", NOT_END(word) ? "word" : "value", n, VAL_TYPE(word) ); Panic_Series(frame); } }