3 Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
4 R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
5 M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
6 P. Tomsich, J. Wenninger
8 This file is part of CACAO.
10 This program is free software; you can redistribute it and/or
11 modify it under the terms of the GNU General Public License as
12 published by the Free Software Foundation; either version 2, or (at
13 your option) any later version.
15 This program is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
25 Contact: cacao@complang.tuwien.ac.at
27 Authors: Reinhard Grafl
32 Contains support functions for:
33 - Reading of Java class files
36 - additional support functions
38 $Id: tables.c 1445 2004-11-05 13:55:33Z twisti $
47 #include <sys/types.h>
51 #include "exceptions.h"
58 #include "statistics.h"
59 #include "threads/thread.h"
60 #include "threads/locks.h"
61 #include "toolbox/logging.h"
62 #include "toolbox/memory.h"
65 hashtable utf_hash; /* hashtable for utf8-symbols */
66 hashtable string_hash; /* hashtable for javastrings */
67 hashtable class_hash; /* hashtable for classes */
69 list unlinkedclasses; /* this is only used for eager class loading */
72 /******************************************************************************
73 *********************** hashtable functions **********************************
74 ******************************************************************************/
76 /* hashsize must be power of 2 */
78 #define UTF_HASHSTART 16384 /* initial size of utf-hash */
79 #define HASHSTART 2048 /* initial size of javastring and class-hash */
82 /******************** function: init_hashtable ******************************
84 Initializes a hashtable structure and allocates memory.
85 The parameter size specifies the initial size of the hashtable.
87 *****************************************************************************/
89 void init_hashtable(hashtable *hash, u4 size)
95 hash->ptr = MNEW(void*, size);
98 for (i = 0; i < size; i++) hash->ptr[i] = NULL;
102 /*********************** function: tables_init *****************************
104 creates hashtables for symboltables
105 (called once at startup)
107 *****************************************************************************/
111 init_hashtable(&utf_hash, UTF_HASHSTART); /* hashtable for utf8-symbols */
112 init_hashtable(&string_hash, HASHSTART); /* hashtable for javastrings */
113 init_hashtable(&class_hash, HASHSTART); /* hashtable for classes */
116 /* list_init(&unlinkedclasses, OFFSET(classinfo, listnode)); */
118 #if defined(STATISTICS)
120 count_utf_len += sizeof(utf*) * utf_hash.size;
125 /********************** function: tables_close ******************************
127 free memory for hashtables
129 *****************************************************************************/
137 /* dispose utf symbols */
138 for (i = 0; i < utf_hash.size; i++) {
141 /* process elements in external hash chain */
142 utf *nextu = u->hashlink;
143 MFREE(u->text, u1, u->blength);
149 /* dispose javastrings */
150 for (i = 0; i < string_hash.size; i++) {
151 s = string_hash.ptr[i];
153 /* process elements in external hash chain */
154 literalstring *nexts = s->hashlink;
155 literalstring_free(s->string);
156 FREE(s, literalstring);
161 /* dispose hashtable structures */
162 MFREE(utf_hash.ptr, void*, utf_hash.size);
163 MFREE(string_hash.ptr, void*, string_hash.size);
164 MFREE(class_hash.ptr, void*, class_hash.size);
168 /********************* function: utf_display *********************************
170 write utf symbol to stdout (debugging purposes)
172 ******************************************************************************/
174 void utf_display(utf *u)
176 char *endpos = utf_end(u); /* points behind utf string */
177 char *utf_ptr = u->text; /* current position in utf text */
182 while (utf_ptr < endpos) {
183 /* read next unicode character */
184 u2 c = utf_nextu2(&utf_ptr);
185 if (c >= 32 && c <= 127) printf("%c", c);
193 /********************* function: utf_display *********************************
195 write utf symbol to stdout (debugging purposes)
197 ******************************************************************************/
199 void utf_display_classname(utf *u)
201 char *endpos = utf_end(u); /* points behind utf string */
202 char *utf_ptr = u->text; /* current position in utf text */
207 while (utf_ptr < endpos) {
208 /* read next unicode character */
209 u2 c = utf_nextu2(&utf_ptr);
210 if (c == '/') c = '.';
211 if (c >= 32 && c <= 127) printf("%c", c);
219 /************************* function: log_utf *********************************
223 ******************************************************************************/
227 char buf[MAXLOGTEXT];
233 /********************** function: log_plain_utf ******************************
235 log utf symbol (without printing "LOG: " and newline)
237 ******************************************************************************/
239 void log_plain_utf(utf *u)
241 char buf[MAXLOGTEXT];
243 dolog_plain("%s", buf);
247 /************************ function: utf_sprint *******************************
249 write utf symbol into c-string (debugging purposes)
251 ******************************************************************************/
253 void utf_sprint(char *buffer, utf *u)
255 char *endpos = utf_end(u); /* points behind utf string */
256 char *utf_ptr = u->text; /* current position in utf text */
257 u2 pos = 0; /* position in c-string */
259 while (utf_ptr < endpos)
260 /* copy next unicode character */
261 buffer[pos++] = utf_nextu2(&utf_ptr);
263 /* terminate string */
268 /************************ function: utf_sprint_classname *********************
270 write utf symbol into c-string (debugging purposes)
272 ******************************************************************************/
274 void utf_sprint_classname(char *buffer, utf *u)
276 char *endpos = utf_end(u); /* points behind utf string */
277 char *utf_ptr = u->text; /* current position in utf text */
278 u2 pos = 0; /* position in c-string */
280 while (utf_ptr < endpos) {
281 /* copy next unicode character */
282 u2 c = utf_nextu2(&utf_ptr);
283 if (c == '/') c = '.';
287 /* terminate string */
292 /********************* Funktion: utf_fprint **********************************
294 write utf symbol into file
296 ******************************************************************************/
298 void utf_fprint(FILE *file, utf *u)
300 char *endpos = utf_end(u); /* points behind utf string */
301 char *utf_ptr = u->text; /* current position in utf text */
306 while (utf_ptr < endpos) {
307 /* read next unicode character */
308 u2 c = utf_nextu2(&utf_ptr);
310 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
311 else fprintf(file, "?");
316 /********************* Funktion: utf_fprint **********************************
318 write utf symbol into file
320 ******************************************************************************/
322 void utf_fprint_classname(FILE *file, utf *u)
324 char *endpos = utf_end(u); /* points behind utf string */
325 char *utf_ptr = u->text; /* current position in utf text */
330 while (utf_ptr < endpos) {
331 /* read next unicode character */
332 u2 c = utf_nextu2(&utf_ptr);
333 if (c == '/') c = '.';
335 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
336 else fprintf(file, "?");
341 /****************** internal function: utf_hashkey ***************************
343 The hashkey is computed from the utf-text by using up to 8 characters.
344 For utf-symbols longer than 15 characters 3 characters are taken from
345 the beginning and the end, 2 characters are taken from the middle.
347 ******************************************************************************/
349 #define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
350 #define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
352 static u4 utf_hashkey(char *text, u4 length)
354 char *start_pos = text; /* pointer to utf text */
359 case 0: /* empty string */
362 case 1: return fbs(0);
363 case 2: return fbs(0) ^ nbs(3);
364 case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
365 case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
366 case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
367 case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
368 case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
369 case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
376 return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
385 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
394 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
406 return a ^ nbs(9) ^ nbs(10);
418 return a ^ nbs(9) ^ nbs(10);
429 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
440 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
442 default: /* 3 characters from beginning */
448 /* 2 characters from middle */
449 text = start_pos + (length / 2);
454 /* 3 characters from end */
455 text = start_pos + length - 4;
460 return a ^ nbs(10) ^ nbs(11);
465 /*************************** function: utf_hashkey ***************************
467 compute the hashkey of a unicode string
469 ******************************************************************************/
471 u4 unicode_hashkey(u2 *text, u2 len)
473 return utf_hashkey((char*) text, len);
477 /************************ function: utf_new **********************************
479 Creates a new utf-symbol, the text of the symbol is passed as a
480 u1-array. The function searches the utf-hashtable for a utf-symbol
481 with this text. On success the element returned, otherwise a new
482 hashtable element is created.
484 If the number of entries in the hashtable exceeds twice the size of the
485 hashtable slots a reorganization of the hashtable is done and the utf
486 symbols are copied to a new hashtable with doubled size.
488 ******************************************************************************/
490 utf *utf_new_intern(char *text, u2 length)
492 u4 key; /* hashkey computed from utf-text */
493 u4 slot; /* slot in hashtable */
494 utf *u; /* hashtable element */
502 key = utf_hashkey(text, length);
503 slot = key & (utf_hash.size-1);
504 u = utf_hash.ptr[slot];
506 /* search external hash chain for utf-symbol */
508 if (u->blength == length) {
510 /* compare text of hashtable elements */
511 for (i = 0; i < length; i++)
512 if (text[i] != u->text[i]) goto nomatch;
516 count_utf_new_found++;
518 /* log_text("symbol found in hash table");*/
519 /* symbol found in hashtable */
530 u = u->hashlink; /* next element in external chain */
535 count_utf_len += sizeof(utf) + length;
538 /* location in hashtable found, create new utf element */
540 u->blength = length; /* length in bytes of utfstring */
541 u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain */
542 u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
543 memcpy(u->text, text, length); /* copy utf-text */
544 u->text[length] = '\0';
545 utf_hash.ptr[slot] = u; /* insert symbol into table */
547 utf_hash.entries++; /* update number of entries */
549 if (utf_hash.entries > (utf_hash.size * 2)) {
551 /* reorganization of hashtable, average length of
552 the external chains is approx. 2 */
556 hashtable newhash; /* the new hashtable */
558 /* create new hashtable, double the size */
559 init_hashtable(&newhash, utf_hash.size * 2);
560 newhash.entries = utf_hash.entries;
564 count_utf_len += sizeof(utf*) * utf_hash.size;
567 /* transfer elements to new hashtable */
568 for (i = 0; i < utf_hash.size; i++) {
569 u = (utf *) utf_hash.ptr[i];
571 utf *nextu = u->hashlink;
572 u4 slot = utf_hashkey(u->text, u->blength) & (newhash.size - 1);
574 u->hashlink = (utf *) newhash.ptr[slot];
575 newhash.ptr[slot] = u;
577 /* follow link in external hash chain */
582 /* dispose old table */
583 MFREE(utf_hash.ptr, void*, utf_hash.size);
591 utf *utf_new(char *text, u2 length)
595 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
599 r = utf_new_intern(text, length);
601 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
609 /********************* function: utf_new_char ********************************
611 creates a new utf symbol, the text for this symbol is passed
612 as a c-string ( = char* )
614 ******************************************************************************/
616 utf *utf_new_char(char *text)
618 return utf_new(text, strlen(text));
622 /********************* function: utf_new_char ********************************
624 creates a new utf symbol, the text for this symbol is passed
625 as a c-string ( = char* )
626 "." characters are going to be replaced by "/". since the above function is
627 used often, this is a separte function, instead of an if
629 ******************************************************************************/
631 utf *utf_new_char_classname(char *text)
633 if (strchr(text, '.')) {
634 char *txt = strdup(text);
635 char *end = txt + strlen(txt);
638 for (c = txt; c < end; c++)
639 if (*c == '.') *c = '/';
640 tmpRes = utf_new(txt, strlen(txt));
645 return utf_new(text, strlen(text));
649 /************************** Funktion: utf_show ******************************
651 writes the utf symbols in the utfhash to stdout and
652 displays the number of external hash chains grouped
653 according to the chainlength
656 *****************************************************************************/
661 #define CHAIN_LIMIT 20 /* limit for seperated enumeration */
663 u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
664 u4 max_chainlength = 0; /* maximum length of the chains */
665 u4 sum_chainlength = 0; /* sum of the chainlengths */
666 u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
669 printf ("UTF-HASH:\n");
671 /* show element of utf-hashtable */
672 for (i=0; i<utf_hash.size; i++) {
673 utf *u = utf_hash.ptr[i];
675 printf ("SLOT %d: ", (int) i);
687 printf ("UTF-HASH: %d slots for %d entries\n",
688 (int) utf_hash.size, (int) utf_hash.entries );
691 if (utf_hash.entries == 0)
694 printf("chains:\n chainlength number of chains %% of utfstrings\n");
696 for (i=0;i<CHAIN_LIMIT;i++)
699 /* count numbers of hashchains according to their length */
700 for (i=0; i<utf_hash.size; i++) {
702 utf *u = (utf*) utf_hash.ptr[i];
705 /* determine chainlength */
711 /* update sum of all chainlengths */
712 sum_chainlength+=chain_length;
714 /* determine the maximum length of the chains */
715 if (chain_length>max_chainlength)
716 max_chainlength = chain_length;
718 /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
719 if (chain_length>=CHAIN_LIMIT) {
720 beyond_limit+=chain_length;
721 chain_length=CHAIN_LIMIT-1;
724 /* update number of hashchains of current length */
725 chain_count[chain_length]++;
728 /* display results */
729 for (i=1;i<CHAIN_LIMIT-1;i++)
730 printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/utf_hash.entries));
732 printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/utf_hash.entries);
735 printf("max. chainlength:%5d\n",max_chainlength);
737 /* avg. chainlength = sum of chainlengths / number of chains */
738 printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (utf_hash.size-chain_count[0]));
741 /******************************************************************************
742 *********************** Misc support functions ********************************
743 ******************************************************************************/
746 /******************** Function: desc_to_type **********************************
748 Determines the corresponding Java base data type for a given type
751 ******************************************************************************/
753 u2 desc_to_type(utf *descriptor)
755 char *utf_ptr = descriptor->text; /* current position in utf text */
756 char logtext[MAXLOGTEXT];
758 if (descriptor->blength < 1) panic("Type-Descriptor is empty string");
760 switch (*utf_ptr++) {
765 case 'Z': return TYPE_INT;
766 case 'D': return TYPE_DOUBLE;
767 case 'F': return TYPE_FLOAT;
768 case 'J': return TYPE_LONG;
770 case '[': return TYPE_ADDRESS;
773 sprintf(logtext, "Invalid Type-Descriptor: ");
774 utf_sprint(logtext+strlen(logtext), descriptor);
781 /********************** Function: desc_typesize *******************************
783 Calculates the lenght in bytes needed for a data element of the type given
784 by its type descriptor.
786 ******************************************************************************/
788 u2 desc_typesize(utf *descriptor)
790 switch (desc_to_type(descriptor)) {
791 case TYPE_INT: return 4;
792 case TYPE_LONG: return 8;
793 case TYPE_FLOAT: return 4;
794 case TYPE_DOUBLE: return 8;
795 case TYPE_ADDRESS: return sizeof(voidptr);
801 /********************** function: utf_nextu2 *********************************
803 read the next unicode character from the utf string and
804 increment the utf-string pointer accordingly
806 ******************************************************************************/
808 u2 utf_nextu2(char **utf_ptr)
810 /* uncompressed unicode character */
812 /* current position in utf text */
813 unsigned char *utf = (unsigned char *) (*utf_ptr);
814 /* bytes representing the unicode character */
815 unsigned char ch1, ch2, ch3;
816 /* number of bytes used to represent the unicode character */
819 switch ((ch1 = utf[0]) >> 4) {
820 default: /* 1 byte */
824 case 0xD: /* 2 bytes */
825 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
826 unsigned char high = ch1 & 0x1F;
827 unsigned char low = ch2 & 0x3F;
828 unicode_char = (high << 6) + low;
833 case 0xE: /* 2 or 3 bytes */
834 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
835 if (((ch3 = utf[2]) & 0xC0) == 0x80) {
836 unsigned char low = ch3 & 0x3f;
837 unsigned char mid = ch2 & 0x3f;
838 unsigned char high = ch1 & 0x0f;
839 unicode_char = (((high << 6) + mid) << 6) + low;
847 /* update position in utf-text */
848 *utf_ptr = (char *) (utf + len);
853 /********************* function: is_valid_utf ********************************
855 return true if the given string is a valid UTF-8 string
857 utf_ptr...points to first character
858 end_pos...points after last character
860 ******************************************************************************/
862 static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26};
865 is_valid_utf(char *utf_ptr,char *end_pos)
872 if (end_pos < utf_ptr) return false;
873 bytes = end_pos - utf_ptr;
876 /*dolog("%c %02x",c,c);*/
877 if (!c) return false; /* 0x00 is not allowed */
878 if ((c & 0x80) == 0) continue; /* ASCII */
880 if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
881 else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
882 else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
883 else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
884 else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
885 else return false; /* invalid leading byte */
887 if (len > 2) return false; /* Java limitation */
889 v = (unsigned long)c & (0x3f >> len);
891 if ((bytes -= len) < 0) return false; /* missing bytes */
893 for (i = len; i--; ) {
895 /*dolog(" %c %02x",c,c);*/
896 if ((c & 0xc0) != 0x80) /* 10xx xxxx */
898 v = (v<<6) | (c & 0x3f);
901 /* dolog("v=%d",v);*/
904 if (len != 1) return false; /* Java special */
907 /* Sun Java seems to allow overlong UTF-8 encodings */
909 if (v < min_codepoint[len]) { /* overlong UTF-8 */
911 fprintf(stderr,"WARNING: Overlong UTF-8 sequence found.\n");
912 /* XXX change this to panic? */
916 /* surrogates in UTF-8 seem to be allowed in Java classfiles */
917 /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
919 /* even these seem to be allowed */
920 /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
926 /********************* function: is_valid_name *******************************
928 return true if the given string may be used as a class/field/method name.
929 (Currently this only disallows empty strings and control characters.)
931 NOTE: The string is assumed to have passed is_valid_utf!
933 utf_ptr...points to first character
934 end_pos...points after last character
936 ******************************************************************************/
939 is_valid_name(char *utf_ptr,char *end_pos)
941 if (end_pos <= utf_ptr) return false; /* disallow empty names */
943 while (utf_ptr < end_pos) {
944 unsigned char c = *utf_ptr++;
946 if (c < 0x20) return false; /* disallow control characters */
947 if (c == 0xc0 && (unsigned char)*utf_ptr == 0x80) return false; /* disallow zero */
953 is_valid_name_utf(utf *u)
955 return is_valid_name(u->text,utf_end(u));
958 /******************** Function: class_new **************************************
960 searches for the class with the specified name in the classes hashtable,
961 if there is no such class a new classinfo structure is created and inserted
962 into the list of classes to be loaded
964 *******************************************************************************/
966 classinfo *class_new_intern(utf *classname)
968 classinfo *c; /* hashtable element */
969 u4 key; /* hashkey computed from classname */
970 u4 slot; /* slot in hashtable */
973 key = utf_hashkey(classname->text, classname->blength);
974 slot = key & (class_hash.size - 1);
975 c = class_hash.ptr[slot];
977 /* search external hash chain for the class */
979 if (c->name->blength == classname->blength) {
980 for (i = 0; i < classname->blength; i++)
981 if (classname->text[i] != c->name->text[i]) goto nomatch;
983 /* class found in hashtable */
988 c = c->hashlink; /* next element in external chain */
991 /* location in hashtable found, create new classinfo structure */
993 #if defined(STATISTICS)
995 count_class_infos += sizeof(classinfo);
999 char logtext[MAXLOGTEXT];
1000 sprintf(logtext, "Creating class: ");
1001 utf_sprint_classname(logtext + strlen(logtext), classname);
1005 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
1006 /*c=NEW(classinfo);*/
1009 c->name = classname;
1010 c->packagename = NULL;
1017 c->interfacescount = 0;
1018 c->interfaces = NULL;
1021 c->methodscount = 0;
1026 c->instancesize = 0;
1027 c->header.vftbl = NULL;
1028 c->innerclasscount = 0;
1029 c->innerclass = NULL;
1031 c->initialized = false;
1032 c->initializing = false;
1033 c->classvftbl = false;
1036 c->classloader = NULL;
1037 c->sourcefile = NULL;
1039 /* insert class into the hashtable */
1040 c->hashlink = class_hash.ptr[slot];
1041 class_hash.ptr[slot] = c;
1043 /* update number of hashtable-entries */
1044 class_hash.entries++;
1046 if (class_hash.entries > (class_hash.size * 2)) {
1048 /* reorganization of hashtable, average length of
1049 the external chains is approx. 2 */
1053 hashtable newhash; /* the new hashtable */
1055 /* create new hashtable, double the size */
1056 init_hashtable(&newhash, class_hash.size * 2);
1057 newhash.entries = class_hash.entries;
1059 /* transfer elements to new hashtable */
1060 for (i = 0; i < class_hash.size; i++) {
1061 c = (classinfo *) class_hash.ptr[i];
1063 classinfo *nextc = c->hashlink;
1064 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
1066 c->hashlink = newhash.ptr[slot];
1067 newhash.ptr[slot] = c;
1073 /* dispose old table */
1074 MFREE(class_hash.ptr, void*, class_hash.size);
1075 class_hash = newhash;
1078 /* Array classes need further initialization. */
1079 if (c->name->text[0] == '[') {
1080 /* Array classes are not loaded from classfiles. */
1083 c->packagename = array_packagename;
1086 /* Find the package name */
1087 /* Classes in the unnamed package keep packagename == NULL. */
1088 char *p = utf_end(c->name) - 1;
1089 char *start = c->name->text;
1090 for (;p > start; --p) {
1092 c->packagename = utf_new(start, p - start);
1097 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1098 initObjectLock(&c->header);
1105 classinfo *class_new(utf *classname)
1109 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1113 c = class_new_intern(classname);
1115 /* we support eager class loading and linking on demand */
1121 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
1124 if (!class_load(c)) {
1125 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1132 /* link all referenced classes */
1134 tc = list_first(&unlinkedclasses);
1137 /* skip the current loaded/linked class */
1139 if (!class_link(tc)) {
1140 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1147 /* we need a tmp variable here, because list_remove sets prev and
1149 tmp = list_next(&unlinkedclasses, tc);
1150 list_remove(&unlinkedclasses, tc);
1155 if (!class_link(c)) {
1156 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1164 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1172 /******************** Function: class_get **************************************
1174 searches for the class with the specified name in the classes hashtable
1175 if there is no such class NULL is returned
1177 *******************************************************************************/
1179 classinfo *class_get(utf *classname)
1181 classinfo *c; /* hashtable element */
1182 u4 key; /* hashkey computed from classname */
1183 u4 slot; /* slot in hashtable */
1186 key = utf_hashkey(classname->text, classname->blength);
1187 slot = key & (class_hash.size-1);
1188 c = class_hash.ptr[slot];
1190 /* search external hash-chain */
1192 if (c->name->blength == classname->blength) {
1193 /* compare classnames */
1194 for (i = 0; i < classname->blength; i++)
1195 if (classname->text[i] != c->name->text[i])
1198 /* class found in hashtable */
1206 /* class not found */
1211 /* class_remove ****************************************************************
1213 removes the class entry wth the specified name in the classes hashtable,
1214 furthermore the class' resources are freed
1215 if there is no such class false is returned
1217 *******************************************************************************/
1219 bool class_remove(classinfo *c)
1221 classinfo *tc; /* hashtable element */
1223 u4 key; /* hashkey computed from classname */
1224 u4 slot; /* slot in hashtable */
1227 key = utf_hashkey(c->name->text, c->name->blength);
1228 slot = key & (class_hash.size - 1);
1229 tc = class_hash.ptr[slot];
1232 /* search external hash-chain */
1234 if (tc->name->blength == c->name->blength) {
1236 /* compare classnames */
1237 for (i = 0; i < c->name->blength; i++)
1238 if (tc->name->text[i] != c->name->text[i])
1241 /* class found in hashtable */
1243 class_hash.ptr[slot] = tc->hashlink;
1246 pc->hashlink = tc->hashlink;
1259 /* class not found */
1264 /***************** Function: class_array_of ***********************************
1266 Returns an array class with the given component class.
1267 The array class is dynamically created if neccessary.
1269 *******************************************************************************/
1271 classinfo *class_array_of(classinfo *component)
1277 /* Assemble the array class name */
1278 namelen = component->name->blength;
1280 if (component->name->text[0] == '[') {
1281 /* the component is itself an array */
1282 namebuf = DMNEW(char, namelen + 1);
1284 memcpy(namebuf + 1, component->name->text, namelen);
1288 /* the component is a non-array class */
1289 namebuf = DMNEW(char, namelen + 3);
1292 memcpy(namebuf + 2, component->name->text, namelen);
1293 namebuf[2 + namelen] = ';';
1297 /* load this class ;-) and link it */
1298 c = class_new(utf_new(namebuf, namelen));
1305 /*************** Function: class_multiarray_of ********************************
1307 Returns an array class with the given dimension and element class.
1308 The array class is dynamically created if neccessary.
1310 *******************************************************************************/
1312 classinfo *class_multiarray_of(int dim, classinfo *element)
1318 panic("Invalid array dimension requested");
1320 /* Assemble the array class name */
1321 namelen = element->name->blength;
1323 if (element->name->text[0] == '[') {
1324 /* the element is itself an array */
1325 namebuf = DMNEW(char, namelen + dim);
1326 memcpy(namebuf + dim, element->name->text, namelen);
1330 /* the element is a non-array class */
1331 namebuf = DMNEW(char, namelen + 2 + dim);
1333 memcpy(namebuf + dim + 1, element->name->text, namelen);
1334 namelen += (2 + dim);
1335 namebuf[namelen - 1] = ';';
1337 memset(namebuf, '[', dim);
1339 return class_new(utf_new(namebuf, namelen));
1342 /************************** function: utf_strlen ******************************
1344 determine number of unicode characters in the utf string
1346 *******************************************************************************/
1348 u4 utf_strlen(utf *u)
1350 char *endpos; /* points behind utf string */
1351 char *utf_ptr; /* current position in utf text */
1352 u4 len = 0; /* number of unicode characters */
1355 *exceptionptr = new_nullpointerexception();
1359 endpos = utf_end(u);
1362 while (utf_ptr < endpos) {
1364 /* next unicode character */
1365 utf_nextu2(&utf_ptr);
1368 if (utf_ptr != endpos)
1369 /* string ended abruptly */
1370 panic("illegal utf string");
1377 * These are local overrides for various environment variables in Emacs.
1378 * Please do not remove this and leave it at the end of the file, where
1379 * Emacs will automagically detect them.
1380 * ---------------------------------------------------------------------
1383 * indent-tabs-mode: t