-/********************** function: utf_nextu2 *********************************
-
- read the next unicode character from the utf string and
- increment the utf-string pointer accordingly
-
-******************************************************************************/
-
-u2 utf_nextu2(char **utf_ptr)
-{
- /* uncompressed unicode character */
- u2 unicode_char = 0;
- /* current position in utf text */
- unsigned char *utf = (unsigned char *) (*utf_ptr);
- /* bytes representing the unicode character */
- unsigned char ch1, ch2, ch3;
- /* number of bytes used to represent the unicode character */
- int len = 0;
-
- switch ((ch1 = utf[0]) >> 4) {
- default: /* 1 byte */
- (*utf_ptr)++;
- return (u2) ch1;
- case 0xC:
- case 0xD: /* 2 bytes */
- if (((ch2 = utf[1]) & 0xC0) == 0x80) {
- unsigned char high = ch1 & 0x1F;
- unsigned char low = ch2 & 0x3F;
- unicode_char = (high << 6) + low;
- len = 2;
- }
- break;
-
- case 0xE: /* 2 or 3 bytes */
- if (((ch2 = utf[1]) & 0xC0) == 0x80) {
- if (((ch3 = utf[2]) & 0xC0) == 0x80) {
- unsigned char low = ch3 & 0x3f;
- unsigned char mid = ch2 & 0x3f;
- unsigned char high = ch1 & 0x0f;
- unicode_char = (((high << 6) + mid) << 6) + low;
- len = 3;
- } else
- len = 2;
- }
- break;
- }
-
- /* update position in utf-text */
- *utf_ptr = (char *) (utf + len);
- return unicode_char;
-}
-
-
-/********************* function: is_valid_utf ********************************
-
- return true if the given string is a valid UTF-8 string
-
- utf_ptr...points to first character
- end_pos...points after last character
-
-******************************************************************************/
-
-static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26};
-
-bool
-is_valid_utf(char *utf_ptr,char *end_pos)
-{
- int bytes;
- int len,i;
- char c;
- unsigned long v;
-
- if (end_pos < utf_ptr) return false;
- bytes = end_pos - utf_ptr;
- while (bytes--) {
- c = *utf_ptr++;
- /*dolog("%c %02x",c,c);*/
- if (!c) return false; /* 0x00 is not allowed */
- if ((c & 0x80) == 0) continue; /* ASCII */
-
- if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
- else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
- else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
- else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
- else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
- else return false; /* invalid leading byte */
-
- if (len > 2) return false; /* Java limitation */
-
- v = (unsigned long)c & (0x3f >> len);
-
- if ((bytes -= len) < 0) return false; /* missing bytes */
-
- for (i = len; i--; ) {
- c = *utf_ptr++;
- /*dolog(" %c %02x",c,c);*/
- if ((c & 0xc0) != 0x80) /* 10xx xxxx */
- return false;
- v = (v<<6) | (c & 0x3f);
- }
-
- /* dolog("v=%d",v);*/
-
- if (v == 0) {
- if (len != 1) return false; /* Java special */
- }
- else {
- /* Sun Java seems to allow overlong UTF-8 encodings */
-
- if (v < min_codepoint[len]) { /* overlong UTF-8 */
- if (!opt_liberalutf)
- fprintf(stderr,"WARNING: Overlong UTF-8 sequence found.\n");
- /* XXX change this to panic? */
- }
- }
-
- /* surrogates in UTF-8 seem to be allowed in Java classfiles */
- /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
-
- /* even these seem to be allowed */
- /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
- }
-
- return true;
-}
-
-/********************* function: is_valid_name *******************************
-
- return true if the given string may be used as a class/field/method name.
- (Currently this only disallows empty strings and control characters.)
-
- NOTE: The string is assumed to have passed is_valid_utf!
-
- utf_ptr...points to first character
- end_pos...points after last character
-
-******************************************************************************/
-
-bool
-is_valid_name(char *utf_ptr,char *end_pos)
-{
- if (end_pos <= utf_ptr) return false; /* disallow empty names */
-
- while (utf_ptr < end_pos) {
- unsigned char c = *utf_ptr++;
-
- if (c < 0x20) return false; /* disallow control characters */
- if (c == 0xc0 && (unsigned char)*utf_ptr == 0x80) return false; /* disallow zero */
- }
- return true;
-}
-
-bool
-is_valid_name_utf(utf *u)
-{
- return is_valid_name(u->text,utf_end(u));
-}
-
-/******************** Function: class_new **************************************
-
- searches for the class with the specified name in the classes hashtable,
- if there is no such class a new classinfo structure is created and inserted
- into the list of classes to be loaded
-
-*******************************************************************************/
-
-classinfo *class_new_intern(utf *classname)
-{
- classinfo *c; /* hashtable element */
- u4 key; /* hashkey computed from classname */
- u4 slot; /* slot in hashtable */
- u2 i;
-
- key = utf_hashkey(classname->text, classname->blength);
- slot = key & (class_hash.size - 1);
- c = class_hash.ptr[slot];
-
- /* search external hash chain for the class */
- while (c) {
- if (c->name->blength == classname->blength) {
- for (i = 0; i < classname->blength; i++)
- if (classname->text[i] != c->name->text[i]) goto nomatch;
-
- /* class found in hashtable */
- return c;
- }
-
- nomatch:
- c = c->hashlink; /* next element in external chain */
- }
-
- /* location in hashtable found, create new classinfo structure */
-
-#if defined(STATISTICS)
- if (opt_stat)
- count_class_infos += sizeof(classinfo);
-#endif
-
- if (initverbose) {
- char logtext[MAXLOGTEXT];
- sprintf(logtext, "Creating class: ");
- utf_sprint_classname(logtext + strlen(logtext), classname);
- log_text(logtext);
- }
-
- c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
- /*c=NEW(classinfo);*/
- c->vmClass = 0;
- c->flags = 0;
- c->name = classname;
- c->packagename = NULL;
- c->cpcount = 0;
- c->cptags = NULL;
- c->cpinfos = NULL;
- c->super = NULL;
- c->sub = NULL;
- c->nextsub = NULL;
- c->interfacescount = 0;
- c->interfaces = NULL;
- c->fieldscount = 0;
- c->fields = NULL;
- c->methodscount = 0;
- c->methods = NULL;
- c->linked = false;
- c->loaded = false;
- c->index = 0;
- c->instancesize = 0;
- c->header.vftbl = NULL;
- c->innerclasscount = 0;
- c->innerclass = NULL;
- c->vftbl = NULL;
- c->initialized = false;
- c->initializing = false;
- c->classvftbl = false;
- c->classUsed = 0;
- c->impldBy = NULL;
- c->classloader = NULL;
- c->sourcefile = NULL;
-
- /* insert class into the hashtable */
- c->hashlink = class_hash.ptr[slot];
- class_hash.ptr[slot] = c;
-
- /* update number of hashtable-entries */
- class_hash.entries++;
-
- if (class_hash.entries > (class_hash.size * 2)) {
-
- /* reorganization of hashtable, average length of
- the external chains is approx. 2 */
-
- u4 i;
- classinfo *c;
- hashtable newhash; /* the new hashtable */
-
- /* create new hashtable, double the size */
- init_hashtable(&newhash, class_hash.size * 2);
- newhash.entries = class_hash.entries;
-
- /* transfer elements to new hashtable */
- for (i = 0; i < class_hash.size; i++) {
- c = (classinfo *) class_hash.ptr[i];
- while (c) {
- classinfo *nextc = c->hashlink;
- u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
-
- c->hashlink = newhash.ptr[slot];
- newhash.ptr[slot] = c;
-
- c = nextc;
- }
- }
-
- /* dispose old table */
- MFREE(class_hash.ptr, void*, class_hash.size);
- class_hash = newhash;
- }
-
- /* Array classes need further initialization. */
- if (c->name->text[0] == '[') {
- /* Array classes are not loaded from classfiles. */
- c->loaded = true;
- class_new_array(c);
- c->packagename = array_packagename;
-
- } else {
- /* Find the package name */
- /* Classes in the unnamed package keep packagename == NULL. */
- char *p = utf_end(c->name) - 1;
- char *start = c->name->text;
- for (;p > start; --p) {
- if (*p == '/') {
- c->packagename = utf_new (start, p - start);
- break;
- }
- }
- }
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- initObjectLock(&c->header);
-#endif
-
- return c;
-}
-
-
-classinfo *class_new(utf *classname)
-{
- classinfo *c;
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- tables_lock();
-#endif
-
- c = class_new_intern(classname);
-
- /* we support eager class loading and linking on demand */
-
- if (opt_eager) {
- classinfo *tc;
- classinfo *tmp;
-
- list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
-
- if (!c->loaded) {
- if (!class_load(c)) {
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- tables_unlock();
-#endif
- return c;
- }
- }
-
- /* link all referenced classes */
-
- tc = list_first(&unlinkedclasses);
-
- while (tc) {
- /* skip the current loaded/linked class */
- if (tc != c) {
- if (!class_link(tc)) {
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- tables_unlock();
-#endif
- return c;
- }
- }
-
- /* we need a tmp variable here, because list_remove sets prev and
- next to NULL */
- tmp = list_next(&unlinkedclasses, tc);
- list_remove(&unlinkedclasses, tc);
- tc = tmp;
- }
-
- if (!c->linked) {
- if (!class_link(c)) {
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- tables_unlock();
-#endif
- return c;
- }
- }
- }
-
-#if defined(USE_THREADS) && defined(NATIVE_THREADS)
- tables_unlock();
-#endif
-
- return c;
-}
-
-
-/******************** Function: class_get **************************************
-
- searches for the class with the specified name in the classes hashtable
- if there is no such class NULL is returned
-
-*******************************************************************************/
-
-classinfo *class_get(utf *classname)
-{
- classinfo *c; /* hashtable element */
- u4 key; /* hashkey computed from classname */
- u4 slot; /* slot in hashtable */
- u2 i;
-
- key = utf_hashkey(classname->text, classname->blength);
- slot = key & (class_hash.size-1);
- c = class_hash.ptr[slot];
-
- /* search external hash-chain */
- while (c) {
- if (c->name->blength == classname->blength) {
- /* compare classnames */
- for (i = 0; i < classname->blength; i++)
- if (classname->text[i] != c->name->text[i])
- goto nomatch;
-
- /* class found in hashtable */
- return c;
- }
-
- nomatch:
- c = c->hashlink;
- }
-
- /* class not found */
- return NULL;
-}
-
-
-/* class_remove ****************************************************************
-
- removes the class entry wth the specified name in the classes hashtable,
- furthermore the class' resources are freed
- if there is no such class false is returned
-
-*******************************************************************************/
-
-bool class_remove(classinfo *c)
-{
- classinfo *tc; /* hashtable element */
- classinfo *pc;
- u4 key; /* hashkey computed from classname */
- u4 slot; /* slot in hashtable */
- u2 i;
-
- key = utf_hashkey(c->name->text, c->name->blength);
- slot = key & (class_hash.size - 1);
- tc = class_hash.ptr[slot];
- pc = NULL;
-
- /* search external hash-chain */
- while (tc) {
- if (tc->name->blength == c->name->blength) {
-
- /* compare classnames */
- for (i = 0; i < c->name->blength; i++)
- if (tc->name->text[i] != c->name->text[i])
- goto nomatch;
-
- /* class found in hashtable */
- if (!pc) {
- class_hash.ptr[slot] = tc->hashlink;
-
- } else {
- pc->hashlink = tc->hashlink;
- }
-
- class_free(tc);
-
- return true;
- }
-
- nomatch:
- pc = tc;
- tc = tc->hashlink;
- }
-
- /* class not found */
- return false;
-}
-
-
-/***************** Function: class_array_of ***********************************
-
- Returns an array class with the given component class.
- The array class is dynamically created if neccessary.
-
-*******************************************************************************/
-
-classinfo *class_array_of(classinfo *component)
-{
- int namelen;
- char *namebuf;
- classinfo *c;
-
- /* Assemble the array class name */
- namelen = component->name->blength;
-
- if (component->name->text[0] == '[') {
- /* the component is itself an array */
- namebuf = DMNEW(char, namelen + 1);
- namebuf[0] = '[';
- memcpy(namebuf + 1, component->name->text, namelen);
- namelen++;
-
- } else {
- /* the component is a non-array class */
- namebuf = DMNEW(char, namelen + 3);
- namebuf[0] = '[';
- namebuf[1] = 'L';
- memcpy(namebuf + 2, component->name->text, namelen);
- namebuf[2 + namelen] = ';';
- namelen += 3;
- }
-
- /* load this class ;-) and link it */
- c = class_new(utf_new(namebuf, namelen));
- c->loaded = 1;
- class_link(c);
-
- return c;
-}
-
-/*************** Function: class_multiarray_of ********************************
-
- Returns an array class with the given dimension and element class.
- The array class is dynamically created if neccessary.
-
-*******************************************************************************/
-
-classinfo *class_multiarray_of(int dim, classinfo *element)
-{
- int namelen;
- char *namebuf;
-
- if (dim < 1)
- panic("Invalid array dimension requested");
-
- /* Assemble the array class name */
- namelen = element->name->blength;
-
- if (element->name->text[0] == '[') {
- /* the element is itself an array */
- namebuf = DMNEW(char, namelen + dim);
- memcpy(namebuf + dim, element->name->text, namelen);
- namelen += dim;
- }
- else {
- /* the element is a non-array class */
- namebuf = DMNEW(char, namelen + 2 + dim);
- namebuf[dim] = 'L';
- memcpy(namebuf + dim + 1, element->name->text, namelen);
- namelen += (2 + dim);
- namebuf[namelen - 1] = ';';
- }
- memset(namebuf, '[', dim);
-
- return class_new(utf_new(namebuf, namelen));
-}
-
-/************************** function: utf_strlen ******************************
-
- determine number of unicode characters in the utf string
-
-*******************************************************************************/
-
-u4 utf_strlen(utf *u)
-{
- char *endpos; /* points behind utf string */
- char *utf_ptr; /* current position in utf text */
- u4 len = 0; /* number of unicode characters */
-
- if (!u) {
- *exceptionptr = new_nullpointerexception();
- return 0;
- }
-
- endpos = utf_end(u);
- utf_ptr = u->text;
-
- while (utf_ptr < endpos) {
- len++;
- /* next unicode character */
- utf_nextu2(&utf_ptr);
- }
-
- if (utf_ptr != endpos)
- /* string ended abruptly */
- panic("illegal utf string");
-
- return len;
-}
-
-