utils.c
来自「This is a resource based on j2me embedde」· C语言 代码 · 共 2,268 行 · 第 1/5 页
C
2,268 行
/* * @(#)utils.c 1.158 06/10/10 * * Copyright 1990-2008 Sun Microsystems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version * 2 only, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License version 2 for more details (a copy is * included at /legal/license.txt). * * You should have received a copy of the GNU General Public License * version 2 along with this work; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa * Clara, CA 95054 or visit www.sun.com if you need additional * information or have any questions. * */#include "javavm/include/porting/doubleword.h"#include "javavm/include/porting/int.h"#include "javavm/include/porting/time.h"#include "javavm/include/porting/path.h"#include "javavm/include/objects.h"#include "javavm/include/classes.h"#include "javavm/include/clib.h"#include "javavm/include/utils.h"#include "javavm/include/indirectmem.h"#include "javavm/include/preloader.h"#include "javavm/include/localroots.h"#include "javavm/include/common_exceptions.h"#include "javavm/include/stacks.h"#include "javavm/include/path_md.h"#include "javavm/include/globalroots.h"#include "generated/javavm/include/build_defs.h"#include "generated/offsets/java_lang_String.h"#include "generated/offsets/java_lang_Class.h"#include "generated/offsets/java_lang_Boolean.h"#include "generated/offsets/java_lang_Character.h"#include "generated/offsets/java_lang_Float.h"#include "generated/offsets/java_lang_Double.h"#include "generated/offsets/java_lang_Byte.h"#include "generated/offsets/java_lang_Short.h"#include "generated/offsets/java_lang_Integer.h"#include "generated/offsets/java_lang_Long.h"#include "generated/offsets/java_lang_Throwable.h"#ifdef CVM_CLASSLOADING#include "generated/offsets/java_lang_ClassLoader.h"#endif#ifdef CVM_DEBUG#include "generated/offsets/java_lang_Thread.h"#endif#include "jni_util.h"/* * Console I/O. Same as printf, but supports special formats like * %C, %P, and %F. See CVMformatStringVaList for details. * * WARNING: may crash if you pass bad arguments. See CVMformatStringVaList * for details on safety checking limitations. */voidCVMconsolePrintf(const char* format, ...){ va_list argList; char buf[256]; va_start(argList, format); CVMformatStringVaList(buf, sizeof(buf), format, argList); va_end(argList); fprintf(stderr, "%s", buf); fflush(stderr);}/* * Dump an exception using CVMconsolePrintf. Useful for failures during * vm startup and for debugging in gdb. */voidCVMdumpException(CVMExecEnv* ee) { CVMClassBlock* exceptionCb; CVMObjectICell* exceptionICell = CVMID_getGlobalRoot(ee); CVMStringICell* exceptionMessage; /* print the exception class name */ CVMID_objectGetClass(ee, CVMlocalExceptionICell(ee), exceptionCb); CVMconsolePrintf("%C: ", exceptionCb); if (exceptionICell == NULL) { CVMconsolePrintf("backtrace not available\n"); return; } /* Fetch and clear the exception. Required if calling CVMprintStackTrace */ CVMID_icellAssign(ee, exceptionICell, CVMlocalExceptionICell(ee)); CVMclearLocalException(ee); /* print the exception detailedMessage if there is one */ exceptionMessage = CVMID_getGlobalRoot(ee); if (exceptionMessage != NULL) { CVMID_fieldReadRef(ee, exceptionICell, CVMoffsetOfjava_lang_Throwable_detailMessage, exceptionMessage); if (!CVMID_icellIsNull(exceptionMessage)) { JNIEnv* env = CVMexecEnv2JniEnv(ee); const char* str = CVMjniGetStringUTFChars(env, exceptionMessage, NULL); if (str != NULL) { CVMconsolePrintf("%s", str); CVMjniReleaseStringUTFChars(env, exceptionMessage, str); } else { CVMclearLocalException(ee); } } CVMconsolePrintf("\n"); CVMID_freeGlobalRoot(ee, exceptionMessage); } /* print the exception backtrace */ CVMprintStackTrace(ee, exceptionICell, NULL); /* restore the local exception */ CVMID_icellAssign(ee, CVMlocalExceptionICell(ee), exceptionICell); /* delete the global root */ CVMID_freeGlobalRoot(ee, exceptionICell);}/* * Random number generation. * * Standard, well-known linear congruential random generator with * * s(n+1) = 16807 * s(n) mod(2^31 - 1) * * For references, see: * * (1) "Random Number Generators: Good Ones Are Hard to Find", * S.K. Park and K.W. Miller, Communications of the ACM 31:10 * (Oct 1988), * * (2) "Two Fast Implementations of the 'Minimal Standard' Random * Number Generator", David G. Carta, Comm. ACM 33, 1 (Jan 1990), * pp. 87-88. */CVMInt32CVMrandomNext(){ const CVMInt32 a = 16807; const CVMInt32 m = 2147483647; CVMInt32 lastRandom = CVMglobals.lastRandom; /* compute az=2^31p+q */ CVMUint32 lo = a * (CVMInt32)(lastRandom & 0xFFFF); CVMUint32 hi = a * (CVMInt32)((CVMUint32)lastRandom >> 16); lo += (hi & 0x7FFF) << 16; /* if q overflowed, ignore the overflow and increment q */ if (lo > m) { lo &= m; ++lo; } lo += hi >> 15; /* if (p+q) overflowed, ignore the overflow and increment (p+q) */ if (lo > m) { lo &= m; ++lo; } CVMglobals.lastRandom = lo; return lo;}voidCVMrandomInit(){ CVMInt32 seed; CVMInt64 millis = CVMtimeMillis(); seed = CVMlong2Int(millis); if (seed == 0) { seed = 32461; } CVMglobals.lastRandom = seed;}/* * Functions for accessing the debugging flags. All of the following functions * return the previous state of the flag. * * You can pass in more than one flag at a time to any of the functions. */#ifdef CVM_TRACE_ENABLED/* NOTE: CVMcheckDebugFlags() is a macro and is defined in utils.h. */CVMInt32CVMsetDebugFlags(CVMInt32 flags){ CVMInt32 result = CVMcheckDebugFlags(flags); CVMInt32 oldValue = CVMglobals.debugFlags; CVMInt32 newValue = CVMglobals.debugFlags | flags; CVMglobals.debugFlags = newValue; CVMtraceReset(oldValue, newValue); return result;}CVMInt32CVMclearDebugFlags(CVMInt32 flags){ CVMInt32 result = CVMcheckDebugFlags(flags); CVMInt32 oldValue = CVMglobals.debugFlags; CVMInt32 newValue = CVMglobals.debugFlags & ~flags; CVMglobals.debugFlags &= ~flags; CVMtraceReset(oldValue, newValue); return result;}CVMInt32CVMrestoreDebugFlags(CVMInt32 flags, CVMInt32 oldvalue){ CVMInt32 result = CVMcheckDebugFlags(flags); CVMInt32 oldValue = CVMglobals.debugFlags; CVMInt32 newValue = (CVMglobals.debugFlags & ~flags) | oldvalue; CVMglobals.debugFlags = newValue; CVMtraceReset(oldValue, newValue); return result;}#endif /* CVM_TRACE_ENABLED */#if defined(CVM_DEBUG) || defined(CVM_TRACE_ENABLED)void CVMlong2String(CVMInt64 number, char *s, char *limit){#undef MAGIC#define MAGIC 10000000 /* slightly more than (2^64) ^ (1/3) */ int group1, group2, group3; CVMInt64 group1l, group2l, group3l; CVMInt64 magic; char *sign; if (CVMlongGez(number)) { sign = ""; /* number = -number */ number = CVMlongNeg(number); /* this lets -2^63 still work! */ } else { sign = "-"; }#if 0 group3 = -(number % MAGIC); /* low 7 digits */ number = (number + group3)/MAGIC; group2 = -(number % MAGIC); /* next 7 digits */ number = (number + group2)/MAGIC; group1 = -number; /* high 7 digits */#endif magic = CVMint2Long(MAGIC); group3l = CVMlongRem(number, magic); /* low 7 digits */ group3l = CVMlongNeg(group3l); number = CVMlongAdd(number, group3l); number = CVMlongDiv(number, magic); /* truncate middle 7 digits */ group2l = CVMlongRem(number, magic); /* next 7 digits */ group2l = CVMlongNeg(group2l); number = CVMlongAdd(number, group2l); number = CVMlongDiv(number, magic); /* truncate middle 7 digits */ group1l = CVMlongNeg(number); /* high 7 digits */ group1 = CVMlong2Int(group1l); group2 = CVMlong2Int(group2l); group3 = CVMlong2Int(group3l); if (group1 != 0) { (void) sprintf(s, "%s%d%07d%07d", sign, group1, group2, group3); } else if (group2 != 0) { (void) sprintf(s, "%s%d%07d", sign, group2, group3); } else { (void) sprintf(s, "%s%d", sign, group3); }}#endif/* * CVMdumpThread - prints thread name and stack trace. */#ifdef CVM_DEBUGvoidCVMdumpThread(JNIEnv* env){ CVMExecEnv *ee = CVMjniEnv2ExecEnv(env); CVMconsolePrintf("Thread \""); CVMprintThreadName(env, CVMcurrentThreadICell(ee)); CVMconsolePrintf("\"\n");#ifdef CVM_DEBUG_DUMPSTACK CVMdumpStack(&ee->interpreterStack, 0, 0, 0);#endif}static voidCVMdumpThreadFromEENoAlloc(CVMExecEnv* ee){ CVMconsolePrintf("Thread ee=0x%x, ID=%d\n", ee, ee->threadID);#ifdef CVM_DEBUG_DUMPSTACK CVMdumpStack(&ee->interpreterStack, 0, 0, 0);#endif}voidCVMdumpAllThreads(){ CVMExecEnv* ee = CVMgetEE(); CVMsysMutexLock(ee, &CVMglobals.threadLock); CVM_WALK_ALL_THREADS(ee, currentEE, { /* * Ideally, we should be calling CVMdumpThread() here. But we * are not allowed to allocate within CVM_WALK_ALL_THREADS(), so * we call a non-allocating version of a thread dump that does not * print the thread's name. */ CVMdumpThreadFromEENoAlloc(currentEE); CVMconsolePrintf("\n"); }); CVMsysMutexUnlock(ee, &CVMglobals.threadLock);}voidCVMprintThreadName(JNIEnv* env, CVMObjectICell* threadICell){ CVMExecEnv *ee = CVMjniEnv2ExecEnv(env); jchar *charArrayElements; jobject nameString; const char* name; /* mixes local roots and JNI */ CVMID_localrootBegin(ee) { CVMID_localrootDeclare(CVMObjectICell, nameICell); CVMID_fieldReadRef(ee, threadICell, CVMoffsetOfjava_lang_Thread_name, nameICell); if (!CVMID_icellIsNull(nameICell)) { charArrayElements = (*env)->GetCharArrayElements(env, (jcharArray) nameICell, NULL); nameString = (*env)->NewString(env, charArrayElements, (*env)->GetArrayLength(env, (jarray) nameICell)); name = (*env)->GetStringUTFChars(env, nameString, NULL); CVMconsolePrintf("%s", name); (*env)->ReleaseStringUTFChars(env, nameString, name); (*env)->ReleaseCharArrayElements(env, (jcharArray) nameICell, charArrayElements, JNI_ABORT); } else { CVMconsolePrintf("<unnamed thread>"); } } CVMID_localrootEnd();}#endif/* * CVMclassname2String - copies the class name in src to dst, converting * each '/' to '.' in the process. */char*CVMclassname2String(CVMClassTypeID typeID, char *dst, int size){ char *buf = dst; CVMtypeidClassNameToCString(typeID, dst, size); for (; (--size > 0) && (*dst != '\0') ; dst++) { if (*dst == '/') { *dst = '.'; } } return buf;}/* * Returns the size of the utf8 char. */static intCVMutfCharSize(const char* utfstring) { switch ((CVMUint8)utfstring[0] >> 4) { default: return 1; case 0xC: case 0xD: /* 110xxxxx 10xxxxxx */ return 2; case 0xE: /* 1110xxxx 10xxxxxx 10xxxxxx */ return 3; } /* end of switch */}/* * Returns # of unicode chars needed to represent the utf8 string */CVMSizeCVMutfLength(const char* utf8string){ CVMSize length; for (length = 0; *utf8string != 0; length++) { utf8string += CVMutfCharSize(utf8string); } return length;}/* * Copy a utf8 array into a counted unicode array. * Return number of UTF characters moved from the source. * This is to allow a user to re-start the copying at a known * stopping point. */intCVMutfCountedCopyIntoCharArray( const char * utf8Bytes, CVMJavaChar* unicodeChars, CVMSize unicodeLength){ int nutf = 0; while( unicodeLength-- > 0 ){ char utfchar = *utf8Bytes++; CVMJavaChar t; switch ( utfchar & 0xf0 ){ default: *unicodeChars++ = utfchar; nutf+= 1; continue; case 0xC0: case 0xD0: /* 110xxxxx 10xxxxxx */ *unicodeChars++ = ((utfchar&0x1f)<<6) | ((*utf8Bytes++)&0x3f); nutf+= 2; continue;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?