Пример #1
0
*/	int main(int argc, char **argv)
/*
***********************************************************************/
{
	char *cmd;

	// Parse command line arguments. Done early. May affect REBOL boot.
	Parse_Args(argc, argv, &Main_Args);

	Print_Str("REBOL 3.0\n");

	REBOL_Init(&Main_Args);

	// Evaluate user input:
	while (TRUE) {
		cmd = Prompt_User();
		REBOL_Do_String(cmd);
		if (!IS_UNSET(DS_TOP)) {
			//if (DSP > 0) {
				if (!IS_ERROR(DS_TOP)) {
					Prin("== ");
					Print_Value(DS_TOP, 0, TRUE);
				} else
					Print_Value(DS_TOP, 0, FALSE);
			//}
		}
		//DS_DROP; // result
	}

	return 0;
}
Пример #2
0
*/  void Out_Value(const REBVAL *value, REBCNT limit, REBOOL mold, REBINT lines)
/*
***********************************************************************/
{
	Print_Value(value, limit, mold); // higher level!
	for (; lines > 0; lines--) Print_OS_Line();
}
Пример #3
0
*/	void Init_Errors(REBVAL *errors)
/*
***********************************************************************/
{
	REBSER *errs;
	REBVAL *val;

	// Create error objects and error type objects:
	*ROOT_ERROBJ = *Get_System(SYS_STANDARD, STD_ERROR);
	errs = Construct_Object(0, VAL_BLK(errors), 0);
	Set_Object(Get_System(SYS_CATALOG, CAT_ERRORS), errs);

	Set_Root_Series(TASK_ERR_TEMPS, Make_Block(3));

	// Create objects for all error types:
	for (val = BLK_SKIP(errs, 1); NOT_END(val); val++) {
		errs = Construct_Object(0, VAL_BLK(val), 0);
		SET_OBJECT(val, errs);
	}

	// Catch top level errors, to provide decent output:
	PUSH_STATE(Top_State, Saved_State);
	if (SET_JUMP(Top_State)) {
		POP_STATE(Top_State, Saved_State);
		DSP++; // Room for return value
		Catch_Error(DS_TOP); // Stores error value here
		Print_Value(DS_TOP, 0, FALSE);
		Crash(RP_NO_CATCH);
	}
	SET_STATE(Top_State, Saved_State);
}
Пример #4
0
*/	RL_API int RL_Do_Binary(REBYTE *bin, REBINT length, REBCNT flags, REBCNT key, RXIARG *result)
/*
**	Evaluate an encoded binary script such as compressed text.
**
**	Returns:
**		The datatype of the result or zero if error in the encoding.
**	Arguments:
**		bin - by default, a REBOL compressed UTF-8 (or ASCII) script.
**		length - the length of the data.
**		flags - special flags (set to zero at this time).
**		key - encoding, encryption, or signature key.
**		result - value returned from evaluation.
**	Notes:
**		As of A104, only compressed scripts are supported, however,
**		rebin, cloaked, signed, and encrypted formats will be supported.
**
***********************************************************************/
{
	REBSER spec = {0};
	REBSER *text;
	REBVAL *val;
#ifdef DUMP_INIT_SCRIPT
	int f;
#endif

	//Cloak(TRUE, code, NAT_SPEC_SIZE, &key[0], 20, TRUE);
	spec.data = bin;
	spec.tail = length;
	text = Decompress(&spec, 0, -1, 10000000, 0);
	if (!text) return FALSE;
	Append_Byte(text, 0);

#ifdef DUMP_INIT_SCRIPT
	f = _open("host-boot.r", _O_CREAT | _O_RDWR, _S_IREAD | _S_IWRITE );
	_write(f, STR_HEAD(text), LEN_BYTES(STR_HEAD(text)));
	_close(f);
#endif

	SAVE_SERIES(text);
	val = Do_String(text->data, flags);
	UNSAVE_SERIES(text);
	if (IS_ERROR(val)) // && (VAL_ERR_NUM(val) != RE_QUIT)) {
		Print_Value(val, 1000, FALSE);

	if (result) {
		*result = Value_To_RXI(val);
		return Reb_To_RXT[VAL_TYPE(val)];
	}
	return 0;
}
Пример #5
0
*/	RL_API int RL_Start(REBYTE *bin, REBINT len, REBYTE *script, REBINT script_len, REBCNT flags)
/*
**	Evaluate the default boot function.
**
**	Returns:
**		Zero on success, otherwise indicates an error occurred.
**	Arguments:
**		bin - optional startup code (compressed), can be null
**		len - length of above bin
**		flags - special flags
**	Notes:
**		This function completes the startup sequence by calling
**		the sys/start function.
**
***********************************************************************/
{
	REBVAL *val;
	REBSER *ser;

	REBOL_STATE state;
	const REBVAL *error;

	REBVAL start_result;

	int result;
	REBVAL out;

	if (bin) {
		ser = Decompress(bin, len, -1, FALSE, FALSE);
		if (!ser) return 1;

		val = BLK_SKIP(Sys_Context, SYS_CTX_BOOT_HOST);
		Val_Init_Binary(val, ser);
	}

	if (script && script_len > 4) {
		/* a 4-byte long payload type at the beginning */
		i32 ptype = 0;
		REBYTE *data = script + sizeof(ptype);
		script_len -= sizeof(ptype);

		memcpy(&ptype, script, sizeof(ptype));

		if (ptype == 1) {/* COMPRESSed data */
			ser = Decompress(data, script_len, -1, FALSE, FALSE);
		} else {
			ser = Make_Binary(script_len);
			if (ser == NULL) {
				OS_FREE(script);
				return 1;
			}
			memcpy(BIN_HEAD(ser), data, script_len);
		}
		OS_FREE(script);

		val = BLK_SKIP(Sys_Context, SYS_CTX_BOOT_EMBEDDED);
		Val_Init_Binary(val, ser);
	}

	PUSH_UNHALTABLE_TRAP(&error, &state);

// The first time through the following code 'error' will be NULL, but...
// `raise Error` can longjmp here, so 'error' won't be NULL *if* that happens!

	if (error) {
		// Save error for EXPLAIN and return it
		*Get_System(SYS_STATE, STATE_LAST_ERROR) = *error;

		Print_Value(error, 1024, FALSE);

		// !!! Whether or not the Rebol interpreter just throws and quits
		// in an error case with a bad error code or breaks you into the
		// console to debug the environment should be controlled by
		// a command line option.  Defaulting to returning an error code
		// seems better, because kicking into an interactive session can
		// cause logging systems to hang.  For now we throw instead of
		// just quietly returning a code if the script fails, but add
		// that option!

		// For RE_HALT and all other errors we return the error
		// number.  Error numbers are not set in stone (currently), but
		// are never zero...which is why we can use 0 for success.
		return VAL_ERR_NUM(error);
	}

	if (Do_Sys_Func_Throws(&out, SYS_CTX_FINISH_RL_START, 0)) {
		#if !defined(NDEBUG)
			if (LEGACY(OPTIONS_EXIT_FUNCTIONS_ONLY))
				raise Error_No_Catch_For_Throw(&out);
		#endif

		if (
			IS_NATIVE(&out) && (
				VAL_FUNC_CODE(&out) == VAL_FUNC_CODE(ROOT_QUIT_NATIVE)
				|| VAL_FUNC_CODE(&out) == VAL_FUNC_CODE(ROOT_EXIT_NATIVE)
			)
		) {
			int status;

			CATCH_THROWN(&out, &out);
			status = Exit_Status_From_Value(&out);

			DROP_TRAP_SAME_STACKLEVEL_AS_PUSH(&state);

			Shutdown_Core();
			OS_EXIT(status);
			DEAD_END;
		}

		raise Error_No_Catch_For_Throw(&out);
	}

	DROP_TRAP_SAME_STACKLEVEL_AS_PUSH(&state);

	// The convention in the API was to return 0 for success.  We use the
	// convention (as for FINISH_INIT_CORE) that any non-UNSET! result from
	// FINISH_RL_START indicates something went wrong.

	if (IS_UNSET(&out))
		result = 0;
	else {
		assert(FALSE); // should not happen (raise an error instead)
		Debug_Fmt("** finish-rl-start returned non-NONE!:");
		Debug_Fmt("%r", &out);
		result = RE_MISC;
	}

	return result;
}
Пример #6
0
//
//  RL_Start: C
// 
// Evaluate the default boot function.
// 
// Returns:
//     Zero on success, otherwise indicates an error occurred.
// Arguments:
//     bin - optional startup code (compressed), can be null
//     len - length of above bin
//     flags - special flags
// Notes:
//     This function completes the startup sequence by calling
//     the sys/start function.
//
RL_API int RL_Start(REBYTE *bin, REBINT len, REBYTE *script, REBINT script_len, REBCNT flags)
{
    REBVAL *val;
    REBSER *ser;

    struct Reb_State state;
    REBCTX *error;
    int error_num;

    REBVAL result;
    VAL_INIT_WRITABLE_DEBUG(&result);

    if (bin) {
        ser = Decompress(bin, len, -1, FALSE, FALSE);
        if (!ser) return 1;

        val = CTX_VAR(Sys_Context, SYS_CTX_BOOT_HOST);
        Val_Init_Binary(val, ser);
    }

    if (script && script_len > 4) {
        /* a 4-byte long payload type at the beginning */
        i32 ptype = 0;
        REBYTE *data = script + sizeof(ptype);
        script_len -= sizeof(ptype);

        memcpy(&ptype, script, sizeof(ptype));

        if (ptype == 1) {/* COMPRESSed data */
            ser = Decompress(data, script_len, -1, FALSE, FALSE);
        } else {
            ser = Make_Binary(script_len);
            if (ser == NULL) {
                OS_FREE(script);
                return 1;
            }
            memcpy(BIN_HEAD(ser), data, script_len);
        }
        OS_FREE(script);

        val = CTX_VAR(Sys_Context, SYS_CTX_BOOT_EMBEDDED);
        Val_Init_Binary(val, ser);
    }

    PUSH_UNHALTABLE_TRAP(&error, &state);

// The first time through the following code 'error' will be NULL, but...
// `fail` can longjmp here, so 'error' won't be NULL *if* that happens!

    if (error) {
        //
        // !!! We are not allowed to ask for a print operation that can take
        // arbitrarily long without allowing for cancellation via Ctrl-C,
        // but here we are wanting to print an error.  If you're printing
        // out an error and get a halt, it won't print the halt.
        //
        REBCTX *halt_error;

        // Save error for WHY?
        //
        REBVAL *last = Get_System(SYS_STATE, STATE_LAST_ERROR);
        Val_Init_Error(last, error);

        PUSH_UNHALTABLE_TRAP(&halt_error, &state);

// The first time through the following code 'error' will be NULL, but...
// `fail` can longjmp here, so 'error' won't be NULL *if* that happens!

        if (halt_error) {
            assert(ERR_NUM(halt_error) == RE_HALT);
            return ERR_NUM(halt_error);
        }

        Print_Value(last, 1024, FALSE);

        DROP_TRAP_SAME_STACKLEVEL_AS_PUSH(&state);

        // !!! When running in a script, whether or not the Rebol interpreter
        // just exits in an error case with a bad error code or breaks you
        // into the console to debug the environment should be controlled by
        // a command line option.  Defaulting to returning an error code
        // seems better, because kicking into an interactive session can
        // cause logging systems to hang.

        // For RE_HALT and all other errors we return the error
        // number.  Error numbers are not set in stone (currently), but
        // are never zero...which is why we can use 0 for success.
        //
        return ERR_NUM(error);
    }

    if (Apply_Only_Throws(
        &result, Sys_Func(SYS_CTX_FINISH_RL_START), END_VALUE
    )) {
        #if !defined(NDEBUG)
            if (LEGACY(OPTIONS_EXIT_FUNCTIONS_ONLY))
                fail (Error_No_Catch_For_Throw(&result));
        #endif

        if (
            IS_FUNCTION_AND(&result, FUNC_CLASS_NATIVE) && (
                VAL_FUNC_CODE(&result) == &N_quit
                || VAL_FUNC_CODE(&result) == &N_exit
            )
        ) {
            int status;

            CATCH_THROWN(&result, &result);
            status = Exit_Status_From_Value(&result);

            DROP_TRAP_SAME_STACKLEVEL_AS_PUSH(&state);

            Shutdown_Core();
            OS_EXIT(status);
            DEAD_END;
        }

        fail (Error_No_Catch_For_Throw(&result));
    }

    DROP_TRAP_SAME_STACKLEVEL_AS_PUSH(&state);

    // The convention in the API was to return 0 for success.  We use the
    // convention (as for FINISH_INIT_CORE) that any non-UNSET! result from
    // FINISH_RL_START indicates something went wrong.

    if (IS_UNSET(&result))
        error_num = 0; // no error
    else {
        assert(FALSE); // should not happen (raise an error instead)
        Debug_Fmt("** finish-rl-start returned non-NONE!:");
        Debug_Fmt("%r", &result);
        error_num = RE_MISC;
    }

    return error_num;
}