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 1240 2004-06-30 20:07:25Z twisti $
47 #include <sys/types.h>
55 #include "statistics.h"
56 #include "threads/thread.h"
57 #include "threads/locks.h"
58 #include "toolbox/logging.h"
59 #include "toolbox/memory.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 = utf_end(u); /* points behind utf string */
174 char *utf_ptr = u->text; /* current position in utf text */
179 while (utf_ptr < endpos) {
180 /* read next unicode character */
181 u2 c = utf_nextu2(&utf_ptr);
182 if (c >= 32 && c <= 127) printf("%c", c);
190 /********************* function: utf_display *********************************
192 write utf symbol to stdout (debugging purposes)
194 ******************************************************************************/
196 void utf_display_classname(utf *u)
198 char *endpos = utf_end(u); /* points behind utf string */
199 char *utf_ptr = u->text; /* current position in utf text */
204 while (utf_ptr < endpos) {
205 /* read next unicode character */
206 u2 c = utf_nextu2(&utf_ptr);
207 if (c == '/') c = '.';
208 if (c >= 32 && c <= 127) printf("%c", c);
216 /************************* function: log_utf *********************************
220 ******************************************************************************/
224 char buf[MAXLOGTEXT];
230 /********************** function: log_plain_utf ******************************
232 log utf symbol (without printing "LOG: " and newline)
234 ******************************************************************************/
236 void log_plain_utf(utf *u)
238 char buf[MAXLOGTEXT];
240 dolog_plain("%s", buf);
244 /************************ function: utf_sprint *******************************
246 write utf symbol into c-string (debugging purposes)
248 ******************************************************************************/
250 void utf_sprint(char *buffer, utf *u)
252 char *endpos = utf_end(u); /* points behind utf string */
253 char *utf_ptr = u->text; /* current position in utf text */
254 u2 pos = 0; /* position in c-string */
256 while (utf_ptr < endpos)
257 /* copy next unicode character */
258 buffer[pos++] = utf_nextu2(&utf_ptr);
260 /* terminate string */
265 /************************ function: utf_sprint_classname *********************
267 write utf symbol into c-string (debugging purposes)
269 ******************************************************************************/
271 void utf_sprint_classname(char *buffer, utf *u)
273 char *endpos = utf_end(u); /* points behind utf string */
274 char *utf_ptr = u->text; /* current position in utf text */
275 u2 pos = 0; /* position in c-string */
277 while (utf_ptr < endpos) {
278 /* copy next unicode character */
279 u2 c = utf_nextu2(&utf_ptr);
280 if (c == '/') c = '.';
284 /* terminate string */
289 /********************* Funktion: utf_fprint **********************************
291 write utf symbol into file
293 ******************************************************************************/
295 void utf_fprint(FILE *file, utf *u)
297 char *endpos = utf_end(u); /* points behind utf string */
298 char *utf_ptr = u->text; /* current position in utf text */
303 while (utf_ptr < endpos) {
304 /* read next unicode character */
305 u2 c = utf_nextu2(&utf_ptr);
307 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
308 else fprintf(file, "?");
313 /********************* Funktion: utf_fprint **********************************
315 write utf symbol into file
317 ******************************************************************************/
319 void utf_fprint_classname(FILE *file, utf *u)
321 char *endpos = utf_end(u); /* points behind utf string */
322 char *utf_ptr = u->text; /* current position in utf text */
327 while (utf_ptr < endpos) {
328 /* read next unicode character */
329 u2 c = utf_nextu2(&utf_ptr);
330 if (c == '/') c = '.';
332 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
333 else fprintf(file, "?");
338 /****************** internal function: utf_hashkey ***************************
340 The hashkey is computed from the utf-text by using up to 8 characters.
341 For utf-symbols longer than 15 characters 3 characters are taken from
342 the beginning and the end, 2 characters are taken from the middle.
344 ******************************************************************************/
346 #define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
347 #define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
349 static u4 utf_hashkey(char *text, u4 length)
351 char *start_pos = text; /* pointer to utf text */
356 case 0: /* empty string */
359 case 1: return fbs(0);
360 case 2: return fbs(0) ^ nbs(3);
361 case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
362 case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
363 case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
364 case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
365 case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
366 case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
373 return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
382 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
391 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
403 return a ^ nbs(9) ^ nbs(10);
415 return a ^ nbs(9) ^ nbs(10);
426 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
437 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
439 default: /* 3 characters from beginning */
445 /* 2 characters from middle */
446 text = start_pos + (length / 2);
451 /* 3 characters from end */
452 text = start_pos + length - 4;
457 return a ^ nbs(10) ^ nbs(11);
462 /*************************** function: utf_hashkey ***************************
464 compute the hashkey of a unicode string
466 ******************************************************************************/
468 u4 unicode_hashkey(u2 *text, u2 len)
470 return utf_hashkey((char*) text, len);
474 /************************ function: utf_new **********************************
476 Creates a new utf-symbol, the text of the symbol is passed as a
477 u1-array. The function searches the utf-hashtable for a utf-symbol
478 with this text. On success the element returned, otherwise a new
479 hashtable element is created.
481 If the number of entries in the hashtable exceeds twice the size of the
482 hashtable slots a reorganization of the hashtable is done and the utf
483 symbols are copied to a new hashtable with doubled size.
485 ******************************************************************************/
487 utf *utf_new_intern(char *text, u2 length)
489 u4 key; /* hashkey computed from utf-text */
490 u4 slot; /* slot in hashtable */
491 utf *u; /* hashtable element */
499 key = utf_hashkey(text, length);
500 slot = key & (utf_hash.size-1);
501 u = utf_hash.ptr[slot];
503 /* search external hash chain for utf-symbol */
505 if (u->blength == length) {
507 /* compare text of hashtable elements */
508 for (i = 0; i < length; i++)
509 if (text[i] != u->text[i]) goto nomatch;
513 count_utf_new_found++;
515 /* log_text("symbol found in hash table");*/
516 /* symbol found in hashtable */
527 u = u->hashlink; /* next element in external chain */
532 count_utf_len += sizeof(utf) + length;
535 /* location in hashtable found, create new utf element */
537 u->blength = length; /* length in bytes of utfstring */
538 u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain */
539 u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
540 memcpy(u->text, text, length); /* copy utf-text */
541 u->text[length] = '\0';
542 utf_hash.ptr[slot] = u; /* insert symbol into table */
544 utf_hash.entries++; /* update number of entries */
546 if (utf_hash.entries > (utf_hash.size * 2)) {
548 /* reorganization of hashtable, average length of
549 the external chains is approx. 2 */
553 hashtable newhash; /* the new hashtable */
555 /* create new hashtable, double the size */
556 init_hashtable(&newhash, utf_hash.size * 2);
557 newhash.entries = utf_hash.entries;
561 count_utf_len += sizeof(utf*) * utf_hash.size;
564 /* transfer elements to new hashtable */
565 for (i = 0; i < utf_hash.size; i++) {
566 u = (utf *) utf_hash.ptr[i];
568 utf *nextu = u->hashlink;
569 u4 slot = utf_hashkey(u->text, u->blength) & (newhash.size - 1);
571 u->hashlink = (utf *) newhash.ptr[slot];
572 newhash.ptr[slot] = u;
574 /* follow link in external hash chain */
579 /* dispose old table */
580 MFREE(utf_hash.ptr, void*, utf_hash.size);
588 utf *utf_new(char *text, u2 length)
592 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
596 r = utf_new_intern(text, length);
598 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
606 /********************* function: utf_new_char ********************************
608 creates a new utf symbol, the text for this symbol is passed
609 as a c-string ( = char* )
611 ******************************************************************************/
613 utf *utf_new_char(char *text)
615 return utf_new(text, strlen(text));
619 /********************* function: utf_new_char ********************************
621 creates a new utf symbol, the text for this symbol is passed
622 as a c-string ( = char* )
623 "." characters are going to be replaced by "/". since the above function is
624 used often, this is a separte function, instead of an if
626 ******************************************************************************/
628 utf *utf_new_char_classname(char *text)
630 if (strchr(text, '.')) {
631 char *txt = strdup(text);
632 char *end = txt + strlen(txt);
635 for (c = txt; c < end; c++)
636 if (*c == '.') *c = '/';
637 tmpRes = utf_new(txt, strlen(txt));
642 return utf_new(text, strlen(text));
646 /************************** Funktion: utf_show ******************************
648 writes the utf symbols in the utfhash to stdout and
649 displays the number of external hash chains grouped
650 according to the chainlength
653 *****************************************************************************/
658 #define CHAIN_LIMIT 20 /* limit for seperated enumeration */
660 u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
661 u4 max_chainlength = 0; /* maximum length of the chains */
662 u4 sum_chainlength = 0; /* sum of the chainlengths */
663 u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
666 printf ("UTF-HASH:\n");
668 /* show element of utf-hashtable */
669 for (i=0; i<utf_hash.size; i++) {
670 utf *u = utf_hash.ptr[i];
672 printf ("SLOT %d: ", (int) i);
684 printf ("UTF-HASH: %d slots for %d entries\n",
685 (int) utf_hash.size, (int) utf_hash.entries );
688 if (utf_hash.entries == 0)
691 printf("chains:\n chainlength number of chains %% of utfstrings\n");
693 for (i=0;i<CHAIN_LIMIT;i++)
696 /* count numbers of hashchains according to their length */
697 for (i=0; i<utf_hash.size; i++) {
699 utf *u = (utf*) utf_hash.ptr[i];
702 /* determine chainlength */
708 /* update sum of all chainlengths */
709 sum_chainlength+=chain_length;
711 /* determine the maximum length of the chains */
712 if (chain_length>max_chainlength)
713 max_chainlength = chain_length;
715 /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
716 if (chain_length>=CHAIN_LIMIT) {
717 beyond_limit+=chain_length;
718 chain_length=CHAIN_LIMIT-1;
721 /* update number of hashchains of current length */
722 chain_count[chain_length]++;
725 /* display results */
726 for (i=1;i<CHAIN_LIMIT-1;i++)
727 printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/utf_hash.entries));
729 printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/utf_hash.entries);
732 printf("max. chainlength:%5d\n",max_chainlength);
734 /* avg. chainlength = sum of chainlengths / number of chains */
735 printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (utf_hash.size-chain_count[0]));
738 /******************************************************************************
739 *********************** Misc support functions ********************************
740 ******************************************************************************/
743 /******************** Function: desc_to_type **********************************
745 Determines the corresponding Java base data type for a given type
748 ******************************************************************************/
750 u2 desc_to_type(utf *descriptor)
752 char *utf_ptr = descriptor->text; /* current position in utf text */
753 char logtext[MAXLOGTEXT];
755 if (descriptor->blength < 1) panic("Type-Descriptor is empty string");
757 switch (*utf_ptr++) {
762 case 'Z': return TYPE_INT;
763 case 'D': return TYPE_DOUBLE;
764 case 'F': return TYPE_FLOAT;
765 case 'J': return TYPE_LONG;
767 case '[': return TYPE_ADDRESS;
770 sprintf(logtext, "Invalid Type-Descriptor: ");
771 utf_sprint(logtext+strlen(logtext), descriptor);
778 /********************** Function: desc_typesize *******************************
780 Calculates the lenght in bytes needed for a data element of the type given
781 by its type descriptor.
783 ******************************************************************************/
785 u2 desc_typesize(utf *descriptor)
787 switch (desc_to_type(descriptor)) {
788 case TYPE_INT: return 4;
789 case TYPE_LONG: return 8;
790 case TYPE_FLOAT: return 4;
791 case TYPE_DOUBLE: return 8;
792 case TYPE_ADDRESS: return sizeof(voidptr);
798 /********************** function: utf_nextu2 *********************************
800 read the next unicode character from the utf string and
801 increment the utf-string pointer accordingly
803 ******************************************************************************/
805 u2 utf_nextu2(char **utf_ptr)
807 /* uncompressed unicode character */
809 /* current position in utf text */
810 unsigned char *utf = (unsigned char *) (*utf_ptr);
811 /* bytes representing the unicode character */
812 unsigned char ch1, ch2, ch3;
813 /* number of bytes used to represent the unicode character */
816 switch ((ch1 = utf[0]) >> 4) {
817 default: /* 1 byte */
821 case 0xD: /* 2 bytes */
822 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
823 unsigned char high = ch1 & 0x1F;
824 unsigned char low = ch2 & 0x3F;
825 unicode_char = (high << 6) + low;
830 case 0xE: /* 2 or 3 bytes */
831 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
832 if (((ch3 = utf[2]) & 0xC0) == 0x80) {
833 unsigned char low = ch3 & 0x3f;
834 unsigned char mid = ch2 & 0x3f;
835 unsigned char high = ch1 & 0x0f;
836 unicode_char = (((high << 6) + mid) << 6) + low;
844 /* update position in utf-text */
845 *utf_ptr = (char *) (utf + len);
850 /********************* function: is_valid_utf ********************************
852 return true if the given string is a valid UTF-8 string
854 utf_ptr...points to first character
855 end_pos...points after last character
857 ******************************************************************************/
859 static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26};
862 is_valid_utf(char *utf_ptr,char *end_pos)
869 if (end_pos < utf_ptr) return false;
870 bytes = end_pos - utf_ptr;
873 /*dolog("%c %02x",c,c);*/
874 if (!c) return false; /* 0x00 is not allowed */
875 if ((c & 0x80) == 0) continue; /* ASCII */
877 if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
878 else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
879 else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
880 else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
881 else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
882 else return false; /* invalid leading byte */
884 if (len > 2) return false; /* Java limitation */
886 v = (unsigned long)c & (0x3f >> len);
888 if ((bytes -= len) < 0) return false; /* missing bytes */
890 for (i = len; i--; ) {
892 /*dolog(" %c %02x",c,c);*/
893 if ((c & 0xc0) != 0x80) /* 10xx xxxx */
895 v = (v<<6) | (c & 0x3f);
898 /* dolog("v=%d",v);*/
901 if (len != 1) return false; /* Java special */
904 /* Sun Java seems to allow overlong UTF-8 encodings */
906 if (v < min_codepoint[len]) { /* overlong UTF-8 */
908 fprintf(stderr,"WARNING: Overlong UTF-8 sequence found.\n");
909 /* XXX change this to panic? */
913 /* surrogates in UTF-8 seem to be allowed in Java classfiles */
914 /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
916 /* even these seem to be allowed */
917 /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
923 /********************* function: is_valid_name *******************************
925 return true if the given string may be used as a class/field/method name.
926 (Currently this only disallows empty strings and control characters.)
928 NOTE: The string is assumed to have passed is_valid_utf!
930 utf_ptr...points to first character
931 end_pos...points after last character
933 ******************************************************************************/
936 is_valid_name(char *utf_ptr,char *end_pos)
938 if (end_pos <= utf_ptr) return false; /* disallow empty names */
940 while (utf_ptr < end_pos) {
941 unsigned char c = *utf_ptr++;
943 if (c < 0x20) return false; /* disallow control characters */
944 if (c == 0xc0 && (unsigned char)*utf_ptr == 0x80) return false; /* disallow zero */
950 is_valid_name_utf(utf *u)
952 return is_valid_name(u->text,utf_end(u));
955 /******************** Function: class_new **************************************
957 searches for the class with the specified name in the classes hashtable,
958 if there is no such class a new classinfo structure is created and inserted
959 into the list of classes to be loaded
961 *******************************************************************************/
963 classinfo *class_new_intern(utf *classname)
965 classinfo *c; /* hashtable element */
966 u4 key; /* hashkey computed from classname */
967 u4 slot; /* slot in hashtable */
970 key = utf_hashkey(classname->text, classname->blength);
971 slot = key & (class_hash.size - 1);
972 c = class_hash.ptr[slot];
974 /* search external hash chain for the class */
976 if (c->name->blength == classname->blength) {
977 for (i = 0; i < classname->blength; i++)
978 if (classname->text[i] != c->name->text[i]) goto nomatch;
980 /* class found in hashtable */
985 c = c->hashlink; /* next element in external chain */
988 /* location in hashtable found, create new classinfo structure */
990 #if defined(STATISTICS)
992 count_class_infos += sizeof(classinfo);
996 char logtext[MAXLOGTEXT];
997 sprintf(logtext, "Creating class: ");
998 utf_sprint_classname(logtext + strlen(logtext), classname);
1002 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
1003 /*c=NEW(classinfo);*/
1006 c->name = classname;
1007 c->packagename = NULL;
1014 c->interfacescount = 0;
1015 c->interfaces = NULL;
1018 c->methodscount = 0;
1023 c->instancesize = 0;
1024 c->header.vftbl = NULL;
1025 c->innerclasscount = 0;
1026 c->innerclass = NULL;
1028 c->initialized = false;
1029 c->initializing = false;
1030 c->classvftbl = false;
1033 c->classloader = NULL;
1034 c->sourcefile = NULL;
1036 /* insert class into the hashtable */
1037 c->hashlink = class_hash.ptr[slot];
1038 class_hash.ptr[slot] = c;
1040 /* update number of hashtable-entries */
1041 class_hash.entries++;
1043 if (class_hash.entries > (class_hash.size * 2)) {
1045 /* reorganization of hashtable, average length of
1046 the external chains is approx. 2 */
1050 hashtable newhash; /* the new hashtable */
1052 /* create new hashtable, double the size */
1053 init_hashtable(&newhash, class_hash.size * 2);
1054 newhash.entries = class_hash.entries;
1056 /* transfer elements to new hashtable */
1057 for (i = 0; i < class_hash.size; i++) {
1058 c = (classinfo *) class_hash.ptr[i];
1060 classinfo *nextc = c->hashlink;
1061 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
1063 c->hashlink = newhash.ptr[slot];
1064 newhash.ptr[slot] = c;
1070 /* dispose old table */
1071 MFREE(class_hash.ptr, void*, class_hash.size);
1072 class_hash = newhash;
1075 /* Array classes need further initialization. */
1076 if (c->name->text[0] == '[') {
1077 /* Array classes are not loaded from classfiles. */
1080 c->packagename = array_packagename;
1083 /* Find the package name */
1084 /* Classes in the unnamed package keep packagename == NULL. */
1085 char *p = utf_end(c->name) - 1;
1086 char *start = c->name->text;
1087 for (;p > start; --p) {
1089 c->packagename = utf_new(start, p - start);
1099 classinfo *class_new(utf *classname)
1103 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1107 c = class_new_intern(classname);
1109 /* we support eager class loading and linking on demand */
1115 list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
1118 if (!class_load(c)) {
1119 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1126 /* link all referenced classes */
1128 tc = list_first(&unlinkedclasses);
1131 /* skip the current loaded/linked class */
1133 if (!class_link(tc)) {
1134 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1141 /* we need a tmp variable here, because list_remove sets prev and
1143 tmp = list_next(&unlinkedclasses, tc);
1144 list_remove(&unlinkedclasses, tc);
1149 if (!class_link(c)) {
1150 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1158 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1166 /******************** Function: class_get **************************************
1168 searches for the class with the specified name in the classes hashtable
1169 if there is no such class NULL is returned
1171 *******************************************************************************/
1173 classinfo *class_get(utf *classname)
1175 classinfo *c; /* hashtable element */
1176 u4 key; /* hashkey computed from classname */
1177 u4 slot; /* slot in hashtable */
1180 key = utf_hashkey(classname->text, classname->blength);
1181 slot = key & (class_hash.size-1);
1182 c = class_hash.ptr[slot];
1184 /* search external hash-chain */
1186 if (c->name->blength == classname->blength) {
1187 /* compare classnames */
1188 for (i = 0; i < classname->blength; i++)
1189 if (classname->text[i] != c->name->text[i])
1192 /* class found in hashtable */
1200 /* class not found */
1205 /* class_remove ****************************************************************
1207 removes the class entry wth the specified name in the classes hashtable,
1208 furthermore the class' resources are freed
1209 if there is no such class false is returned
1211 *******************************************************************************/
1213 bool class_remove(classinfo *c)
1215 classinfo *tc; /* hashtable element */
1217 u4 key; /* hashkey computed from classname */
1218 u4 slot; /* slot in hashtable */
1221 key = utf_hashkey(c->name->text, c->name->blength);
1222 slot = key & (class_hash.size - 1);
1223 tc = class_hash.ptr[slot];
1226 /* search external hash-chain */
1228 if (tc->name->blength == c->name->blength) {
1230 /* compare classnames */
1231 for (i = 0; i < c->name->blength; i++)
1232 if (tc->name->text[i] != c->name->text[i])
1235 /* class found in hashtable */
1237 class_hash.ptr[slot] = tc->hashlink;
1240 pc->hashlink = tc->hashlink;
1253 /* class not found */
1258 /***************** Function: class_array_of ***********************************
1260 Returns an array class with the given component class.
1261 The array class is dynamically created if neccessary.
1263 *******************************************************************************/
1265 classinfo *class_array_of(classinfo *component)
1271 /* Assemble the array class name */
1272 namelen = component->name->blength;
1274 if (component->name->text[0] == '[') {
1275 /* the component is itself an array */
1276 namebuf = DMNEW(char, namelen + 1);
1278 memcpy(namebuf + 1, component->name->text, namelen);
1282 /* the component is a non-array class */
1283 namebuf = DMNEW(char, namelen + 3);
1286 memcpy(namebuf + 2, component->name->text, namelen);
1287 namebuf[2 + namelen] = ';';
1291 /* load this class ;-) and link it */
1292 c = class_new(utf_new(namebuf, namelen));
1299 /*************** Function: class_multiarray_of ********************************
1301 Returns an array class with the given dimension and element class.
1302 The array class is dynamically created if neccessary.
1304 *******************************************************************************/
1306 classinfo *class_multiarray_of(int dim, classinfo *element)
1312 panic("Invalid array dimension requested");
1314 /* Assemble the array class name */
1315 namelen = element->name->blength;
1317 if (element->name->text[0] == '[') {
1318 /* the element is itself an array */
1319 namebuf = DMNEW(char, namelen + dim);
1320 memcpy(namebuf + dim, element->name->text, namelen);
1324 /* the element is a non-array class */
1325 namebuf = DMNEW(char, namelen + 2 + dim);
1327 memcpy(namebuf + dim + 1, element->name->text, namelen);
1328 namelen += (2 + dim);
1329 namebuf[namelen - 1] = ';';
1331 memset(namebuf, '[', dim);
1333 return class_new(utf_new(namebuf, namelen));
1336 /************************** function: utf_strlen ******************************
1338 determine number of unicode characters in the utf string
1340 *******************************************************************************/
1342 u4 utf_strlen(utf *u)
1344 char *endpos = utf_end(u); /* points behind utf string */
1345 char *utf_ptr = u->text; /* current position in utf text */
1346 u4 len = 0; /* number of unicode characters */
1348 while (utf_ptr < endpos) {
1350 /* next unicode character */
1351 utf_nextu2(&utf_ptr);
1354 if (utf_ptr != endpos)
1355 /* string ended abruptly */
1356 panic("illegal utf string");
1363 * These are local overrides for various environment variables in Emacs.
1364 * Please do not remove this and leave it at the end of the file, where
1365 * Emacs will automagically detect them.
1366 * ---------------------------------------------------------------------
1369 * indent-tabs-mode: t