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 1482 2004-11-11 14:39:13Z 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; /* points behind utf string */
177 char *utf_ptr; /* current position in utf text */
188 while (utf_ptr < endpos) {
189 /* read next unicode character */
190 u2 c = utf_nextu2(&utf_ptr);
191 if (c >= 32 && c <= 127) printf("%c", c);
199 /* utf_display_classname *******************************************************
201 write utf symbol to stdout (debugging purposes)
203 *******************************************************************************/
205 void utf_display_classname(utf *u)
207 char *endpos; /* points behind utf string */
208 char *utf_ptr; /* current position in utf text */
219 while (utf_ptr < endpos) {
220 /* read next unicode character */
221 u2 c = utf_nextu2(&utf_ptr);
222 if (c == '/') c = '.';
223 if (c >= 32 && c <= 127) printf("%c", c);
231 /************************* function: log_utf *********************************
235 ******************************************************************************/
239 char buf[MAXLOGTEXT];
245 /********************** function: log_plain_utf ******************************
247 log utf symbol (without printing "LOG: " and newline)
249 ******************************************************************************/
251 void log_plain_utf(utf *u)
253 char buf[MAXLOGTEXT];
255 dolog_plain("%s", buf);
259 /* utf_sprint ******************************************************************
261 write utf symbol into c-string (debugging purposes)
263 *******************************************************************************/
265 void utf_sprint(char *buffer, utf *u)
267 char *endpos; /* points behind utf string */
268 char *utf_ptr; /* current position in utf text */
269 u2 pos = 0; /* position in c-string */
272 memcpy(buffer, "NULL", 5); /* 4 chars + terminating \0 */
279 while (utf_ptr < endpos)
280 /* copy next unicode character */
281 buffer[pos++] = utf_nextu2(&utf_ptr);
283 /* terminate string */
288 /* utf_sprint_classname ********************************************************
290 write utf symbol into c-string (debugging purposes)
292 *******************************************************************************/
294 void utf_sprint_classname(char *buffer, utf *u)
296 char *endpos; /* points behind utf string */
297 char *utf_ptr; /* current position in utf text */
298 u2 pos = 0; /* position in c-string */
301 memcpy(buffer, "NULL", 5); /* 4 chars + terminating \0 */
308 while (utf_ptr < endpos) {
309 /* copy next unicode character */
310 u2 c = utf_nextu2(&utf_ptr);
311 if (c == '/') c = '.';
315 /* terminate string */
320 /********************* Funktion: utf_fprint **********************************
322 write utf symbol into file
324 ******************************************************************************/
326 void utf_fprint(FILE *file, utf *u)
328 char *endpos = utf_end(u); /* points behind utf string */
329 char *utf_ptr = u->text; /* current position in utf text */
334 while (utf_ptr < endpos) {
335 /* read next unicode character */
336 u2 c = utf_nextu2(&utf_ptr);
338 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
339 else fprintf(file, "?");
344 /********************* Funktion: utf_fprint **********************************
346 write utf symbol into file
348 ******************************************************************************/
350 void utf_fprint_classname(FILE *file, utf *u)
352 char *endpos = utf_end(u); /* points behind utf string */
353 char *utf_ptr = u->text; /* current position in utf text */
358 while (utf_ptr < endpos) {
359 /* read next unicode character */
360 u2 c = utf_nextu2(&utf_ptr);
361 if (c == '/') c = '.';
363 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
364 else fprintf(file, "?");
369 /****************** internal function: utf_hashkey ***************************
371 The hashkey is computed from the utf-text by using up to 8 characters.
372 For utf-symbols longer than 15 characters 3 characters are taken from
373 the beginning and the end, 2 characters are taken from the middle.
375 ******************************************************************************/
377 #define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
378 #define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
380 static u4 utf_hashkey(char *text, u4 length)
382 char *start_pos = text; /* pointer to utf text */
387 case 0: /* empty string */
390 case 1: return fbs(0);
391 case 2: return fbs(0) ^ nbs(3);
392 case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
393 case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
394 case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
395 case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
396 case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
397 case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
404 return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
413 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
422 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
434 return a ^ nbs(9) ^ nbs(10);
446 return a ^ nbs(9) ^ nbs(10);
457 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
468 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
470 default: /* 3 characters from beginning */
476 /* 2 characters from middle */
477 text = start_pos + (length / 2);
482 /* 3 characters from end */
483 text = start_pos + length - 4;
488 return a ^ nbs(10) ^ nbs(11);
493 /*************************** function: utf_hashkey ***************************
495 compute the hashkey of a unicode string
497 ******************************************************************************/
499 u4 unicode_hashkey(u2 *text, u2 len)
501 return utf_hashkey((char*) text, len);
505 /************************ function: utf_new **********************************
507 Creates a new utf-symbol, the text of the symbol is passed as a
508 u1-array. The function searches the utf-hashtable for a utf-symbol
509 with this text. On success the element returned, otherwise a new
510 hashtable element is created.
512 If the number of entries in the hashtable exceeds twice the size of the
513 hashtable slots a reorganization of the hashtable is done and the utf
514 symbols are copied to a new hashtable with doubled size.
516 ******************************************************************************/
518 utf *utf_new_intern(char *text, u2 length)
520 u4 key; /* hashkey computed from utf-text */
521 u4 slot; /* slot in hashtable */
522 utf *u; /* hashtable element */
530 key = utf_hashkey(text, length);
531 slot = key & (utf_hash.size-1);
532 u = utf_hash.ptr[slot];
534 /* search external hash chain for utf-symbol */
536 if (u->blength == length) {
538 /* compare text of hashtable elements */
539 for (i = 0; i < length; i++)
540 if (text[i] != u->text[i]) goto nomatch;
544 count_utf_new_found++;
546 /* log_text("symbol found in hash table");*/
547 /* symbol found in hashtable */
558 u = u->hashlink; /* next element in external chain */
563 count_utf_len += sizeof(utf) + length;
566 /* location in hashtable found, create new utf element */
568 u->blength = length; /* length in bytes of utfstring */
569 u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain */
570 u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
571 memcpy(u->text, text, length); /* copy utf-text */
572 u->text[length] = '\0';
573 utf_hash.ptr[slot] = u; /* insert symbol into table */
575 utf_hash.entries++; /* update number of entries */
577 if (utf_hash.entries > (utf_hash.size * 2)) {
579 /* reorganization of hashtable, average length of
580 the external chains is approx. 2 */
584 hashtable newhash; /* the new hashtable */
586 /* create new hashtable, double the size */
587 init_hashtable(&newhash, utf_hash.size * 2);
588 newhash.entries = utf_hash.entries;
592 count_utf_len += sizeof(utf*) * utf_hash.size;
595 /* transfer elements to new hashtable */
596 for (i = 0; i < utf_hash.size; i++) {
597 u = (utf *) utf_hash.ptr[i];
599 utf *nextu = u->hashlink;
600 u4 slot = utf_hashkey(u->text, u->blength) & (newhash.size - 1);
602 u->hashlink = (utf *) newhash.ptr[slot];
603 newhash.ptr[slot] = u;
605 /* follow link in external hash chain */
610 /* dispose old table */
611 MFREE(utf_hash.ptr, void*, utf_hash.size);
619 utf *utf_new(char *text, u2 length)
623 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
627 r = utf_new_intern(text, length);
629 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
637 /********************* function: utf_new_char ********************************
639 creates a new utf symbol, the text for this symbol is passed
640 as a c-string ( = char* )
642 ******************************************************************************/
644 utf *utf_new_char(char *text)
646 return utf_new(text, strlen(text));
650 /********************* function: utf_new_char ********************************
652 creates a new utf symbol, the text for this symbol is passed
653 as a c-string ( = char* )
654 "." characters are going to be replaced by "/". since the above function is
655 used often, this is a separte function, instead of an if
657 ******************************************************************************/
659 utf *utf_new_char_classname(char *text)
661 if (strchr(text, '.')) {
662 char *txt = strdup(text);
663 char *end = txt + strlen(txt);
666 for (c = txt; c < end; c++)
667 if (*c == '.') *c = '/';
668 tmpRes = utf_new(txt, strlen(txt));
673 return utf_new(text, strlen(text));
677 /************************** Funktion: utf_show ******************************
679 writes the utf symbols in the utfhash to stdout and
680 displays the number of external hash chains grouped
681 according to the chainlength
684 *****************************************************************************/
689 #define CHAIN_LIMIT 20 /* limit for seperated enumeration */
691 u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
692 u4 max_chainlength = 0; /* maximum length of the chains */
693 u4 sum_chainlength = 0; /* sum of the chainlengths */
694 u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
697 printf ("UTF-HASH:\n");
699 /* show element of utf-hashtable */
700 for (i=0; i<utf_hash.size; i++) {
701 utf *u = utf_hash.ptr[i];
703 printf ("SLOT %d: ", (int) i);
715 printf ("UTF-HASH: %d slots for %d entries\n",
716 (int) utf_hash.size, (int) utf_hash.entries );
719 if (utf_hash.entries == 0)
722 printf("chains:\n chainlength number of chains %% of utfstrings\n");
724 for (i=0;i<CHAIN_LIMIT;i++)
727 /* count numbers of hashchains according to their length */
728 for (i=0; i<utf_hash.size; i++) {
730 utf *u = (utf*) utf_hash.ptr[i];
733 /* determine chainlength */
739 /* update sum of all chainlengths */
740 sum_chainlength+=chain_length;
742 /* determine the maximum length of the chains */
743 if (chain_length>max_chainlength)
744 max_chainlength = chain_length;
746 /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
747 if (chain_length>=CHAIN_LIMIT) {
748 beyond_limit+=chain_length;
749 chain_length=CHAIN_LIMIT-1;
752 /* update number of hashchains of current length */
753 chain_count[chain_length]++;
756 /* display results */
757 for (i=1;i<CHAIN_LIMIT-1;i++)
758 printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/utf_hash.entries));
760 printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/utf_hash.entries);
763 printf("max. chainlength:%5d\n",max_chainlength);
765 /* avg. chainlength = sum of chainlengths / number of chains */
766 printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (utf_hash.size-chain_count[0]));
769 /******************************************************************************
770 *********************** Misc support functions ********************************
771 ******************************************************************************/
774 /******************** Function: desc_to_type **********************************
776 Determines the corresponding Java base data type for a given type
779 ******************************************************************************/
781 u2 desc_to_type(utf *descriptor)
783 char *utf_ptr = descriptor->text; /* current position in utf text */
784 char logtext[MAXLOGTEXT];
786 if (descriptor->blength < 1) panic("Type-Descriptor is empty string");
788 switch (*utf_ptr++) {
793 case 'Z': return TYPE_INT;
794 case 'D': return TYPE_DOUBLE;
795 case 'F': return TYPE_FLOAT;
796 case 'J': return TYPE_LONG;
798 case '[': return TYPE_ADDRESS;
801 sprintf(logtext, "Invalid Type-Descriptor: ");
802 utf_sprint(logtext+strlen(logtext), descriptor);
809 /********************** Function: desc_typesize *******************************
811 Calculates the lenght in bytes needed for a data element of the type given
812 by its type descriptor.
814 ******************************************************************************/
816 u2 desc_typesize(utf *descriptor)
818 switch (desc_to_type(descriptor)) {
819 case TYPE_INT: return 4;
820 case TYPE_LONG: return 8;
821 case TYPE_FLOAT: return 4;
822 case TYPE_DOUBLE: return 8;
823 case TYPE_ADDRESS: return sizeof(voidptr);
829 /********************** function: utf_nextu2 *********************************
831 read the next unicode character from the utf string and
832 increment the utf-string pointer accordingly
834 ******************************************************************************/
836 u2 utf_nextu2(char **utf_ptr)
838 /* uncompressed unicode character */
840 /* current position in utf text */
841 unsigned char *utf = (unsigned char *) (*utf_ptr);
842 /* bytes representing the unicode character */
843 unsigned char ch1, ch2, ch3;
844 /* number of bytes used to represent the unicode character */
847 switch ((ch1 = utf[0]) >> 4) {
848 default: /* 1 byte */
852 case 0xD: /* 2 bytes */
853 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
854 unsigned char high = ch1 & 0x1F;
855 unsigned char low = ch2 & 0x3F;
856 unicode_char = (high << 6) + low;
861 case 0xE: /* 2 or 3 bytes */
862 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
863 if (((ch3 = utf[2]) & 0xC0) == 0x80) {
864 unsigned char low = ch3 & 0x3f;
865 unsigned char mid = ch2 & 0x3f;
866 unsigned char high = ch1 & 0x0f;
867 unicode_char = (((high << 6) + mid) << 6) + low;
875 /* update position in utf-text */
876 *utf_ptr = (char *) (utf + len);
881 /********************* function: is_valid_utf ********************************
883 return true if the given string is a valid UTF-8 string
885 utf_ptr...points to first character
886 end_pos...points after last character
888 ******************************************************************************/
890 static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26};
893 is_valid_utf(char *utf_ptr,char *end_pos)
900 if (end_pos < utf_ptr) return false;
901 bytes = end_pos - utf_ptr;
904 /*dolog("%c %02x",c,c);*/
905 if (!c) return false; /* 0x00 is not allowed */
906 if ((c & 0x80) == 0) continue; /* ASCII */
908 if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
909 else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
910 else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
911 else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
912 else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
913 else return false; /* invalid leading byte */
915 if (len > 2) return false; /* Java limitation */
917 v = (unsigned long)c & (0x3f >> len);
919 if ((bytes -= len) < 0) return false; /* missing bytes */
921 for (i = len; i--; ) {
923 /*dolog(" %c %02x",c,c);*/
924 if ((c & 0xc0) != 0x80) /* 10xx xxxx */
926 v = (v<<6) | (c & 0x3f);
929 /* dolog("v=%d",v);*/
932 if (len != 1) return false; /* Java special */
935 /* Sun Java seems to allow overlong UTF-8 encodings */
937 if (v < min_codepoint[len]) { /* overlong UTF-8 */
939 fprintf(stderr,"WARNING: Overlong UTF-8 sequence found.\n");
940 /* XXX change this to panic? */
944 /* surrogates in UTF-8 seem to be allowed in Java classfiles */
945 /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
947 /* even these seem to be allowed */
948 /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
954 /********************* function: is_valid_name *******************************
956 return true if the given string may be used as a class/field/method name.
957 (Currently this only disallows empty strings and control characters.)
959 NOTE: The string is assumed to have passed is_valid_utf!
961 utf_ptr...points to first character
962 end_pos...points after last character
964 ******************************************************************************/
967 is_valid_name(char *utf_ptr,char *end_pos)
969 if (end_pos <= utf_ptr) return false; /* disallow empty names */
971 while (utf_ptr < end_pos) {
972 unsigned char c = *utf_ptr++;
974 if (c < 0x20) return false; /* disallow control characters */
975 if (c == 0xc0 && (unsigned char)*utf_ptr == 0x80) return false; /* disallow zero */
981 is_valid_name_utf(utf *u)
983 return is_valid_name(u->text,utf_end(u));
986 /******************** Function: class_new **************************************
988 searches for the class with the specified name in the classes hashtable,
989 if there is no such class a new classinfo structure is created and inserted
990 into the list of classes to be loaded
992 *******************************************************************************/
994 classinfo *class_new_intern(utf *classname)
996 classinfo *c; /* hashtable element */
997 u4 key; /* hashkey computed from classname */
998 u4 slot; /* slot in hashtable */
1001 key = utf_hashkey(classname->text, classname->blength);
1002 slot = key & (class_hash.size - 1);
1003 c = class_hash.ptr[slot];
1005 /* search external hash chain for the class */
1007 if (c->name->blength == classname->blength) {
1008 for (i = 0; i < classname->blength; i++)
1009 if (classname->text[i] != c->name->text[i]) goto nomatch;
1011 /* class found in hashtable */
1016 c = c->hashlink; /* next element in external chain */
1019 /* location in hashtable found, create new classinfo structure */
1021 #if defined(STATISTICS)
1023 count_class_infos += sizeof(classinfo);
1027 char logtext[MAXLOGTEXT];
1028 sprintf(logtext, "Creating class: ");
1029 utf_sprint_classname(logtext + strlen(logtext), classname);
1033 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
1034 /*c=NEW(classinfo);*/
1037 c->name = classname;
1038 c->packagename = NULL;
1045 c->interfacescount = 0;
1046 c->interfaces = NULL;
1049 c->methodscount = 0;
1054 c->instancesize = 0;
1055 c->header.vftbl = NULL;
1056 c->innerclasscount = 0;
1057 c->innerclass = NULL;
1059 c->initialized = false;
1060 c->initializing = false;
1061 c->classvftbl = false;
1064 c->classloader = NULL;
1065 c->sourcefile = NULL;
1067 /* insert class into the hashtable */
1068 c->hashlink = class_hash.ptr[slot];
1069 class_hash.ptr[slot] = c;
1071 /* update number of hashtable-entries */
1072 class_hash.entries++;
1074 if (class_hash.entries > (class_hash.size * 2)) {
1076 /* reorganization of hashtable, average length of
1077 the external chains is approx. 2 */
1081 hashtable newhash; /* the new hashtable */
1083 /* create new hashtable, double the size */
1084 init_hashtable(&newhash, class_hash.size * 2);
1085 newhash.entries = class_hash.entries;
1087 /* transfer elements to new hashtable */
1088 for (i = 0; i < class_hash.size; i++) {
1089 c = (classinfo *) class_hash.ptr[i];
1091 classinfo *nextc = c->hashlink;
1092 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
1094 c->hashlink = newhash.ptr[slot];
1095 newhash.ptr[slot] = c;
1101 /* dispose old table */
1102 MFREE(class_hash.ptr, void*, class_hash.size);
1103 class_hash = newhash;
1106 /* Array classes need further initialization. */
1107 if (c->name->text[0] == '[') {
1108 /* Array classes are not loaded from classfiles. */
1111 c->packagename = array_packagename;
1114 /* Find the package name */
1115 /* Classes in the unnamed package keep packagename == NULL. */
1116 char *p = utf_end(c->name) - 1;
1117 char *start = c->name->text;
1118 for (;p > start; --p) {
1120 c->packagename = utf_new(start, p - start);
1125 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1126 initObjectLock(&c->header);
1133 classinfo *class_new(utf *classname)
1137 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1141 c = class_new_intern(classname);
1143 /* we support eager class loading and linking on demand */
1149 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
1152 if (!class_load(c)) {
1153 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1160 /* link all referenced classes */
1162 tc = list_first(&unlinkedclasses);
1165 /* skip the current loaded/linked class */
1167 if (!class_link(tc)) {
1168 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1175 /* we need a tmp variable here, because list_remove sets prev and
1177 tmp = list_next(&unlinkedclasses, tc);
1178 list_remove(&unlinkedclasses, tc);
1183 if (!class_link(c)) {
1184 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1192 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1200 /******************** Function: class_get **************************************
1202 searches for the class with the specified name in the classes hashtable
1203 if there is no such class NULL is returned
1205 *******************************************************************************/
1207 classinfo *class_get(utf *classname)
1209 classinfo *c; /* hashtable element */
1210 u4 key; /* hashkey computed from classname */
1211 u4 slot; /* slot in hashtable */
1214 key = utf_hashkey(classname->text, classname->blength);
1215 slot = key & (class_hash.size-1);
1216 c = class_hash.ptr[slot];
1218 /* search external hash-chain */
1220 if (c->name->blength == classname->blength) {
1221 /* compare classnames */
1222 for (i = 0; i < classname->blength; i++)
1223 if (classname->text[i] != c->name->text[i])
1226 /* class found in hashtable */
1234 /* class not found */
1239 /* class_remove ****************************************************************
1241 removes the class entry wth the specified name in the classes hashtable,
1242 furthermore the class' resources are freed
1243 if there is no such class false is returned
1245 *******************************************************************************/
1247 bool class_remove(classinfo *c)
1249 classinfo *tc; /* hashtable element */
1251 u4 key; /* hashkey computed from classname */
1252 u4 slot; /* slot in hashtable */
1255 key = utf_hashkey(c->name->text, c->name->blength);
1256 slot = key & (class_hash.size - 1);
1257 tc = class_hash.ptr[slot];
1260 /* search external hash-chain */
1262 if (tc->name->blength == c->name->blength) {
1264 /* compare classnames */
1265 for (i = 0; i < c->name->blength; i++)
1266 if (tc->name->text[i] != c->name->text[i])
1269 /* class found in hashtable */
1271 class_hash.ptr[slot] = tc->hashlink;
1274 pc->hashlink = tc->hashlink;
1287 /* class not found */
1292 /***************** Function: class_array_of ***********************************
1294 Returns an array class with the given component class.
1295 The array class is dynamically created if neccessary.
1297 *******************************************************************************/
1299 classinfo *class_array_of(classinfo *component)
1305 /* Assemble the array class name */
1306 namelen = component->name->blength;
1308 if (component->name->text[0] == '[') {
1309 /* the component is itself an array */
1310 namebuf = DMNEW(char, namelen + 1);
1312 memcpy(namebuf + 1, component->name->text, namelen);
1316 /* the component is a non-array class */
1317 namebuf = DMNEW(char, namelen + 3);
1320 memcpy(namebuf + 2, component->name->text, namelen);
1321 namebuf[2 + namelen] = ';';
1325 /* load this class ;-) and link it */
1326 c = class_new(utf_new(namebuf, namelen));
1333 /*************** Function: class_multiarray_of ********************************
1335 Returns an array class with the given dimension and element class.
1336 The array class is dynamically created if neccessary.
1338 *******************************************************************************/
1340 classinfo *class_multiarray_of(int dim, classinfo *element)
1346 panic("Invalid array dimension requested");
1348 /* Assemble the array class name */
1349 namelen = element->name->blength;
1351 if (element->name->text[0] == '[') {
1352 /* the element is itself an array */
1353 namebuf = DMNEW(char, namelen + dim);
1354 memcpy(namebuf + dim, element->name->text, namelen);
1358 /* the element is a non-array class */
1359 namebuf = DMNEW(char, namelen + 2 + dim);
1361 memcpy(namebuf + dim + 1, element->name->text, namelen);
1362 namelen += (2 + dim);
1363 namebuf[namelen - 1] = ';';
1365 memset(namebuf, '[', dim);
1367 return class_new(utf_new(namebuf, namelen));
1370 /************************** function: utf_strlen ******************************
1372 determine number of unicode characters in the utf string
1374 *******************************************************************************/
1376 u4 utf_strlen(utf *u)
1378 char *endpos; /* points behind utf string */
1379 char *utf_ptr; /* current position in utf text */
1380 u4 len = 0; /* number of unicode characters */
1383 *exceptionptr = new_nullpointerexception();
1387 endpos = utf_end(u);
1390 while (utf_ptr < endpos) {
1392 /* next unicode character */
1393 utf_nextu2(&utf_ptr);
1396 if (utf_ptr != endpos)
1397 /* string ended abruptly */
1398 panic("illegal utf string");
1405 * These are local overrides for various environment variables in Emacs.
1406 * Please do not remove this and leave it at the end of the file, where
1407 * Emacs will automagically detect them.
1408 * ---------------------------------------------------------------------
1411 * indent-tabs-mode: t