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 1621 2004-11-30 13:06:55Z twisti $
45 #include <sys/types.h>
50 #include "mm/memory.h"
51 #include "native/native.h"
52 #include "toolbox/logging.h"
53 #include "vm/builtin.h"
54 #include "vm/exceptions.h"
55 #include "vm/global.h"
56 #include "vm/loader.h"
57 #include "vm/options.h"
58 #include "vm/statistics.h"
59 #include "vm/tables.h"
62 hashtable utf_hash; /* hashtable for utf8-symbols */
63 hashtable string_hash; /* hashtable for javastrings */
64 hashtable class_hash; /* hashtable for classes */
66 list unlinkedclasses; /* this is only used for eager class loading */
69 /******************************************************************************
70 *********************** hashtable functions **********************************
71 ******************************************************************************/
73 /* hashsize must be power of 2 */
75 #define UTF_HASHSTART 16384 /* initial size of utf-hash */
76 #define HASHSTART 2048 /* initial size of javastring and class-hash */
79 /******************** function: init_hashtable ******************************
81 Initializes a hashtable structure and allocates memory.
82 The parameter size specifies the initial size of the hashtable.
84 *****************************************************************************/
86 void init_hashtable(hashtable *hash, u4 size)
92 hash->ptr = MNEW(void*, size);
95 for (i = 0; i < size; i++) hash->ptr[i] = NULL;
99 /*********************** function: tables_init *****************************
101 creates hashtables for symboltables
102 (called once at startup)
104 *****************************************************************************/
108 init_hashtable(&utf_hash, UTF_HASHSTART); /* hashtable for utf8-symbols */
109 init_hashtable(&string_hash, HASHSTART); /* hashtable for javastrings */
110 init_hashtable(&class_hash, HASHSTART); /* hashtable for classes */
113 /* list_init(&unlinkedclasses, OFFSET(classinfo, listnode)); */
115 #if defined(STATISTICS)
117 count_utf_len += sizeof(utf*) * utf_hash.size;
122 /********************** function: tables_close ******************************
124 free memory for hashtables
126 *****************************************************************************/
134 /* dispose utf symbols */
135 for (i = 0; i < utf_hash.size; i++) {
138 /* process elements in external hash chain */
139 utf *nextu = u->hashlink;
140 MFREE(u->text, u1, u->blength);
146 /* dispose javastrings */
147 for (i = 0; i < string_hash.size; i++) {
148 s = string_hash.ptr[i];
150 /* process elements in external hash chain */
151 literalstring *nexts = s->hashlink;
152 literalstring_free(s->string);
153 FREE(s, literalstring);
158 /* dispose hashtable structures */
159 MFREE(utf_hash.ptr, void*, utf_hash.size);
160 MFREE(string_hash.ptr, void*, string_hash.size);
161 MFREE(class_hash.ptr, void*, class_hash.size);
165 /********************* function: utf_display *********************************
167 write utf symbol to stdout (debugging purposes)
169 *******************************************************************************/
171 void utf_display(utf *u)
173 char *endpos; /* points behind utf string */
174 char *utf_ptr; /* current position in utf text */
185 while (utf_ptr < endpos) {
186 /* read next unicode character */
187 u2 c = utf_nextu2(&utf_ptr);
188 if (c >= 32 && c <= 127) printf("%c", c);
196 /* utf_display_classname *******************************************************
198 write utf symbol to stdout (debugging purposes)
200 *******************************************************************************/
202 void utf_display_classname(utf *u)
204 char *endpos; /* points behind utf string */
205 char *utf_ptr; /* current position in utf text */
216 while (utf_ptr < endpos) {
217 /* read next unicode character */
218 u2 c = utf_nextu2(&utf_ptr);
219 if (c == '/') c = '.';
220 if (c >= 32 && c <= 127) printf("%c", c);
228 /************************* function: log_utf *********************************
232 ******************************************************************************/
236 char buf[MAXLOGTEXT];
242 /********************** function: log_plain_utf ******************************
244 log utf symbol (without printing "LOG: " and newline)
246 ******************************************************************************/
248 void log_plain_utf(utf *u)
250 char buf[MAXLOGTEXT];
252 dolog_plain("%s", buf);
256 /* utf_sprint ******************************************************************
258 write utf symbol into c-string (debugging purposes)
260 *******************************************************************************/
262 void utf_sprint(char *buffer, utf *u)
264 char *endpos; /* points behind utf string */
265 char *utf_ptr; /* current position in utf text */
266 u2 pos = 0; /* position in c-string */
269 memcpy(buffer, "NULL", 5); /* 4 chars + terminating \0 */
276 while (utf_ptr < endpos)
277 /* copy next unicode character */
278 buffer[pos++] = utf_nextu2(&utf_ptr);
280 /* terminate string */
285 /* utf_sprint_classname ********************************************************
287 write utf symbol into c-string (debugging purposes)
289 *******************************************************************************/
291 void utf_sprint_classname(char *buffer, utf *u)
293 char *endpos; /* points behind utf string */
294 char *utf_ptr; /* current position in utf text */
295 u2 pos = 0; /* position in c-string */
298 memcpy(buffer, "NULL", 5); /* 4 chars + terminating \0 */
305 while (utf_ptr < endpos) {
306 /* copy next unicode character */
307 u2 c = utf_nextu2(&utf_ptr);
308 if (c == '/') c = '.';
312 /* terminate string */
317 /********************* Funktion: utf_fprint **********************************
319 write utf symbol into file
321 ******************************************************************************/
323 void utf_fprint(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);
335 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
336 else fprintf(file, "?");
341 /********************* Funktion: utf_fprint **********************************
343 write utf symbol into file
345 ******************************************************************************/
347 void utf_fprint_classname(FILE *file, utf *u)
349 char *endpos = utf_end(u); /* points behind utf string */
350 char *utf_ptr = u->text; /* current position in utf text */
355 while (utf_ptr < endpos) {
356 /* read next unicode character */
357 u2 c = utf_nextu2(&utf_ptr);
358 if (c == '/') c = '.';
360 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
361 else fprintf(file, "?");
366 /****************** internal function: utf_hashkey ***************************
368 The hashkey is computed from the utf-text by using up to 8 characters.
369 For utf-symbols longer than 15 characters 3 characters are taken from
370 the beginning and the end, 2 characters are taken from the middle.
372 ******************************************************************************/
374 #define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
375 #define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
377 static u4 utf_hashkey(char *text, u4 length)
379 char *start_pos = text; /* pointer to utf text */
384 case 0: /* empty string */
387 case 1: return fbs(0);
388 case 2: return fbs(0) ^ nbs(3);
389 case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
390 case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
391 case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
392 case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
393 case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
394 case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
401 return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
410 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
419 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
431 return a ^ nbs(9) ^ nbs(10);
443 return a ^ nbs(9) ^ nbs(10);
454 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
465 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
467 default: /* 3 characters from beginning */
473 /* 2 characters from middle */
474 text = start_pos + (length / 2);
479 /* 3 characters from end */
480 text = start_pos + length - 4;
485 return a ^ nbs(10) ^ nbs(11);
490 /*************************** function: utf_hashkey ***************************
492 compute the hashkey of a unicode string
494 ******************************************************************************/
496 u4 unicode_hashkey(u2 *text, u2 len)
498 return utf_hashkey((char*) text, len);
502 /************************ function: utf_new **********************************
504 Creates a new utf-symbol, the text of the symbol is passed as a
505 u1-array. The function searches the utf-hashtable for a utf-symbol
506 with this text. On success the element returned, otherwise a new
507 hashtable element is created.
509 If the number of entries in the hashtable exceeds twice the size of the
510 hashtable slots a reorganization of the hashtable is done and the utf
511 symbols are copied to a new hashtable with doubled size.
513 ******************************************************************************/
515 utf *utf_new_intern(char *text, u2 length)
517 u4 key; /* hashkey computed from utf-text */
518 u4 slot; /* slot in hashtable */
519 utf *u; /* hashtable element */
527 key = utf_hashkey(text, length);
528 slot = key & (utf_hash.size-1);
529 u = utf_hash.ptr[slot];
531 /* search external hash chain for utf-symbol */
533 if (u->blength == length) {
535 /* compare text of hashtable elements */
536 for (i = 0; i < length; i++)
537 if (text[i] != u->text[i]) goto nomatch;
541 count_utf_new_found++;
543 /* log_text("symbol found in hash table");*/
544 /* symbol found in hashtable */
555 u = u->hashlink; /* next element in external chain */
560 count_utf_len += sizeof(utf) + length;
563 /* location in hashtable found, create new utf element */
565 u->blength = length; /* length in bytes of utfstring */
566 u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain */
567 u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
568 memcpy(u->text, text, length); /* copy utf-text */
569 u->text[length] = '\0';
570 utf_hash.ptr[slot] = u; /* insert symbol into table */
572 utf_hash.entries++; /* update number of entries */
574 if (utf_hash.entries > (utf_hash.size * 2)) {
576 /* reorganization of hashtable, average length of
577 the external chains is approx. 2 */
581 hashtable newhash; /* the new hashtable */
583 /* create new hashtable, double the size */
584 init_hashtable(&newhash, utf_hash.size * 2);
585 newhash.entries = utf_hash.entries;
589 count_utf_len += sizeof(utf*) * utf_hash.size;
592 /* transfer elements to new hashtable */
593 for (i = 0; i < utf_hash.size; i++) {
594 u = (utf *) utf_hash.ptr[i];
596 utf *nextu = u->hashlink;
597 u4 slot = utf_hashkey(u->text, u->blength) & (newhash.size - 1);
599 u->hashlink = (utf *) newhash.ptr[slot];
600 newhash.ptr[slot] = u;
602 /* follow link in external hash chain */
607 /* dispose old table */
608 MFREE(utf_hash.ptr, void*, utf_hash.size);
616 utf *utf_new(char *text, u2 length)
620 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
624 r = utf_new_intern(text, length);
626 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
634 /********************* function: utf_new_char ********************************
636 creates a new utf symbol, the text for this symbol is passed
637 as a c-string ( = char* )
639 ******************************************************************************/
641 utf *utf_new_char(char *text)
643 return utf_new(text, strlen(text));
647 /********************* function: utf_new_char ********************************
649 creates a new utf symbol, the text for this symbol is passed
650 as a c-string ( = char* )
651 "." characters are going to be replaced by "/". since the above function is
652 used often, this is a separte function, instead of an if
654 ******************************************************************************/
656 utf *utf_new_char_classname(char *text)
658 if (strchr(text, '.')) {
659 char *txt = strdup(text);
660 char *end = txt + strlen(txt);
663 for (c = txt; c < end; c++)
664 if (*c == '.') *c = '/';
665 tmpRes = utf_new(txt, strlen(txt));
670 return utf_new(text, strlen(text));
674 /************************** Funktion: utf_show ******************************
676 writes the utf symbols in the utfhash to stdout and
677 displays the number of external hash chains grouped
678 according to the chainlength
681 *****************************************************************************/
686 #define CHAIN_LIMIT 20 /* limit for seperated enumeration */
688 u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
689 u4 max_chainlength = 0; /* maximum length of the chains */
690 u4 sum_chainlength = 0; /* sum of the chainlengths */
691 u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
694 printf ("UTF-HASH:\n");
696 /* show element of utf-hashtable */
697 for (i=0; i<utf_hash.size; i++) {
698 utf *u = utf_hash.ptr[i];
700 printf ("SLOT %d: ", (int) i);
712 printf ("UTF-HASH: %d slots for %d entries\n",
713 (int) utf_hash.size, (int) utf_hash.entries );
716 if (utf_hash.entries == 0)
719 printf("chains:\n chainlength number of chains %% of utfstrings\n");
721 for (i=0;i<CHAIN_LIMIT;i++)
724 /* count numbers of hashchains according to their length */
725 for (i=0; i<utf_hash.size; i++) {
727 utf *u = (utf*) utf_hash.ptr[i];
730 /* determine chainlength */
736 /* update sum of all chainlengths */
737 sum_chainlength+=chain_length;
739 /* determine the maximum length of the chains */
740 if (chain_length>max_chainlength)
741 max_chainlength = chain_length;
743 /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
744 if (chain_length>=CHAIN_LIMIT) {
745 beyond_limit+=chain_length;
746 chain_length=CHAIN_LIMIT-1;
749 /* update number of hashchains of current length */
750 chain_count[chain_length]++;
753 /* display results */
754 for (i=1;i<CHAIN_LIMIT-1;i++)
755 printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/utf_hash.entries));
757 printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/utf_hash.entries);
760 printf("max. chainlength:%5d\n",max_chainlength);
762 /* avg. chainlength = sum of chainlengths / number of chains */
763 printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (utf_hash.size-chain_count[0]));
766 /******************************************************************************
767 *********************** Misc support functions ********************************
768 ******************************************************************************/
771 /******************** Function: desc_to_type **********************************
773 Determines the corresponding Java base data type for a given type
776 ******************************************************************************/
778 u2 desc_to_type(utf *descriptor)
780 char *utf_ptr = descriptor->text; /* current position in utf text */
781 char logtext[MAXLOGTEXT];
783 if (descriptor->blength < 1) panic("Type-Descriptor is empty string");
785 switch (*utf_ptr++) {
790 case 'Z': return TYPE_INT;
791 case 'D': return TYPE_DOUBLE;
792 case 'F': return TYPE_FLOAT;
793 case 'J': return TYPE_LONG;
795 case '[': return TYPE_ADDRESS;
798 sprintf(logtext, "Invalid Type-Descriptor: ");
799 utf_sprint(logtext+strlen(logtext), descriptor);
806 /********************** Function: desc_typesize *******************************
808 Calculates the lenght in bytes needed for a data element of the type given
809 by its type descriptor.
811 ******************************************************************************/
813 u2 desc_typesize(utf *descriptor)
815 switch (desc_to_type(descriptor)) {
816 case TYPE_INT: return 4;
817 case TYPE_LONG: return 8;
818 case TYPE_FLOAT: return 4;
819 case TYPE_DOUBLE: return 8;
820 case TYPE_ADDRESS: return sizeof(voidptr);
826 /********************** function: utf_nextu2 *********************************
828 read the next unicode character from the utf string and
829 increment the utf-string pointer accordingly
831 ******************************************************************************/
833 u2 utf_nextu2(char **utf_ptr)
835 /* uncompressed unicode character */
837 /* current position in utf text */
838 unsigned char *utf = (unsigned char *) (*utf_ptr);
839 /* bytes representing the unicode character */
840 unsigned char ch1, ch2, ch3;
841 /* number of bytes used to represent the unicode character */
844 switch ((ch1 = utf[0]) >> 4) {
845 default: /* 1 byte */
849 case 0xD: /* 2 bytes */
850 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
851 unsigned char high = ch1 & 0x1F;
852 unsigned char low = ch2 & 0x3F;
853 unicode_char = (high << 6) + low;
858 case 0xE: /* 2 or 3 bytes */
859 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
860 if (((ch3 = utf[2]) & 0xC0) == 0x80) {
861 unsigned char low = ch3 & 0x3f;
862 unsigned char mid = ch2 & 0x3f;
863 unsigned char high = ch1 & 0x0f;
864 unicode_char = (((high << 6) + mid) << 6) + low;
872 /* update position in utf-text */
873 *utf_ptr = (char *) (utf + len);
878 /********************* function: is_valid_utf ********************************
880 return true if the given string is a valid UTF-8 string
882 utf_ptr...points to first character
883 end_pos...points after last character
885 ******************************************************************************/
887 static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26};
890 is_valid_utf(char *utf_ptr,char *end_pos)
897 if (end_pos < utf_ptr) return false;
898 bytes = end_pos - utf_ptr;
901 /*dolog("%c %02x",c,c);*/
902 if (!c) return false; /* 0x00 is not allowed */
903 if ((c & 0x80) == 0) continue; /* ASCII */
905 if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
906 else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
907 else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
908 else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
909 else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
910 else return false; /* invalid leading byte */
912 if (len > 2) return false; /* Java limitation */
914 v = (unsigned long)c & (0x3f >> len);
916 if ((bytes -= len) < 0) return false; /* missing bytes */
918 for (i = len; i--; ) {
920 /*dolog(" %c %02x",c,c);*/
921 if ((c & 0xc0) != 0x80) /* 10xx xxxx */
923 v = (v<<6) | (c & 0x3f);
926 /* dolog("v=%d",v);*/
929 if (len != 1) return false; /* Java special */
932 /* Sun Java seems to allow overlong UTF-8 encodings */
934 if (v < min_codepoint[len]) { /* overlong UTF-8 */
936 fprintf(stderr,"WARNING: Overlong UTF-8 sequence found.\n");
937 /* XXX change this to panic? */
941 /* surrogates in UTF-8 seem to be allowed in Java classfiles */
942 /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
944 /* even these seem to be allowed */
945 /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
951 /********************* function: is_valid_name *******************************
953 return true if the given string may be used as a class/field/method name.
954 (Currently this only disallows empty strings and control characters.)
956 NOTE: The string is assumed to have passed is_valid_utf!
958 utf_ptr...points to first character
959 end_pos...points after last character
961 ******************************************************************************/
964 is_valid_name(char *utf_ptr,char *end_pos)
966 if (end_pos <= utf_ptr) return false; /* disallow empty names */
968 while (utf_ptr < end_pos) {
969 unsigned char c = *utf_ptr++;
971 if (c < 0x20) return false; /* disallow control characters */
972 if (c == 0xc0 && (unsigned char)*utf_ptr == 0x80) return false; /* disallow zero */
978 is_valid_name_utf(utf *u)
980 return is_valid_name(u->text,utf_end(u));
983 /******************** Function: class_new **************************************
985 searches for the class with the specified name in the classes hashtable,
986 if there is no such class a new classinfo structure is created and inserted
987 into the list of classes to be loaded
989 *******************************************************************************/
991 classinfo *class_new_intern(utf *classname)
993 classinfo *c; /* hashtable element */
994 u4 key; /* hashkey computed from classname */
995 u4 slot; /* slot in hashtable */
998 key = utf_hashkey(classname->text, classname->blength);
999 slot = key & (class_hash.size - 1);
1000 c = class_hash.ptr[slot];
1002 /* search external hash chain for the class */
1004 if (c->name->blength == classname->blength) {
1005 for (i = 0; i < classname->blength; i++)
1006 if (classname->text[i] != c->name->text[i]) goto nomatch;
1008 /* class found in hashtable */
1013 c = c->hashlink; /* next element in external chain */
1016 /* location in hashtable found, create new classinfo structure */
1018 #if defined(STATISTICS)
1020 count_class_infos += sizeof(classinfo);
1024 char logtext[MAXLOGTEXT];
1025 sprintf(logtext, "Creating class: ");
1026 utf_sprint_classname(logtext + strlen(logtext), classname);
1030 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
1031 /*c=NEW(classinfo);*/
1034 c->name = classname;
1035 c->packagename = NULL;
1042 c->interfacescount = 0;
1043 c->interfaces = NULL;
1046 c->methodscount = 0;
1051 c->instancesize = 0;
1052 c->header.vftbl = NULL;
1053 c->innerclasscount = 0;
1054 c->innerclass = NULL;
1056 c->initialized = false;
1057 c->initializing = false;
1058 c->classvftbl = false;
1061 c->classloader = NULL;
1062 c->sourcefile = NULL;
1064 /* insert class into the hashtable */
1065 c->hashlink = class_hash.ptr[slot];
1066 class_hash.ptr[slot] = c;
1068 /* update number of hashtable-entries */
1069 class_hash.entries++;
1071 if (class_hash.entries > (class_hash.size * 2)) {
1073 /* reorganization of hashtable, average length of
1074 the external chains is approx. 2 */
1078 hashtable newhash; /* the new hashtable */
1080 /* create new hashtable, double the size */
1081 init_hashtable(&newhash, class_hash.size * 2);
1082 newhash.entries = class_hash.entries;
1084 /* transfer elements to new hashtable */
1085 for (i = 0; i < class_hash.size; i++) {
1086 c = (classinfo *) class_hash.ptr[i];
1088 classinfo *nextc = c->hashlink;
1089 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
1091 c->hashlink = newhash.ptr[slot];
1092 newhash.ptr[slot] = c;
1098 /* dispose old table */
1099 MFREE(class_hash.ptr, void*, class_hash.size);
1100 class_hash = newhash;
1103 /* Array classes need further initialization. */
1104 if (c->name->text[0] == '[') {
1105 /* Array classes are not loaded from classfiles. */
1108 c->packagename = array_packagename;
1111 /* Find the package name */
1112 /* Classes in the unnamed package keep packagename == NULL. */
1113 char *p = utf_end(c->name) - 1;
1114 char *start = c->name->text;
1115 for (;p > start; --p) {
1117 c->packagename = utf_new(start, p - start);
1122 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1123 initObjectLock(&c->header);
1130 classinfo *class_new(utf *classname)
1134 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1138 c = class_new_intern(classname);
1140 /* we support eager class loading and linking on demand */
1146 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
1149 if (!class_load(c)) {
1150 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1157 /* link all referenced classes */
1159 tc = list_first(&unlinkedclasses);
1162 /* skip the current loaded/linked class */
1164 if (!class_link(tc)) {
1165 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1172 /* we need a tmp variable here, because list_remove sets prev and
1174 tmp = list_next(&unlinkedclasses, tc);
1175 list_remove(&unlinkedclasses, tc);
1180 if (!class_link(c)) {
1181 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1189 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1197 /******************** Function: class_get **************************************
1199 searches for the class with the specified name in the classes hashtable
1200 if there is no such class NULL is returned
1202 *******************************************************************************/
1204 classinfo *class_get(utf *classname)
1206 classinfo *c; /* hashtable element */
1207 u4 key; /* hashkey computed from classname */
1208 u4 slot; /* slot in hashtable */
1211 key = utf_hashkey(classname->text, classname->blength);
1212 slot = key & (class_hash.size-1);
1213 c = class_hash.ptr[slot];
1215 /* search external hash-chain */
1217 if (c->name->blength == classname->blength) {
1218 /* compare classnames */
1219 for (i = 0; i < classname->blength; i++)
1220 if (classname->text[i] != c->name->text[i])
1223 /* class found in hashtable */
1231 /* class not found */
1236 /* class_remove ****************************************************************
1238 removes the class entry wth the specified name in the classes hashtable,
1239 furthermore the class' resources are freed
1240 if there is no such class false is returned
1242 *******************************************************************************/
1244 bool class_remove(classinfo *c)
1246 classinfo *tc; /* hashtable element */
1248 u4 key; /* hashkey computed from classname */
1249 u4 slot; /* slot in hashtable */
1252 key = utf_hashkey(c->name->text, c->name->blength);
1253 slot = key & (class_hash.size - 1);
1254 tc = class_hash.ptr[slot];
1257 /* search external hash-chain */
1259 if (tc->name->blength == c->name->blength) {
1261 /* compare classnames */
1262 for (i = 0; i < c->name->blength; i++)
1263 if (tc->name->text[i] != c->name->text[i])
1266 /* class found in hashtable */
1268 class_hash.ptr[slot] = tc->hashlink;
1271 pc->hashlink = tc->hashlink;
1284 /* class not found */
1289 /***************** Function: class_array_of ***********************************
1291 Returns an array class with the given component class.
1292 The array class is dynamically created if neccessary.
1294 *******************************************************************************/
1296 classinfo *class_array_of(classinfo *component)
1302 /* Assemble the array class name */
1303 namelen = component->name->blength;
1305 if (component->name->text[0] == '[') {
1306 /* the component is itself an array */
1307 namebuf = DMNEW(char, namelen + 1);
1309 memcpy(namebuf + 1, component->name->text, namelen);
1313 /* the component is a non-array class */
1314 namebuf = DMNEW(char, namelen + 3);
1317 memcpy(namebuf + 2, component->name->text, namelen);
1318 namebuf[2 + namelen] = ';';
1322 /* load this class ;-) and link it */
1323 c = class_new(utf_new(namebuf, namelen));
1330 /*************** Function: class_multiarray_of ********************************
1332 Returns an array class with the given dimension and element class.
1333 The array class is dynamically created if neccessary.
1335 *******************************************************************************/
1337 classinfo *class_multiarray_of(int dim, classinfo *element)
1343 panic("Invalid array dimension requested");
1345 /* Assemble the array class name */
1346 namelen = element->name->blength;
1348 if (element->name->text[0] == '[') {
1349 /* the element is itself an array */
1350 namebuf = DMNEW(char, namelen + dim);
1351 memcpy(namebuf + dim, element->name->text, namelen);
1355 /* the element is a non-array class */
1356 namebuf = DMNEW(char, namelen + 2 + dim);
1358 memcpy(namebuf + dim + 1, element->name->text, namelen);
1359 namelen += (2 + dim);
1360 namebuf[namelen - 1] = ';';
1362 memset(namebuf, '[', dim);
1364 return class_new(utf_new(namebuf, namelen));
1367 /************************** function: utf_strlen ******************************
1369 determine number of unicode characters in the utf string
1371 *******************************************************************************/
1373 u4 utf_strlen(utf *u)
1375 char *endpos; /* points behind utf string */
1376 char *utf_ptr; /* current position in utf text */
1377 u4 len = 0; /* number of unicode characters */
1380 *exceptionptr = new_nullpointerexception();
1384 endpos = utf_end(u);
1387 while (utf_ptr < endpos) {
1389 /* next unicode character */
1390 utf_nextu2(&utf_ptr);
1393 if (utf_ptr != endpos)
1394 /* string ended abruptly */
1395 panic("illegal utf string");
1402 * These are local overrides for various environment variables in Emacs.
1403 * Please do not remove this and leave it at the end of the file, where
1404 * Emacs will automagically detect them.
1405 * ---------------------------------------------------------------------
1408 * indent-tabs-mode: t