📄 loaderfile.c
字号:
if (n != length) { if (checkEOF) fatalError(KVM_MSG_CLASSFILE_SIZE_DOES_NOT_MATCH); else if (n > 0) return (n); else return (-1); /* eof */ } else { return (n); } } else { struct jarPointerStruct* ds = (struct jarPointerStruct*)ClassFile; int avail; if (pos == -1) pos = ds->dataIndex; avail = ds->dataLen - pos; if (avail < length && checkEOF) /* inconceivable? */{ fatalError(KVM_MSG_CLASSFILE_SIZE_DOES_NOT_MATCH); } else { if (avail) { int readLength = (avail > length) ? length : avail; memcpy(buffer, &ds->data[pos], readLength); ds->dataIndex = pos + readLength; return (readLength); } else { return (-1); } } } return (0);}voidloadBytes(FILEPOINTER_HANDLE ClassFileH, char* buffer, int length){ /* check for eof */ (void)loadBytesInternal(ClassFileH, buffer, -1, length, TRUE);}intloadBytesNoEOFCheck(FILEPOINTER_HANDLE ClassFileH, char* buffer, int pos, int length){ /* don't check for EOF */ return (loadBytesInternal(ClassFileH, buffer, pos, length, FALSE));}int getBytesAvailable(FILEPOINTER_HANDLE ClassFileH){ FILEPOINTER ClassFile = unhand(ClassFileH); if (!ClassFile->isJarFile) { int pos; struct stdioPointerStruct* ds = (struct stdioPointerStruct*)ClassFile; FILE* file = ds->file; pos = ftell(file); if (ds->size == 0 || pos == -1L) { return 0; /* if error state, then just return 0, system will */ /* read byte by byte */ } else { return (ds->size - pos); } } else { struct jarPointerStruct* ds = (struct jarPointerStruct*)ClassFile; return (ds->dataLen - ds->dataIndex); }}voidskipBytes(FILEPOINTER_HANDLE ClassFileH, unsigned long length){ int pos; FILEPOINTER ClassFile = unhand(ClassFileH); if (!ClassFile->isJarFile) { struct stdioPointerStruct* ds = (struct stdioPointerStruct*)ClassFile; FILE* file = ds->file; pos = ftell(file); if (ds->size == 0 || pos == -1) { /* In some kind of error state, just do it byte by byte and the * EOF error will get returned if appropriate. */ while (length-- > 0) { int c = getc(file); if (c == EOF) { fatalError(KVM_MSG_CLASSFILE_SIZE_DOES_NOT_MATCH); } } } else { if (pos + length > (unsigned int)ds->size) { fatalError(KVM_MSG_CLASSFILE_SIZE_DOES_NOT_MATCH); } else { fseek(file, (pos + length), SEEK_SET); } } } else { struct jarPointerStruct* ds = (struct jarPointerStruct*)ClassFile; unsigned int avail = ds->dataLen - ds->dataIndex; if (avail < length) { fatalError(KVM_MSG_CLASSFILE_SIZE_DOES_NOT_MATCH); } else { ds->dataIndex += length; } }}/*========================================================================= * FUNCTION: closeClassfile() * TYPE: private class file load operation * OVERVIEW: Close the given classfile. Ensure that we have * reached the end of the classfile. * INTERFACE: * parameters: file pointer * returns: <nothing> *=======================================================================*/void closeClassfile(FILEPOINTER_HANDLE ClassFileH){ FILEPOINTER ClassFile = unhand(ClassFileH);#if INCLUDEDEBUGCODE if (traceclassloadingverbose) { fprintf(stdout, "Closing classfile\n"); }#endif /* INCLUDEDEBUGCODE */ if (ClassFile->isJarFile) { /* Close the JAR datastream. Don't need to do anything */ } else { /* Close the classfile */ FILE* file = ((struct stdioPointerStruct*)ClassFile)->file; if (file != NULL) { fclose(file); ((struct stdioPointerStruct*)ClassFile)->file = NULL; } }}/*========================================================================= * FUNCTION: InitializeClassLoading() * TYPE: constructor (kind of) * OVERVIEW: Set up the dynamic class loader. * Read the optional environment variable CLASSPATH * and set up the class path for classfile loading * correspondingly. Actual implementation of this * function is platform-dependent. * INTERFACE: * parameters: <none> * returns: nothing directly, but the operation initializes * the global classpath variables. *=======================================================================*/void InitializeClassLoading(){ char* classpath = UserClassPath; int length, pathCount, i; int tableIndex; int previousI; /* Count the number of individual directory paths along CLASSPATH */ length = strlen(classpath); pathCount = 1; for (i = 0; i < length; i++) { if (classpath[i] == PATH_SEPARATOR) pathCount++; } /* We use callocObject() since we'll be allocating new objects to fill * up the table */ ClassPathTable = (POINTERLIST)callocObject(SIZEOF_POINTERLIST(pathCount), GCT_POINTERLIST); makeGlobalRoot((cell**)&ClassPathTable); ClassPathTable->length = pathCount; MaxClassPathTableLength = 0; tableIndex = 0; previousI = 0; for (i = 0; i <= length; i++) { if (classpath[i] == PATH_SEPARATOR || classpath[i] == 0) { struct stat sbuf; /* Create a new string containing the individual directory path. * We prepend either a 'j' (jar file) or 'd' (directory) indicating * the type of classpath element this is. */ unsigned int length = i - previousI; CLASS_PATH_ENTRY result = (CLASS_PATH_ENTRY)mallocBytes( sizeof(struct classPathEntryStruct) + length); /* Copy the name into the result buffer */ memcpy(result->name, classpath + previousI, length); result->name[length] = '\0'; result->type = '\0'; /* indicates a problem */ if (stat(result->name, &sbuf) < 0) { /* No need to do anything */ } else if (S_ISDIR(sbuf.st_mode)) { /* This is a directory */ /* Store the newly created string to the classpath table */ if (length > MaxClassPathTableLength) { MaxClassPathTableLength = length; } result->type = 'd'; }#if JAR_FILES_USE_STDIO else if (openJARFile(result->name, 0, &result->u.jarInfo)) { result->type = 'j'; }#else else { /* This is something we only do for debugging */ long fileLength = sbuf.st_size; FILE* file = fopen(result->name, "rb"); char* data = mmap(0, fileLength, PROT_READ, MAP_SHARED, fileno(file), 0); if (openJARFile(data, fileLength, &result->u.jarInfo)) { result->type = 'j'; } else { /* Not a 'jar' file. Unmap it */ if (data != NULL) { munmap(data, fileLength); } } }#endif /* JAR_FILES_USE_STDIO */ if (result->type == '\0') { /* bad entry */ ClassPathTable->length--; } else { ClassPathTable->data[tableIndex].cellp = (cell*)result; tableIndex++; } previousI = i+1; } } }/*========================================================================= * FUNCTION: FinalizeClassLoading() * TYPE: destructor (kind of) * OVERVIEW: Shut down the dynamic class loader. * Actual implementation of this function is * platform-dependent. * INTERFACE: * parameters: <none> * returns: <nothing> (but closes JAR files as a side-effect) *=======================================================================*/void FinalizeClassLoading() { int paths = ClassPathTable->length; int i; for (i = 0; i < paths; i++) { CLASS_PATH_ENTRY entry = (CLASS_PATH_ENTRY)ClassPathTable->data[i].cellp; if (entry->type == 'j') { closeJARFile(&entry->u.jarInfo); } }}/*========================================================================= * FUNCTION: setFilePointer * TYPE: * OVERVIEW: given a filepointer store it in the global root and return * a file descriptor * INTERFACE (operand stack manipulation): * parameters: filepointer * returns: integer file descriptor *=======================================================================*/int setFilePointer(FILEPOINTER_HANDLE fph){ int i; long length; FILEPOINTER fp; if (filePointerRoot == NULL) { /* This pointerlist maintains a mapping between an integer file * descriptor and filepointers for resource files. Added to support * MIDP changes to ResourceInputStream.java for commonality between KVM * and Project Monty */ filePointerRoot = (POINTERLIST)callocObject(SIZEOF_POINTERLIST(FILE_OBJECT_SIZE), GCT_POINTERLIST); filePointerRoot->length = FILE_OBJECT_SIZE; makeGlobalRoot((cell**)&filePointerRoot); } fp = unhand(fph); length = filePointerRoot->length; for (i = 0; i < length; i++) { if (filePointerRoot->data[i].cellp == NULL) { filePointerRoot->data[i].cellp = (cell*)fp; if (i < length - 1) { return i; } else { break; } } } { const int expansion = FILE_OBJECT_SIZE; int newLength = length + expansion; POINTERLIST tmpList = (POINTERLIST)callocObject(SIZEOF_POINTERLIST(newLength), GCT_POINTERLIST); tmpList->length = newLength; memcpy(tmpList->data, filePointerRoot->data, length << log2CELL); filePointerRoot = tmpList; return i; }}/*========================================================================= * FUNCTION: getFilePointer * TYPE: * OVERVIEW: given a file descriptor, return a file pointer * INTERFACE (operand stack manipulation): * parameters: file descriptor * returns: file pointer *=======================================================================*/FILEPOINTER getFilePointer(int fd){ if (fd == -1 || fd >= filePointerRoot->length) { return NULL; } return (FILEPOINTER)(filePointerRoot->data[fd].cellp);}/*========================================================================= * FUNCTION: clearFilePointer * TYPE: * OVERVIEW: given a file descriptor, clear this entry * INTERFACE (operand stack manipulation): * parameters: file descriptor * returns: nothing *=======================================================================*/void clearFilePointer(int fd){ if (fd == -1 || fd >= filePointerRoot->length) { return; } filePointerRoot->data[fd].cellp = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -