*/ REBINT Emit_Tuple(REBVAL *value, REBYTE *out) /* ** The out array must be large enough to hold longest tuple. ** Longest is: (3 digits + '.') * 11 nums + 1 term => 45 ** ***********************************************************************/ { REBCNT len; REBYTE *tp; REBYTE *start = out; len = VAL_TUPLE_LEN(value); tp = (REBYTE *)VAL_TUPLE(value); for (; len > 0; len--, tp++) { out = Form_Int(out, *tp); *out++ = '.'; } len = VAL_TUPLE_LEN(value); while (len++ < 3) { *out++ = '0'; *out++ = '.'; } *--out = 0; return out-start; }
// // MF_Tuple: C // void MF_Tuple(REB_MOLD *mo, const REBCEL *v, bool form) { UNUSED(form); // "Buffer must be large enough to hold longest tuple. // Longest is: (3 digits + '.') * 11 nums + 1 term => 45" // // !!! ^-- Out of date comments; TUPLE! needs review and replacement. // REBYTE buf[60]; REBCNT len = VAL_TUPLE_LEN(v); const REBYTE *tp = cast(const REBYTE *, VAL_TUPLE(v)); REBYTE *out = buf; for (; len > 0; len--, tp++) { out = Form_Int(out, *tp); *out++ = '.'; } len = VAL_TUPLE_LEN(v); while (len++ < 3) { *out++ = '0'; *out++ = '.'; } *--out = 0; Append_Ascii_Len(mo->series, s_cast(buf), out - buf); }
// // Emit_Tuple: C // // The out array must be large enough to hold longest tuple. // Longest is: (3 digits + '.') * 11 nums + 1 term => 45 // REBINT Emit_Tuple(const REBVAL *value, REBYTE *out) { REBCNT len = VAL_TUPLE_LEN(value); const REBYTE *tp = cast(const REBYTE *, VAL_TUPLE(value)); REBYTE *start = out; for (; len > 0; len--, tp++) { out = Form_Int(out, *tp); *out++ = '.'; } len = VAL_TUPLE_LEN(value); while (len++ < 3) { *out++ = '0'; *out++ = '.'; } *--out = 0; return out-start; }
// // Panic_Core: C // // (va_list by pointer: http://stackoverflow.com/a/3369762/211160) // // Print a failure message and abort. The code adapts to several // different load stages of the system, and uses simpler ways to // report the error when the boot has not progressed enough to // use the more advanced modes. This allows the same interface // to be used for `panic Error_XXX(...)` and `fail (Error_XXX(...))`. // ATTRIBUTE_NO_RETURN void Panic_Core(REBCNT id, REBSER *maybe_frame, va_list *args) { char title[PANIC_TITLE_SIZE]; char message[PANIC_MESSAGE_SIZE]; title[0] = '\0'; message[0] = '\0'; if (maybe_frame) { assert(id == 0); id = ERR_NUM(maybe_frame); } // We are crashing, so a legitimate time to be disabling the garbage // collector. (It won't be turned back on.) GC_Disabled++; if (Reb_Opts && Reb_Opts->crash_dump) { Dump_Info(); Dump_Stack(0, 0); } strncat(title, "PANIC #", PANIC_TITLE_SIZE - 1); Form_Int(b_cast(title + strlen(title)), id); // !!! no bounding... strncat(message, Str_Panic_Directions, PANIC_MESSAGE_SIZE - 1); #if !defined(NDEBUG) // In debug builds, we may have the file and line number to report if // the call to Panic_Core originated from the `panic` macro. But we // will not if the panic is being called from a Make_Error call that // is earlier than errors can be made... if (TG_Erroring_C_File) { Form_Args( b_cast(message + strlen(message)), PANIC_MESSAGE_SIZE - 1 - strlen(message), "C Source File %s, Line %d\n", TG_Erroring_C_File, TG_Erroring_C_Line, NULL ); } #endif if (PG_Boot_Phase < BOOT_LOADED) { strncat(message, title, PANIC_MESSAGE_SIZE - 1); strncat( message, "\n** Boot Error: (string table not decompressed yet)", PANIC_MESSAGE_SIZE - 1 ); } else if (PG_Boot_Phase < BOOT_ERRORS && id < RE_INTERNAL_MAX) { // We are panic'ing on one of the errors that can occur during // boot (e.g. before Make_Error() be assured to run). So we use // the C string constant that was formed by %make-boot.r and // compressed in the boot block. // // Note: These strings currently do not allow arguments. const char *format = cs_cast(BOOT_STR(RS_ERROR, id - RE_INTERNAL_FIRST)); assert(args && !maybe_frame); strncat(message, "\n** Boot Error: ", PANIC_MESSAGE_SIZE - 1); Form_Args_Core( b_cast(message + strlen(message)), PANIC_MESSAGE_SIZE - 1 - strlen(message), format, args ); } else if (PG_Boot_Phase < BOOT_ERRORS && id >= RE_INTERNAL_MAX) { strncat(message, title, PANIC_MESSAGE_SIZE - 1); strncat( message, "\n** Boot Error: (error object table not initialized yet)", PANIC_MESSAGE_SIZE - 1 ); } else { // The system should be theoretically able to make and mold errors. // // !!! If you're trying to panic *during* error molding this // is obviously not going to not work. All errors pertaining to // molding errors should audited to be in the Boot: category. REBVAL error; if (maybe_frame) { assert(!args); Val_Init_Error(&error, maybe_frame); } else { // We aren't explicitly passed a Rebol ERROR! object, but we // consider it "safe" to make one since we're past BOOT_ERRORS Val_Init_Error(&error, Make_Error_Core(id, args)); } Form_Args( b_cast(message + strlen(message)), PANIC_MESSAGE_SIZE - 1 - strlen(message), "%v", &error, NULL ); } OS_CRASH(cb_cast(Str_Panic_Title), cb_cast(message)); // Note that since we crash, we never return so that the caller can run // a va_end on the passed-in args. This is illegal in the general case: // // http://stackoverflow.com/a/587139/211160 DEAD_END; }
*/ void Emit_Date(REB_MOLD *mold, const REBVAL *value_orig) /* ***********************************************************************/ { REBYTE buf[64]; REBYTE *bp = &buf[0]; REBINT tz; REBYTE dash = GET_MOPT(mold, MOPT_SLASH_DATE) ? '/' : '-'; // We don't want to modify the incoming date value we are molding, // so we make a copy that we can tweak during the emit process REBVAL value_buffer = *value_orig; REBVAL *value = &value_buffer; if ( VAL_MONTH(value) == 0 || VAL_MONTH(value) > 12 || VAL_DAY(value) == 0 || VAL_DAY(value) > 31 ) { Append_Unencoded(mold->series, "?date?"); return; } if (VAL_TIME(value) != NO_TIME) Adjust_Date_Zone(value, FALSE); // Punctuation[GET_MOPT(mold, MOPT_COMMA_PT) ? PUNCT_COMMA : PUNCT_DOT] bp = Form_Int(bp, (REBINT)VAL_DAY(value)); *bp++ = dash; memcpy(bp, Month_Names[VAL_MONTH(value)-1], 3); bp += 3; *bp++ = dash; bp = Form_Int_Pad(bp, (REBINT)VAL_YEAR(value), 6, -4, '0'); *bp = 0; Append_Unencoded(mold->series, s_cast(buf)); if (VAL_TIME(value) != NO_TIME) { Append_Byte(mold->series, '/'); Emit_Time(mold, value); if (VAL_ZONE(value) != 0) { bp = &buf[0]; tz = VAL_ZONE(value); if (tz < 0) { *bp++ = '-'; tz = -tz; } else *bp++ = '+'; bp = Form_Int(bp, tz/4); *bp++ = ':'; bp = Form_Int_Pad(bp, (tz&3) * 15, 2, 2, '0'); *bp = 0; Append_Unencoded(mold->series, s_cast(buf)); } } }
*/ void Crash(REBINT id, ...) /* ** Print a failure message and abort. ** ** LATIN1 ONLY!! (For now) ** ** The error is identified by id number, which can reference an ** error message string in the boot strings block. ** ** Note that lower level error messages should not attempt to ** use the %r (mold value) format (uses higher level functions). ** ** See panics.h for list of crash errors. ** ***********************************************************************/ { va_list args; REBYTE buf[CRASH_BUF_SIZE]; REBYTE *msg; REBINT n = 0; va_start(args, id); DISABLE_GC; if (Reb_Opts->crash_dump) { Dump_Info(); Dump_Stack(0, 0); } // "REBOL PANIC #nnn:" COPY_BYTES(buf, Crash_Msgs[CM_ERROR], CRASH_BUF_SIZE); APPEND_BYTES(buf, " #", CRASH_BUF_SIZE); Form_Int(buf + LEN_BYTES(buf), id); APPEND_BYTES(buf, ": ", CRASH_BUF_SIZE); // "REBOL PANIC #nnn: put error message here" // The first few error types only print general error message. // Those errors > RP_STR_BASE have specific error messages (from boot.r). if (id < RP_BOOT_DATA) n = CM_DEBUG; else if (id < RP_INTERNAL) n = CM_BOOT; else if (id < RP_ASSERTS) n = CM_INTERNAL; else if (id < RP_DATATYPE) n = CM_ASSERT; else if (id < RP_STR_BASE) n = CM_DATATYPE; else if (id > RP_STR_BASE + RS_MAX - RS_ERROR) n = CM_DEBUG; // Use the above string or the boot string for the error (in boot.r): msg = (REBYTE*)(n >= 0 ? Crash_Msgs[n] : BOOT_STR(RS_ERROR, id - RP_STR_BASE - 1)); Form_Var_Args(buf + LEN_BYTES(buf), CRASH_BUF_SIZE - 1 - LEN_BYTES(buf), msg, args); n = LEN_BYTES(Crash_Msgs[CM_CONTACT]); if ((LEN_BYTES(buf) + n) < (CRASH_BUF_SIZE - 1)) APPEND_BYTES(buf, Crash_Msgs[CM_CONTACT], n); // Convert to OS-specific char-type: #ifdef disable_for_now //OS_WIDE_CHAR /// win98 does not support it { REBCHR s1[512]; REBCHR s2[2000]; n = TO_OS_STR(s1, Crash_Msgs[CM_ERROR], LEN_BYTES(Crash_Msgs[CM_ERROR])); if (n > 0) s1[n] = 0; // terminate else OS_EXIT(200); // bad conversion n = TO_OS_STR(s2, buf, LEN_BYTES(buf)); if (n > 0) s2[n] = 0; else OS_EXIT(200); OS_CRASH(s1, s2); } #else OS_CRASH(Crash_Msgs[CM_ERROR], buf); #endif }