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 1185 2004-06-19 12:23:13Z twisti $
47 #include <sys/types.h>
55 #include "threads/thread.h"
56 #include "threads/locks.h"
57 #include "toolbox/logging.h"
58 #include "toolbox/memory.h"
62 int count_utf_len = 0; /* size of utf hash */
63 int count_utf_new = 0; /* calls of utf_new */
64 int count_utf_new_found = 0; /* calls of utf_new with fast return */
66 hashtable utf_hash; /* hashtable for utf8-symbols */
67 hashtable string_hash; /* hashtable for javastrings */
68 hashtable class_hash; /* hashtable for classes */
70 list unlinkedclasses; /* this is only used for eager class loading */
73 /******************************************************************************
74 *********************** hashtable functions **********************************
75 ******************************************************************************/
77 /* hashsize must be power of 2 */
79 #define UTF_HASHSTART 16384 /* initial size of utf-hash */
80 #define HASHSTART 2048 /* initial size of javastring and class-hash */
83 /******************** function: init_hashtable ******************************
85 Initializes a hashtable structure and allocates memory.
86 The parameter size specifies the initial size of the hashtable.
88 *****************************************************************************/
90 void init_hashtable(hashtable *hash, u4 size)
96 hash->ptr = MNEW(void*, size);
99 for (i = 0; i < size; i++) hash->ptr[i] = NULL;
103 /*********************** function: tables_init *****************************
105 creates hashtables for symboltables
106 (called once at startup)
108 *****************************************************************************/
112 init_hashtable(&utf_hash, UTF_HASHSTART); /* hashtable for utf8-symbols */
113 init_hashtable(&string_hash, HASHSTART); /* hashtable for javastrings */
114 init_hashtable(&class_hash, HASHSTART); /* hashtable for classes */
117 /* list_init(&unlinkedclasses, OFFSET(classinfo, listnode)); */
119 #if defined(STATISTICS)
121 count_utf_len += sizeof(utf*) * utf_hash.size;
126 /********************** function: tables_close ******************************
128 free memory for hashtables
130 *****************************************************************************/
138 /* dispose utf symbols */
139 for (i = 0; i < utf_hash.size; i++) {
142 /* process elements in external hash chain */
143 utf *nextu = u->hashlink;
144 MFREE(u->text, u1, u->blength);
150 /* dispose javastrings */
151 for (i = 0; i < string_hash.size; i++) {
152 s = string_hash.ptr[i];
154 /* process elements in external hash chain */
155 literalstring *nexts = s->hashlink;
156 literalstring_free(s->string);
157 FREE(s, literalstring);
162 /* dispose hashtable structures */
163 MFREE(utf_hash.ptr, void*, utf_hash.size);
164 MFREE(string_hash.ptr, void*, string_hash.size);
165 MFREE(class_hash.ptr, void*, class_hash.size);
169 /********************* function: utf_display *********************************
171 write utf symbol to stdout (debugging purposes)
173 ******************************************************************************/
175 void utf_display(utf *u)
177 char *endpos = utf_end(u); /* points behind utf string */
178 char *utf_ptr = u->text; /* current position in utf text */
183 while (utf_ptr < endpos) {
184 /* read next unicode character */
185 u2 c = utf_nextu2(&utf_ptr);
186 if (c >= 32 && c <= 127) printf("%c", c);
194 /********************* function: utf_display *********************************
196 write utf symbol to stdout (debugging purposes)
198 ******************************************************************************/
200 void utf_display_classname(utf *u)
202 char *endpos = utf_end(u); /* points behind utf string */
203 char *utf_ptr = u->text; /* current position in utf text */
208 while (utf_ptr < endpos) {
209 /* read next unicode character */
210 u2 c = utf_nextu2(&utf_ptr);
211 if (c == '/') c = '.';
212 if (c >= 32 && c <= 127) printf("%c", c);
220 /************************* function: log_utf *********************************
224 ******************************************************************************/
228 char buf[MAXLOGTEXT];
234 /********************** function: log_plain_utf ******************************
236 log utf symbol (without printing "LOG: " and newline)
238 ******************************************************************************/
240 void log_plain_utf(utf *u)
242 char buf[MAXLOGTEXT];
244 dolog_plain("%s", buf);
248 /************************ function: utf_sprint *******************************
250 write utf symbol into c-string (debugging purposes)
252 ******************************************************************************/
254 void utf_sprint(char *buffer, utf *u)
256 char *endpos = utf_end(u); /* points behind utf string */
257 char *utf_ptr = u->text; /* current position in utf text */
258 u2 pos = 0; /* position in c-string */
260 while (utf_ptr < endpos)
261 /* copy next unicode character */
262 buffer[pos++] = utf_nextu2(&utf_ptr);
264 /* terminate string */
269 /************************ function: utf_sprint_classname *********************
271 write utf symbol into c-string (debugging purposes)
273 ******************************************************************************/
275 void utf_sprint_classname(char *buffer, utf *u)
277 char *endpos = utf_end(u); /* points behind utf string */
278 char *utf_ptr = u->text; /* current position in utf text */
279 u2 pos = 0; /* position in c-string */
281 while (utf_ptr < endpos) {
282 /* copy next unicode character */
283 u2 c = utf_nextu2(&utf_ptr);
284 if (c == '/') c = '.';
288 /* terminate string */
293 /********************* Funktion: utf_fprint **********************************
295 write utf symbol into file
297 ******************************************************************************/
299 void utf_fprint(FILE *file, utf *u)
301 char *endpos = utf_end(u); /* points behind utf string */
302 char *utf_ptr = u->text; /* current position in utf text */
307 while (utf_ptr < endpos) {
308 /* read next unicode character */
309 u2 c = utf_nextu2(&utf_ptr);
311 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
312 else fprintf(file, "?");
317 /********************* Funktion: utf_fprint **********************************
319 write utf symbol into file
321 ******************************************************************************/
323 void utf_fprint_classname(FILE *file, utf *u)
325 char *endpos = utf_end(u); /* points behind utf string */
326 char *utf_ptr = u->text; /* current position in utf text */
331 while (utf_ptr < endpos) {
332 /* read next unicode character */
333 u2 c = utf_nextu2(&utf_ptr);
334 if (c == '/') c = '.';
336 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
337 else fprintf(file, "?");
342 /****************** internal function: utf_hashkey ***************************
344 The hashkey is computed from the utf-text by using up to 8 characters.
345 For utf-symbols longer than 15 characters 3 characters are taken from
346 the beginning and the end, 2 characters are taken from the middle.
348 ******************************************************************************/
350 #define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
351 #define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
353 static u4 utf_hashkey(char *text, u4 length)
355 char *start_pos = text; /* pointer to utf text */
360 case 0: /* empty string */
363 case 1: return fbs(0);
364 case 2: return fbs(0) ^ nbs(3);
365 case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
366 case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
367 case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
368 case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
369 case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
370 case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
377 return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
386 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
395 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
407 return a ^ nbs(9) ^ nbs(10);
419 return a ^ nbs(9) ^ nbs(10);
430 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
441 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
443 default: /* 3 characters from beginning */
449 /* 2 characters from middle */
450 text = start_pos + (length / 2);
455 /* 3 characters from end */
456 text = start_pos + length - 4;
461 return a ^ nbs(10) ^ nbs(11);
466 /*************************** function: utf_hashkey ***************************
468 compute the hashkey of a unicode string
470 ******************************************************************************/
472 u4 unicode_hashkey(u2 *text, u2 len)
474 return utf_hashkey((char*) text, len);
478 /************************ function: utf_new **********************************
480 Creates a new utf-symbol, the text of the symbol is passed as a
481 u1-array. The function searches the utf-hashtable for a utf-symbol
482 with this text. On success the element returned, otherwise a new
483 hashtable element is created.
485 If the number of entries in the hashtable exceeds twice the size of the
486 hashtable slots a reorganization of the hashtable is done and the utf
487 symbols are copied to a new hashtable with doubled size.
489 ******************************************************************************/
491 utf *utf_new_intern(char *text, u2 length)
493 u4 key; /* hashkey computed from utf-text */
494 u4 slot; /* slot in hashtable */
495 utf *u; /* hashtable element */
503 key = utf_hashkey(text, length);
504 slot = key & (utf_hash.size-1);
505 u = utf_hash.ptr[slot];
507 /* search external hash chain for utf-symbol */
509 if (u->blength == length) {
511 /* compare text of hashtable elements */
512 for (i = 0; i < length; i++)
513 if (text[i] != u->text[i]) goto nomatch;
517 count_utf_new_found++;
519 /* log_text("symbol found in hash table");*/
520 /* symbol found in hashtable */
531 u = u->hashlink; /* next element in external chain */
536 count_utf_len += sizeof(utf) + length;
539 /* location in hashtable found, create new utf element */
541 u->blength = length; /* length in bytes of utfstring */
542 u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain */
543 u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
544 memcpy(u->text, text, length); /* copy utf-text */
545 u->text[length] = '\0';
546 utf_hash.ptr[slot] = u; /* insert symbol into table */
548 utf_hash.entries++; /* update number of entries */
550 if (utf_hash.entries > (utf_hash.size * 2)) {
552 /* reorganization of hashtable, average length of
553 the external chains is approx. 2 */
557 hashtable newhash; /* the new hashtable */
559 /* create new hashtable, double the size */
560 init_hashtable(&newhash, utf_hash.size * 2);
561 newhash.entries = utf_hash.entries;
565 count_utf_len += sizeof(utf*) * utf_hash.size;
568 /* transfer elements to new hashtable */
569 for (i = 0; i < utf_hash.size; i++) {
570 u = (utf *) utf_hash.ptr[i];
572 utf *nextu = u->hashlink;
573 u4 slot = utf_hashkey(u->text, u->blength) & (newhash.size - 1);
575 u->hashlink = (utf *) newhash.ptr[slot];
576 newhash.ptr[slot] = u;
578 /* follow link in external hash chain */
583 /* dispose old table */
584 MFREE(utf_hash.ptr, void*, utf_hash.size);
592 utf *utf_new(char *text, u2 length)
596 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
600 r = utf_new_intern(text, length);
602 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
610 /********************* function: utf_new_char ********************************
612 creates a new utf symbol, the text for this symbol is passed
613 as a c-string ( = char* )
615 ******************************************************************************/
617 utf *utf_new_char(char *text)
619 return utf_new(text, strlen(text));
623 /********************* function: utf_new_char ********************************
625 creates a new utf symbol, the text for this symbol is passed
626 as a c-string ( = char* )
627 "." characters are going to be replaced by "/". since the above function is
628 used often, this is a separte function, instead of an if
630 ******************************************************************************/
632 utf *utf_new_char_classname(char *text)
634 if (strchr(text, '.')) {
635 char *txt = strdup(text);
636 char *end = txt + strlen(txt);
639 for (c = txt; c < end; c++)
640 if (*c == '.') *c = '/';
641 tmpRes = utf_new(txt, strlen(txt));
646 return utf_new(text, strlen(text));
650 /************************** Funktion: utf_show ******************************
652 writes the utf symbols in the utfhash to stdout and
653 displays the number of external hash chains grouped
654 according to the chainlength
657 *****************************************************************************/
662 #define CHAIN_LIMIT 20 /* limit for seperated enumeration */
664 u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
665 u4 max_chainlength = 0; /* maximum length of the chains */
666 u4 sum_chainlength = 0; /* sum of the chainlengths */
667 u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
670 printf ("UTF-HASH:\n");
672 /* show element of utf-hashtable */
673 for (i=0; i<utf_hash.size; i++) {
674 utf *u = utf_hash.ptr[i];
676 printf ("SLOT %d: ", (int) i);
688 printf ("UTF-HASH: %d slots for %d entries\n",
689 (int) utf_hash.size, (int) utf_hash.entries );
692 if (utf_hash.entries == 0)
695 printf("chains:\n chainlength number of chains %% of utfstrings\n");
697 for (i=0;i<CHAIN_LIMIT;i++)
700 /* count numbers of hashchains according to their length */
701 for (i=0; i<utf_hash.size; i++) {
703 utf *u = (utf*) utf_hash.ptr[i];
706 /* determine chainlength */
712 /* update sum of all chainlengths */
713 sum_chainlength+=chain_length;
715 /* determine the maximum length of the chains */
716 if (chain_length>max_chainlength)
717 max_chainlength = chain_length;
719 /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
720 if (chain_length>=CHAIN_LIMIT) {
721 beyond_limit+=chain_length;
722 chain_length=CHAIN_LIMIT-1;
725 /* update number of hashchains of current length */
726 chain_count[chain_length]++;
729 /* display results */
730 for (i=1;i<CHAIN_LIMIT-1;i++)
731 printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/utf_hash.entries));
733 printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/utf_hash.entries);
736 printf("max. chainlength:%5d\n",max_chainlength);
738 /* avg. chainlength = sum of chainlengths / number of chains */
739 printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (utf_hash.size-chain_count[0]));
742 /******************************************************************************
743 *********************** Misc support functions ********************************
744 ******************************************************************************/
747 /******************** Function: desc_to_type **********************************
749 Determines the corresponding Java base data type for a given type
752 ******************************************************************************/
754 u2 desc_to_type(utf *descriptor)
756 char *utf_ptr = descriptor->text; /* current position in utf text */
757 char logtext[MAXLOGTEXT];
759 if (descriptor->blength < 1) panic("Type-Descriptor is empty string");
761 switch (*utf_ptr++) {
766 case 'Z': return TYPE_INT;
767 case 'D': return TYPE_DOUBLE;
768 case 'F': return TYPE_FLOAT;
769 case 'J': return TYPE_LONG;
771 case '[': return TYPE_ADDRESS;
774 sprintf(logtext, "Invalid Type-Descriptor: ");
775 utf_sprint(logtext+strlen(logtext), descriptor);
782 /********************** Function: desc_typesize *******************************
784 Calculates the lenght in bytes needed for a data element of the type given
785 by its type descriptor.
787 ******************************************************************************/
789 u2 desc_typesize(utf *descriptor)
791 switch (desc_to_type(descriptor)) {
792 case TYPE_INT: return 4;
793 case TYPE_LONG: return 8;
794 case TYPE_FLOAT: return 4;
795 case TYPE_DOUBLE: return 8;
796 case TYPE_ADDRESS: return sizeof(voidptr);
802 /********************** function: utf_nextu2 *********************************
804 read the next unicode character from the utf string and
805 increment the utf-string pointer accordingly
807 ******************************************************************************/
809 u2 utf_nextu2(char **utf_ptr)
811 /* uncompressed unicode character */
813 /* current position in utf text */
814 unsigned char *utf = (unsigned char *) (*utf_ptr);
815 /* bytes representing the unicode character */
816 unsigned char ch1, ch2, ch3;
817 /* number of bytes used to represent the unicode character */
820 switch ((ch1 = utf[0]) >> 4) {
821 default: /* 1 byte */
825 case 0xD: /* 2 bytes */
826 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
827 unsigned char high = ch1 & 0x1F;
828 unsigned char low = ch2 & 0x3F;
829 unicode_char = (high << 6) + low;
834 case 0xE: /* 2 or 3 bytes */
835 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
836 if (((ch3 = utf[2]) & 0xC0) == 0x80) {
837 unsigned char low = ch3 & 0x3f;
838 unsigned char mid = ch2 & 0x3f;
839 unsigned char high = ch1 & 0x0f;
840 unicode_char = (((high << 6) + mid) << 6) + low;
848 /* update position in utf-text */
849 *utf_ptr = (char *) (utf + len);
854 /********************* function: is_valid_utf ********************************
856 return true if the given string is a valid UTF-8 string
858 utf_ptr...points to first character
859 end_pos...points after last character
861 ******************************************************************************/
863 static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26};
866 is_valid_utf(char *utf_ptr,char *end_pos)
873 if (end_pos < utf_ptr) return false;
874 bytes = end_pos - utf_ptr;
877 /*dolog("%c %02x",c,c);*/
878 if (!c) return false; /* 0x00 is not allowed */
879 if ((c & 0x80) == 0) continue; /* ASCII */
881 if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
882 else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
883 else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
884 else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
885 else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
886 else return false; /* invalid leading byte */
888 if (len > 2) return false; /* Java limitation */
890 v = (unsigned long)c & (0x3f >> len);
892 if ((bytes -= len) < 0) return false; /* missing bytes */
894 for (i = len; i--; ) {
896 /*dolog(" %c %02x",c,c);*/
897 if ((c & 0xc0) != 0x80) /* 10xx xxxx */
899 v = (v<<6) | (c & 0x3f);
902 /* dolog("v=%d",v);*/
905 if (len != 1) return false; /* Java special */
908 /* Sun Java seems to allow overlong UTF-8 encodings */
910 if (v < min_codepoint[len]) { /* overlong UTF-8 */
912 fprintf(stderr,"WARNING: Overlong UTF-8 sequence found.\n");
913 /* XXX change this to panic? */
917 /* surrogates in UTF-8 seem to be allowed in Java classfiles */
918 /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
920 /* even these seem to be allowed */
921 /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
927 /********************* function: is_valid_name *******************************
929 return true if the given string may be used as a class/field/method name.
930 (Currently this only disallows empty strings and control characters.)
932 NOTE: The string is assumed to have passed is_valid_utf!
934 utf_ptr...points to first character
935 end_pos...points after last character
937 ******************************************************************************/
940 is_valid_name(char *utf_ptr,char *end_pos)
942 if (end_pos <= utf_ptr) return false; /* disallow empty names */
944 while (utf_ptr < end_pos) {
945 unsigned char c = *utf_ptr++;
947 if (c < 0x20) return false; /* disallow control characters */
948 if (c == 0xc0 && (unsigned char)*utf_ptr == 0x80) return false; /* disallow zero */
954 is_valid_name_utf(utf *u)
956 return is_valid_name(u->text,utf_end(u));
959 /******************** Function: class_new **************************************
961 searches for the class with the specified name in the classes hashtable,
962 if there is no such class a new classinfo structure is created and inserted
963 into the list of classes to be loaded
965 *******************************************************************************/
967 classinfo *class_new_intern(utf *classname)
969 classinfo *c; /* hashtable element */
970 u4 key; /* hashkey computed from classname */
971 u4 slot; /* slot in hashtable */
974 key = utf_hashkey(classname->text, classname->blength);
975 slot = key & (class_hash.size - 1);
976 c = class_hash.ptr[slot];
978 /* search external hash chain for the class */
980 if (c->name->blength == classname->blength) {
981 for (i = 0; i < classname->blength; i++)
982 if (classname->text[i] != c->name->text[i]) goto nomatch;
984 /* class found in hashtable */
989 c = c->hashlink; /* next element in external chain */
992 /* location in hashtable found, create new classinfo structure */
994 #if defined(STATISTICS)
996 count_class_infos += sizeof(classinfo);
1000 char logtext[MAXLOGTEXT];
1001 sprintf(logtext, "Creating class: ");
1002 utf_sprint_classname(logtext + strlen(logtext), classname);
1006 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
1007 /*c=NEW(classinfo);*/
1010 c->name = classname;
1011 c->packagename = NULL;
1018 c->interfacescount = 0;
1019 c->interfaces = NULL;
1022 c->methodscount = 0;
1027 c->instancesize = 0;
1028 c->header.vftbl = NULL;
1029 c->innerclasscount = 0;
1030 c->innerclass = NULL;
1032 c->initialized = false;
1033 c->initializing = false;
1034 c->classvftbl = false;
1037 c->classloader = NULL;
1038 c->sourcefile = NULL;
1040 /* insert class into the hashtable */
1041 c->hashlink = class_hash.ptr[slot];
1042 class_hash.ptr[slot] = c;
1044 /* update number of hashtable-entries */
1045 class_hash.entries++;
1047 if (class_hash.entries > (class_hash.size * 2)) {
1049 /* reorganization of hashtable, average length of
1050 the external chains is approx. 2 */
1054 hashtable newhash; /* the new hashtable */
1056 /* create new hashtable, double the size */
1057 init_hashtable(&newhash, class_hash.size * 2);
1058 newhash.entries = class_hash.entries;
1060 /* transfer elements to new hashtable */
1061 for (i = 0; i < class_hash.size; i++) {
1062 c = (classinfo *) class_hash.ptr[i];
1064 classinfo *nextc = c->hashlink;
1065 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
1067 c->hashlink = newhash.ptr[slot];
1068 newhash.ptr[slot] = c;
1074 /* dispose old table */
1075 MFREE(class_hash.ptr, void*, class_hash.size);
1076 class_hash = newhash;
1079 /* Array classes need further initialization. */
1080 if (c->name->text[0] == '[') {
1081 /* Array classes are not loaded from classfiles. */
1084 c->packagename = array_packagename;
1087 /* Find the package name */
1088 /* Classes in the unnamed package keep packagename == NULL. */
1089 char *p = utf_end(c->name) - 1;
1090 char *start = c->name->text;
1091 for (;p > start; --p) {
1093 c->packagename = utf_new(start, p - start);
1103 classinfo *class_new(utf *classname)
1107 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1111 c = class_new_intern(classname);
1113 /* we support eager class loading and linking on demand */
1118 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
1121 if (!class_load(c)) {
1122 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1129 /* link all referenced classes */
1131 while ((tc = list_first(&unlinkedclasses))) {
1132 printf("tc=%p next=%p prev=%p ", tc, tc->listnode.next, tc->listnode.prev);
1133 utf_display(tc->name);
1137 /* skip super class */
1139 if (!class_link(tc)) {
1140 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1147 list_remove(&unlinkedclasses, tc);
1151 if (!class_link(c)) {
1152 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1160 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1168 /******************** Function: class_get **************************************
1170 searches for the class with the specified name in the classes hashtable
1171 if there is no such class NULL is returned
1173 *******************************************************************************/
1175 classinfo *class_get(utf *classname)
1177 classinfo *c; /* hashtable element */
1178 u4 key; /* hashkey computed from classname */
1179 u4 slot; /* slot in hashtable */
1182 key = utf_hashkey(classname->text, classname->blength);
1183 slot = key & (class_hash.size-1);
1184 c = class_hash.ptr[slot];
1186 /* search external hash-chain */
1188 if (c->name->blength == classname->blength) {
1189 /* compare classnames */
1190 for (i = 0; i < classname->blength; i++)
1191 if (classname->text[i] != c->name->text[i])
1194 /* class found in hashtable */
1202 /* class not found */
1207 /* class_remove ****************************************************************
1209 removes the class entry wth the specified name in the classes hashtable,
1210 furthermore the class' resources are freed
1211 if there is no such class false is returned
1213 *******************************************************************************/
1215 bool class_remove(classinfo *c)
1217 classinfo *tc; /* hashtable element */
1219 u4 key; /* hashkey computed from classname */
1220 u4 slot; /* slot in hashtable */
1223 key = utf_hashkey(c->name->text, c->name->blength);
1224 slot = key & (class_hash.size - 1);
1225 tc = class_hash.ptr[slot];
1228 /* search external hash-chain */
1230 if (tc->name->blength == c->name->blength) {
1232 /* compare classnames */
1233 for (i = 0; i < c->name->blength; i++)
1234 if (tc->name->text[i] != c->name->text[i])
1237 /* class found in hashtable */
1239 class_hash.ptr[slot] = tc->hashlink;
1242 pc->hashlink = tc->hashlink;
1255 /* class not found */
1260 /***************** Function: class_array_of ***********************************
1262 Returns an array class with the given component class.
1263 The array class is dynamically created if neccessary.
1265 *******************************************************************************/
1267 classinfo *class_array_of(classinfo *component)
1273 /* Assemble the array class name */
1274 namelen = component->name->blength;
1276 if (component->name->text[0] == '[') {
1277 /* the component is itself an array */
1278 namebuf = DMNEW(char, namelen + 1);
1280 memcpy(namebuf + 1, component->name->text, namelen);
1284 /* the component is a non-array class */
1285 namebuf = DMNEW(char, namelen + 3);
1288 memcpy(namebuf + 2, component->name->text, namelen);
1289 namebuf[2 + namelen] = ';';
1293 /* load this class ;-) and link it */
1294 c = class_new(utf_new(namebuf, namelen));
1301 /*************** Function: class_multiarray_of ********************************
1303 Returns an array class with the given dimension and element class.
1304 The array class is dynamically created if neccessary.
1306 *******************************************************************************/
1308 classinfo *class_multiarray_of(int dim, classinfo *element)
1314 panic("Invalid array dimension requested");
1316 /* Assemble the array class name */
1317 namelen = element->name->blength;
1319 if (element->name->text[0] == '[') {
1320 /* the element is itself an array */
1321 namebuf = DMNEW(char, namelen + dim);
1322 memcpy(namebuf + dim, element->name->text, namelen);
1326 /* the element is a non-array class */
1327 namebuf = DMNEW(char, namelen + 2 + dim);
1329 memcpy(namebuf + dim + 1, element->name->text, namelen);
1330 namelen += (2 + dim);
1331 namebuf[namelen - 1] = ';';
1333 memset(namebuf, '[', dim);
1335 return class_new(utf_new(namebuf, namelen));
1338 /************************** function: utf_strlen ******************************
1340 determine number of unicode characters in the utf string
1342 *******************************************************************************/
1344 u4 utf_strlen(utf *u)
1346 char *endpos = utf_end(u); /* points behind utf string */
1347 char *utf_ptr = u->text; /* current position in utf text */
1348 u4 len = 0; /* number of unicode characters */
1350 while (utf_ptr < endpos) {
1352 /* next unicode character */
1353 utf_nextu2(&utf_ptr);
1356 if (utf_ptr != endpos)
1357 /* string ended abruptly */
1358 panic("illegal utf string");
1365 * These are local overrides for various environment variables in Emacs.
1366 * Please do not remove this and leave it at the end of the file, where
1367 * Emacs will automagically detect them.
1368 * ---------------------------------------------------------------------
1371 * indent-tabs-mode: t