Beispiel #1
0
*/  void Dump_Stack(REBINT dsf, REBINT dsp)
/*
***********************************************************************/
{
	REBINT n;
	REBINT m;
	REBVAL *args;

	if (dsf == 0) {
		dsf = DSF;
		dsp = DSP;
	}

	m = dsp - dsf - DSF_SIZE;
	Debug_Fmt(BOOT_STR(RS_STACK, 1), dsp, Get_Word_Name(DSF_WORD(dsf)), m, Get_Type_Name(DSF_FUNC(dsf)));

	if (dsf > 0) {
		if (ANY_FUNC(DSF_FUNC(dsf))) {
			args = BLK_HEAD(VAL_FUNC_ARGS(DSF_FUNC(dsf)));
			m = SERIES_TAIL(VAL_FUNC_ARGS(DSF_FUNC(dsf)));
			for (n = 1; n < m; n++)
				Debug_Fmt("\t%s: %72r", Get_Word_Name(args+n), DSF_ARGS(dsf, n));
		}
		//Debug_Fmt(Str_Stack[2], PRIOR_DSF(dsf));
		if (PRIOR_DSF(dsf) > 0) Dump_Stack(PRIOR_DSF(dsf), dsf-1);
	}

	//for (n = 1; n <= 2; n++) {
	//	Debug_Fmt("  ARG%d: %s %r", n, Get_Type_Name(DSF_ARGS(dsf, n)), DSF_ARGS(dsf, n));
	//}
}
Beispiel #2
0
//
//  Dump_Stack: C
//
// Prints stack counting levels from the passed in number.  Pass 0 to start.
//
void Dump_Stack(REBFRM *f, REBCNT level)
{
    REBINT n;
    REBVAL *arg;
    REBVAL *param;

    Debug_Fmt(""); // newline.

    if (f == NULL) f = FS_TOP;
    if (f == NULL) {
        Debug_Fmt("*STACK[] - NO FRAMES*");
        return;
    }

    Debug_Fmt(
        "STACK[%d](%s) - %d",
        level,
        STR_HEAD(FRM_LABEL(f)),
        f->eval_type // note: this is now an ordinary Reb_Kind, stringify it
    );

    if (NOT(Is_Any_Function_Frame(f))) {
        Debug_Fmt("(no function call pending or in progress)");
        return;
    }

    n = 1;
    arg = FRM_ARG(f, 1);
    param = FUNC_PARAMS_HEAD(f->func);

    for (; NOT_END(param); ++param, ++arg, ++n) {
        Debug_Fmt(
            "    %s: %72r",
            STR_HEAD(VAL_PARAM_SPELLING(param)),
            arg
        );
    }

    if (f->prior)
        Dump_Stack(f->prior, level + 1);
}
Beispiel #3
0
//
//  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;
}
Beispiel #4
0
*/	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
}