*/ void Init_Mold(REBCNT size) /* ***********************************************************************/ { REBYTE *cp; REBYTE c; REBYTE *dc; Set_Root_Series(TASK_MOLD_LOOP, Make_Block(size/10), cb_cast("mold loop")); Set_Root_Series(TASK_BUF_MOLD, Make_Unicode(size), cb_cast("mold buffer")); // Create quoted char escape table: Char_Escapes = cp = Make_Mem(MAX_ESC_CHAR+1); // cleared for (c = '@'; c <= '_'; c++) *cp++ = c; Char_Escapes[TAB] = '-'; Char_Escapes[LF] = '/'; Char_Escapes['"'] = '"'; Char_Escapes['^'] = '^'; URL_Escapes = cp = Make_Mem(MAX_URL_CHAR+1); // cleared //for (c = 0; c <= MAX_URL_CHAR; c++) if (IS_LEX_DELIMIT(c)) cp[c] = ESC_URL; for (c = 0; c <= ' '; c++) cp[c] = ESC_URL | ESC_FILE; dc = b_cast(";%\"()[]{}<>"); for (c = (REBYTE)LEN_BYTES(dc); c > 0; c--) URL_Escapes[*dc++] = ESC_URL | ESC_FILE; }
// // OS_Delta_Time: C // // Return time difference in microseconds. If base = 0, then // return the counter. If base != 0, compute the time difference. // // Note: Requires high performance timer. // Q: If not found, use timeGetTime() instead ?! // i64 OS_Delta_Time(i64 base, int flags) { LARGE_INTEGER freq; LARGE_INTEGER time; if (!QueryPerformanceCounter(&time)) OS_Crash(cb_cast("Missing resource"), cb_cast("High performance timer")); if (base == 0) return time.QuadPart; // counter (may not be time) QueryPerformanceFrequency(&freq); return ((time.QuadPart - base) * 1000) / (freq.QuadPart / 1000); }
*/ void Display_Backtrace(REBCNT lines) /* ***********************************************************************/ { REBCNT tail; REBCNT i; if (Trace_Limit > 0) { tail = Trace_Buffer->tail; i = tail - 1; for (lines++ ;lines > 0; lines--, i--) { i = Find_Str_Char(Trace_Buffer, 0, i, tail, -1, LF, 0); if (i == NOT_FOUND || i == 0) { i = 0; break; } } if (lines == 0) i += 2; // start of next line Prin_OS_String(BIN_SKIP(Trace_Buffer, i), tail-i, 0); //RESET_SERIES(Trace_Buffer); } else { Out_Str(cb_cast("backtrace not enabled"), 1); } }
*/ ATTRIBUTE_NO_RETURN static void Error_Compression(const z_stream *strm, int ret) /* ** Zlib gives back string error messages. We use them or fall ** back on the integer code if there is no message. ** ***********************************************************************/ { REBVAL arg; if (ret == Z_MEM_ERROR) { // We do not technically know the amount of memory that zlib asked // for and did not get. Hence categorizing it as an "out of memory" // error might be less useful than leaving as a compression error, // but that is what the old code here historically did. raise Error_No_Memory(0); } if (strm->msg) Val_Init_String( &arg, Copy_Bytes(cb_cast(strm->msg), strlen(strm->msg)) ); else SET_INTEGER(&arg, ret); Error_1(RE_BAD_COMPRESSION, &arg); }
*/ void Init_Mold(REBCNT size) /* ***********************************************************************/ { REBYTE *cp; REBYTE c; const REBYTE *dc; Set_Root_Series(TASK_MOLD_LOOP, Make_Block(size/10), "mold loop"); Set_Root_Series(TASK_BUF_MOLD, Make_Unicode(size), "mold buffer"); // Create quoted char escape table: Char_Escapes = cp = ALLOC_ARRAY_ZEROFILL(REBYTE, MAX_ESC_CHAR + 1); for (c = '@'; c <= '_'; c++) *cp++ = c; Char_Escapes[cast(REBYTE, TAB)] = '-'; Char_Escapes[cast(REBYTE, LF)] = '/'; Char_Escapes[cast(REBYTE, '"')] = '"'; Char_Escapes[cast(REBYTE, '^')] = '^'; URL_Escapes = cp = ALLOC_ARRAY_ZEROFILL(REBYTE, MAX_URL_CHAR + 1); //for (c = 0; c <= MAX_URL_CHAR; c++) if (IS_LEX_DELIMIT(c)) cp[c] = ESC_URL; for (c = 0; c <= ' '; c++) cp[c] = ESC_URL | ESC_FILE; dc = cb_cast(";%\"()[]{}<>"); for (c = LEN_BYTES(dc); c > 0; c--) URL_Escapes[*dc++] = ESC_URL | ESC_FILE; }
*/ void Debug_Str(const char *str) /* ** Print a string followed by a newline. ** ***********************************************************************/ { Debug_String(cb_cast(str), UNKNOWN, 0, 1); }
// // OS_Free_Mem: C // // Free memory allocated in this OS environment. (See OS_Alloc_Mem) // void OS_Free_Mem(void *mem) { #ifdef NDEBUG free(mem); #else { char *ptr = cast(char *, mem) - sizeof(REBI64); if (*cast(REBI64 *, ptr) != -1020) { OS_CRASH( cb_cast("OS_Free_Mem() mismatched with allocator!"), cb_cast("Did you mean to use FREE() instead of OS_FREE()?") ); } free(ptr); } #endif }
*/ DEVICE_CMD Read_IO(REBREQ *req) /* ** Low level "raw" standard input function. ** ** The request buffer must be long enough to hold result. ** ** Result is NOT terminated (the actual field has length.) ** ***********************************************************************/ { long total = 0; int len = req->length; if (GET_FLAG(req->modes, RDM_NULL)) { req->common.data[0] = 0; return DR_DONE; } req->actual = 0; if (Std_Inp >= 0) { interrupted = 0; // Perform a processed read or a raw read? #ifndef HAS_SMART_CONSOLE if (Term_IO) total = Read_Line(Term_IO, s_cast(req->common.data), len); else #endif total = read(Std_Inp, req->common.data, len); /* will be restarted in case of signal */ if (total < 0) { req->error = errno; return DR_ERROR; } if (interrupted) { char noop[] = "does[]\n"; APPEND_BYTES_LIMIT(req->common.data, cb_cast(noop), len); total += sizeof(noop); } req->actual = total; } return DR_DONE; }
*/ i64 OS_Delta_Time(i64 base, int flags) /* ** Return time difference in microseconds. If base = 0, then ** return the counter. If base != 0, compute the time difference. ** ** Note: Requires high performance timer. ** Q: If not found, use timeGetTime() instead ?! ** ***********************************************************************/ { LARGE_INTEGER freq; LARGE_INTEGER time; if (!QueryPerformanceCounter(&time)) OS_Crash(cb_cast("Missing resource"), "High performance timer"); if (base == 0) return time.QuadPart; // counter (may not be time) QueryPerformanceFrequency(&freq); return ((time.QuadPart - base) * 1000) / (freq.QuadPart / 1000); }
// // Read_IO: C // // Low level "raw" standard input function. // // The request buffer must be long enough to hold result. // // Result is NOT terminated (the actual field has length.) // DEVICE_CMD Read_IO(REBREQ *req) { long total = 0; int len = req->length; if (GET_FLAG(req->modes, RDM_NULL)) { req->common.data[0] = 0; return DR_DONE; } req->actual = 0; if (Std_Inp >= 0) { interrupted = 0; // Perform a processed read or a raw read? #ifndef HAS_SMART_CONSOLE if (Term_IO) total = Read_Line(Term_IO, s_cast(req->common.data), len); else #endif total = read(Std_Inp, req->common.data, len); /* will be restarted in case of signal */ if (total < 0) { req->error = errno; return DR_ERROR; } if (interrupted) { char noop[] = "does[]\n"; APPEND_BYTES_LIMIT(req->common.data, cb_cast(noop), len); total += sizeof(noop); } req->actual = total; } return DR_DONE; }
*/ void Debug_Line(void) /* ***********************************************************************/ { Debug_String(cb_cast(""), UNKNOWN, 0, 1); }
/* coverity[+kill] */ void Host_Crash(const char *reason) { OS_Crash(cb_cast("REBOL Host Failure"), cb_cast(reason)); }
// // 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; }