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 1087 2004-05-26 21:27:03Z 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 /******************************************************************************
71 *********************** hashtable functions **********************************
72 ******************************************************************************/
74 /* hashsize must be power of 2 */
76 #define UTF_HASHSTART 16384 /* initial size of utf-hash */
77 #define HASHSTART 2048 /* initial size of javastring and class-hash */
80 /******************** function: init_hashtable ******************************
82 Initializes a hashtable structure and allocates memory.
83 The parameter size specifies the initial size of the hashtable.
85 *****************************************************************************/
87 void init_hashtable(hashtable *hash, u4 size)
93 hash->ptr = MNEW(void*, size);
96 for (i = 0; i < size; i++) hash->ptr[i] = NULL;
100 /*********************** function: tables_init *****************************
102 creates hashtables for symboltables
103 (called once at startup)
105 *****************************************************************************/
109 init_hashtable(&utf_hash, UTF_HASHSTART); /* hashtable for utf8-symbols */
110 init_hashtable(&string_hash, HASHSTART); /* hashtable for javastrings */
111 init_hashtable(&class_hash, HASHSTART); /* hashtable for classes */
115 count_utf_len += sizeof(utf*) * utf_hash.size;
121 /********************** function: tables_close ******************************
123 free memory for hashtables
125 *****************************************************************************/
127 void tables_close(stringdeleter del)
133 /* dispose utf symbols */
134 for (i = 0; i < utf_hash.size; i++) {
137 /* process elements in external hash chain */
138 utf *nextu = u->hashlink;
139 MFREE(u->text, u1, u->blength);
145 /* dispose javastrings */
146 for (i = 0; i < string_hash.size; i++) {
147 s = string_hash.ptr[i];
149 /* process elements in external hash chain */
150 literalstring *nexts = s->hashlink;
152 FREE(s, literalstring);
157 /* dispose hashtable structures */
158 MFREE(utf_hash.ptr, void*, utf_hash.size);
159 MFREE(string_hash.ptr, void*, string_hash.size);
160 MFREE(class_hash.ptr, void*, class_hash.size);
164 /********************* function: utf_display *********************************
166 write utf symbol to stdout (debugging purposes)
168 ******************************************************************************/
170 void utf_display(utf *u)
172 char *endpos = utf_end(u); /* points behind utf string */
173 char *utf_ptr = u->text; /* current position in utf text */
178 while (utf_ptr < endpos) {
179 /* read next unicode character */
180 u2 c = utf_nextu2(&utf_ptr);
181 if (c >= 32 && c <= 127) printf("%c", c);
189 /********************* function: utf_display *********************************
191 write utf symbol to stdout (debugging purposes)
193 ******************************************************************************/
195 void utf_display_classname(utf *u)
197 char *endpos = utf_end(u); /* points behind utf string */
198 char *utf_ptr = u->text; /* current position in utf text */
203 while (utf_ptr < endpos) {
204 /* read next unicode character */
205 u2 c = utf_nextu2(&utf_ptr);
206 if (c == '/') c = '.';
207 if (c >= 32 && c <= 127) printf("%c", c);
215 /************************* function: log_utf *********************************
219 ******************************************************************************/
223 char buf[MAXLOGTEXT];
229 /********************** function: log_plain_utf ******************************
231 log utf symbol (without printing "LOG: " and newline)
233 ******************************************************************************/
235 void log_plain_utf(utf *u)
237 char buf[MAXLOGTEXT];
239 dolog_plain("%s", buf);
243 /************************ function: utf_sprint *******************************
245 write utf symbol into c-string (debugging purposes)
247 ******************************************************************************/
249 void utf_sprint(char *buffer, utf *u)
251 char *endpos = utf_end(u); /* points behind utf string */
252 char *utf_ptr = u->text; /* current position in utf text */
253 u2 pos = 0; /* position in c-string */
255 while (utf_ptr < endpos)
256 /* copy next unicode character */
257 buffer[pos++] = utf_nextu2(&utf_ptr);
259 /* terminate string */
264 /************************ function: utf_sprint_classname *********************
266 write utf symbol into c-string (debugging purposes)
268 ******************************************************************************/
270 void utf_sprint_classname(char *buffer, utf *u)
272 char *endpos = utf_end(u); /* points behind utf string */
273 char *utf_ptr = u->text; /* current position in utf text */
274 u2 pos = 0; /* position in c-string */
276 while (utf_ptr < endpos) {
277 /* copy next unicode character */
278 u2 c = utf_nextu2(&utf_ptr);
279 if (c == '/') c = '.';
283 /* terminate string */
288 /********************* Funktion: utf_fprint **********************************
290 write utf symbol into file
292 ******************************************************************************/
294 void utf_fprint(FILE *file, utf *u)
296 char *endpos = utf_end(u); /* points behind utf string */
297 char *utf_ptr = u->text; /* current position in utf text */
302 while (utf_ptr < endpos) {
303 /* read next unicode character */
304 u2 c = utf_nextu2(&utf_ptr);
306 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
307 else fprintf(file, "?");
312 /********************* Funktion: utf_fprint **********************************
314 write utf symbol into file
316 ******************************************************************************/
318 void utf_fprint_classname(FILE *file, utf *u)
320 char *endpos = utf_end(u); /* points behind utf string */
321 char *utf_ptr = u->text; /* current position in utf text */
326 while (utf_ptr < endpos) {
327 /* read next unicode character */
328 u2 c = utf_nextu2(&utf_ptr);
329 if (c == '/') c = '.';
331 if (c >= 32 && c <= 127) fprintf(file, "%c", c);
332 else fprintf(file, "?");
337 /****************** internal function: utf_hashkey ***************************
339 The hashkey is computed from the utf-text by using up to 8 characters.
340 For utf-symbols longer than 15 characters 3 characters are taken from
341 the beginning and the end, 2 characters are taken from the middle.
343 ******************************************************************************/
345 #define nbs(val) ((u4) *(++text) << val) /* get next byte, left shift by val */
346 #define fbs(val) ((u4) *( text) << val) /* get first byte, left shift by val */
348 static u4 utf_hashkey(char *text, u4 length)
350 char *start_pos = text; /* pointer to utf text */
355 case 0: /* empty string */
358 case 1: return fbs(0);
359 case 2: return fbs(0) ^ nbs(3);
360 case 3: return fbs(0) ^ nbs(3) ^ nbs(5);
361 case 4: return fbs(0) ^ nbs(2) ^ nbs(4) ^ nbs(6);
362 case 5: return fbs(0) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(6);
363 case 6: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(5) ^ nbs(6);
364 case 7: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6);
365 case 8: return fbs(0) ^ nbs(1) ^ nbs(2) ^ nbs(3) ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7);
372 return a ^ nbs(4) ^ nbs(5) ^ nbs(6) ^ nbs(7) ^ nbs(8);
381 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9);
390 return a ^ nbs(6) ^ nbs(7) ^ nbs(8) ^ nbs(9) ^ nbs(10);
402 return a ^ nbs(9) ^ nbs(10);
414 return a ^ nbs(9) ^ nbs(10);
425 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
436 return a ^ nbs(9) ^ nbs(10) ^ nbs(11);
438 default: /* 3 characters from beginning */
444 /* 2 characters from middle */
445 text = start_pos + (length / 2);
450 /* 3 characters from end */
451 text = start_pos + length - 4;
456 return a ^ nbs(10) ^ nbs(11);
461 /*************************** function: utf_hashkey ***************************
463 compute the hashkey of a unicode string
465 ******************************************************************************/
467 u4 unicode_hashkey(u2 *text, u2 len)
469 return utf_hashkey((char*) text, len);
473 /************************ function: utf_new **********************************
475 Creates a new utf-symbol, the text of the symbol is passed as a
476 u1-array. The function searches the utf-hashtable for a utf-symbol
477 with this text. On success the element returned, otherwise a new
478 hashtable element is created.
480 If the number of entries in the hashtable exceeds twice the size of the
481 hashtable slots a reorganization of the hashtable is done and the utf
482 symbols are copied to a new hashtable with doubled size.
484 ******************************************************************************/
486 utf *utf_new_int(char *text, u2 length)
488 u4 key; /* hashkey computed from utf-text */
489 u4 slot; /* slot in hashtable */
490 utf *u; /* hashtable element */
498 key = utf_hashkey(text, length);
499 slot = key & (utf_hash.size-1);
500 u = utf_hash.ptr[slot];
502 /* search external hash chain for utf-symbol */
504 if (u->blength == length) {
506 /* compare text of hashtable elements */
507 for (i = 0; i < length; i++)
508 if (text[i] != u->text[i]) goto nomatch;
512 count_utf_new_found++;
514 /* log_text("symbol found in hash table");*/
515 /* symbol found in hashtable */
526 u = u->hashlink; /* next element in external chain */
531 count_utf_len += sizeof(utf) + length;
534 /* location in hashtable found, create new utf element */
536 u->blength = length; /* length in bytes of utfstring */
537 u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain */
538 u->text = mem_alloc(length + 1);/* allocate memory for utf-text */
539 memcpy(u->text, text, length); /* copy utf-text */
540 u->text[length] = '\0';
541 utf_hash.ptr[slot] = u; /* insert symbol into table */
543 utf_hash.entries++; /* update number of entries */
545 if (utf_hash.entries > (utf_hash.size * 2)) {
547 /* reorganization of hashtable, average length of
548 the external chains is approx. 2 */
552 hashtable newhash; /* the new hashtable */
554 /* create new hashtable, double the size */
555 init_hashtable(&newhash, utf_hash.size * 2);
556 newhash.entries = utf_hash.entries;
560 count_utf_len += sizeof(utf*) * utf_hash.size;
563 /* transfer elements to new hashtable */
564 for (i = 0; i < utf_hash.size; i++) {
565 u = (utf *) utf_hash.ptr[i];
567 utf *nextu = u->hashlink;
568 u4 slot = utf_hashkey(u->text, u->blength) & (newhash.size - 1);
570 u->hashlink = (utf *) newhash.ptr[slot];
571 newhash.ptr[slot] = u;
573 /* follow link in external hash chain */
578 /* dispose old table */
579 MFREE(utf_hash.ptr, void*, utf_hash.size);
587 utf *utf_new(char *text, u2 length)
591 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
595 r = utf_new_int(text, length);
597 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
605 /********************* function: utf_new_char ********************************
607 creates a new utf symbol, the text for this symbol is passed
608 as a c-string ( = char* )
610 ******************************************************************************/
612 utf *utf_new_char(char *text)
614 return utf_new(text, strlen(text));
618 /********************* function: utf_new_char ********************************
620 creates a new utf symbol, the text for this symbol is passed
621 as a c-string ( = char* )
622 "." characters are going to be replaced by "/". since the above function is
623 used often, this is a separte function, instead of an if
625 ******************************************************************************/
627 utf *utf_new_char_classname(char *text)
629 if (strchr(text, '.')) {
630 char *txt = strdup(text);
631 char *end = txt + strlen(txt);
634 for (c = txt; c < end; c++)
635 if (*c == '.') *c = '/';
636 tmpRes = utf_new(txt, strlen(txt));
641 return utf_new(text, strlen(text));
645 /************************** Funktion: utf_show ******************************
647 writes the utf symbols in the utfhash to stdout and
648 displays the number of external hash chains grouped
649 according to the chainlength
652 *****************************************************************************/
657 #define CHAIN_LIMIT 20 /* limit for seperated enumeration */
659 u4 chain_count[CHAIN_LIMIT]; /* numbers of chains */
660 u4 max_chainlength = 0; /* maximum length of the chains */
661 u4 sum_chainlength = 0; /* sum of the chainlengths */
662 u4 beyond_limit = 0; /* number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
665 printf ("UTF-HASH:\n");
667 /* show element of utf-hashtable */
668 for (i=0; i<utf_hash.size; i++) {
669 utf *u = utf_hash.ptr[i];
671 printf ("SLOT %d: ", (int) i);
683 printf ("UTF-HASH: %d slots for %d entries\n",
684 (int) utf_hash.size, (int) utf_hash.entries );
687 if (utf_hash.entries == 0)
690 printf("chains:\n chainlength number of chains %% of utfstrings\n");
692 for (i=0;i<CHAIN_LIMIT;i++)
695 /* count numbers of hashchains according to their length */
696 for (i=0; i<utf_hash.size; i++) {
698 utf *u = (utf*) utf_hash.ptr[i];
701 /* determine chainlength */
707 /* update sum of all chainlengths */
708 sum_chainlength+=chain_length;
710 /* determine the maximum length of the chains */
711 if (chain_length>max_chainlength)
712 max_chainlength = chain_length;
714 /* update number of utf-symbols in chains with length>=CHAIN_LIMIT-1 */
715 if (chain_length>=CHAIN_LIMIT) {
716 beyond_limit+=chain_length;
717 chain_length=CHAIN_LIMIT-1;
720 /* update number of hashchains of current length */
721 chain_count[chain_length]++;
724 /* display results */
725 for (i=1;i<CHAIN_LIMIT-1;i++)
726 printf(" %2d %17d %18.2f%%\n",i,chain_count[i],(((float) chain_count[i]*i*100)/utf_hash.entries));
728 printf(" >=%2d %17d %18.2f%%\n",CHAIN_LIMIT-1,chain_count[CHAIN_LIMIT-1],((float) beyond_limit*100)/utf_hash.entries);
731 printf("max. chainlength:%5d\n",max_chainlength);
733 /* avg. chainlength = sum of chainlengths / number of chains */
734 printf("avg. chainlength:%5.2f\n",(float) sum_chainlength / (utf_hash.size-chain_count[0]));
737 /******************************************************************************
738 *********************** Misc support functions ********************************
739 ******************************************************************************/
742 /******************** Function: desc_to_type **********************************
744 Determines the corresponding Java base data type for a given type
747 ******************************************************************************/
749 u2 desc_to_type(utf *descriptor)
751 char *utf_ptr = descriptor->text; /* current position in utf text */
752 char logtext[MAXLOGTEXT];
754 if (descriptor->blength < 1) panic("Type-Descriptor is empty string");
756 switch (*utf_ptr++) {
761 case 'Z': return TYPE_INT;
762 case 'D': return TYPE_DOUBLE;
763 case 'F': return TYPE_FLOAT;
764 case 'J': return TYPE_LONG;
766 case '[': return TYPE_ADDRESS;
769 sprintf(logtext, "Invalid Type-Descriptor: ");
770 utf_sprint(logtext+strlen(logtext), descriptor);
777 /********************** Function: desc_typesize *******************************
779 Calculates the lenght in bytes needed for a data element of the type given
780 by its type descriptor.
782 ******************************************************************************/
784 u2 desc_typesize(utf *descriptor)
786 switch (desc_to_type(descriptor)) {
787 case TYPE_INT: return 4;
788 case TYPE_LONG: return 8;
789 case TYPE_FLOAT: return 4;
790 case TYPE_DOUBLE: return 8;
791 case TYPE_ADDRESS: return sizeof(voidptr);
797 /********************** function: utf_nextu2 *********************************
799 read the next unicode character from the utf string and
800 increment the utf-string pointer accordingly
802 ******************************************************************************/
804 u2 utf_nextu2(char **utf_ptr)
806 /* uncompressed unicode character */
808 /* current position in utf text */
809 unsigned char *utf = (unsigned char *) (*utf_ptr);
810 /* bytes representing the unicode character */
811 unsigned char ch1, ch2, ch3;
812 /* number of bytes used to represent the unicode character */
815 switch ((ch1 = utf[0]) >> 4) {
816 default: /* 1 byte */
820 case 0xD: /* 2 bytes */
821 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
822 unsigned char high = ch1 & 0x1F;
823 unsigned char low = ch2 & 0x3F;
824 unicode_char = (high << 6) + low;
829 case 0xE: /* 2 or 3 bytes */
830 if (((ch2 = utf[1]) & 0xC0) == 0x80) {
831 if (((ch3 = utf[2]) & 0xC0) == 0x80) {
832 unsigned char low = ch3 & 0x3f;
833 unsigned char mid = ch2 & 0x3f;
834 unsigned char high = ch1 & 0x0f;
835 unicode_char = (((high << 6) + mid) << 6) + low;
843 /* update position in utf-text */
844 *utf_ptr = (char *) (utf + len);
849 /********************* function: is_valid_utf ********************************
851 return true if the given string is a valid UTF-8 string
853 utf_ptr...points to first character
854 end_pos...points after last character
856 ******************************************************************************/
858 static unsigned long min_codepoint[6] = {0,1L<<7,1L<<11,1L<<16,1L<<21,1L<<26};
861 is_valid_utf(char *utf_ptr,char *end_pos)
868 if (end_pos < utf_ptr) return false;
869 bytes = end_pos - utf_ptr;
872 /*dolog("%c %02x",c,c);*/
873 if (!c) return false; /* 0x00 is not allowed */
874 if ((c & 0x80) == 0) continue; /* ASCII */
876 if ((c & 0xe0) == 0xc0) len = 1; /* 110x xxxx */
877 else if ((c & 0xf0) == 0xe0) len = 2; /* 1110 xxxx */
878 else if ((c & 0xf8) == 0xf0) len = 3; /* 1111 0xxx */
879 else if ((c & 0xfc) == 0xf8) len = 4; /* 1111 10xx */
880 else if ((c & 0xfe) == 0xfc) len = 5; /* 1111 110x */
881 else return false; /* invalid leading byte */
883 if (len > 2) return false; /* Java limitation */
885 v = (unsigned long)c & (0x3f >> len);
887 if ((bytes -= len) < 0) return false; /* missing bytes */
889 for (i = len; i--; ) {
891 /*dolog(" %c %02x",c,c);*/
892 if ((c & 0xc0) != 0x80) /* 10xx xxxx */
894 v = (v<<6) | (c & 0x3f);
897 /* dolog("v=%d",v);*/
900 if (len != 1) return false; /* Java special */
903 /* Sun Java seems to allow overlong UTF-8 encodings */
905 if (v < min_codepoint[len]) { /* overlong UTF-8 */
907 fprintf(stderr,"WARNING: Overlong UTF-8 sequence found.\n");
908 /* XXX change this to panic? */
912 /* surrogates in UTF-8 seem to be allowed in Java classfiles */
913 /* if (v >= 0xd800 && v <= 0xdfff) return false; */ /* surrogates */
915 /* even these seem to be allowed */
916 /* if (v == 0xfffe || v == 0xffff) return false; */ /* invalid codepoints */
922 /********************* function: is_valid_name *******************************
924 return true if the given string may be used as a class/field/method name.
925 (Currently this only disallows empty strings and control characters.)
927 NOTE: The string is assumed to have passed is_valid_utf!
929 utf_ptr...points to first character
930 end_pos...points after last character
932 ******************************************************************************/
935 is_valid_name(char *utf_ptr,char *end_pos)
937 if (end_pos <= utf_ptr) return false; /* disallow empty names */
939 while (utf_ptr < end_pos) {
940 unsigned char c = *utf_ptr++;
942 if (c < 0x20) return false; /* disallow control characters */
943 if (c == 0xc0 && (unsigned char)*utf_ptr == 0x80) return false; /* disallow zero */
949 is_valid_name_utf(utf *u)
951 return is_valid_name(u->text,utf_end(u));
954 /******************** Function: class_new **************************************
956 searches for the class with the specified name in the classes hashtable,
957 if there is no such class a new classinfo structure is created and inserted
958 into the list of classes to be loaded
960 *******************************************************************************/
962 classinfo *class_new_int(utf *classname)
964 classinfo *c; /* hashtable element */
965 u4 key; /* hashkey computed from classname */
966 u4 slot; /* slot in hashtable */
969 key = utf_hashkey(classname->text, classname->blength);
970 slot = key & (class_hash.size - 1);
971 c = class_hash.ptr[slot];
973 /* search external hash chain for the class */
975 if (c->name->blength == classname->blength) {
976 for (i = 0; i < classname->blength; i++)
977 if (classname->text[i] != c->name->text[i]) goto nomatch;
979 /* class found in hashtable */
984 c = c->hashlink; /* next element in external chain */
987 /* location in hashtable found, create new classinfo structure */
991 count_class_infos += sizeof(classinfo);
995 char logtext[MAXLOGTEXT];
996 sprintf(logtext, "Creating class: ");
997 utf_sprint_classname(logtext + strlen(logtext), classname);
1001 c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
1002 /*c=NEW(classinfo);*/
1005 c->name = classname;
1006 c->packagename = NULL;
1013 c->interfacescount = 0;
1014 c->interfaces = NULL;
1017 c->methodscount = 0;
1022 c->instancesize = 0;
1023 c->header.vftbl = NULL;
1024 c->innerclasscount = 0;
1025 c->innerclass = NULL;
1027 c->initialized = false;
1028 c->classvftbl = false;
1031 c->classloader = NULL;
1032 c->sourcefile = NULL;
1034 /* insert class into the hashtable */
1035 c->hashlink = class_hash.ptr[slot];
1036 class_hash.ptr[slot] = c;
1038 /* update number of hashtable-entries */
1039 class_hash.entries++;
1041 if (class_hash.entries > (class_hash.size * 2)) {
1043 /* reorganization of hashtable, average length of
1044 the external chains is approx. 2 */
1048 hashtable newhash; /* the new hashtable */
1050 /* create new hashtable, double the size */
1051 init_hashtable(&newhash, class_hash.size * 2);
1052 newhash.entries = class_hash.entries;
1054 /* transfer elements to new hashtable */
1055 for (i = 0; i < class_hash.size; i++) {
1056 c = (classinfo *) class_hash.ptr[i];
1058 classinfo *nextc = c->hashlink;
1059 u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
1061 c->hashlink = newhash.ptr[slot];
1062 newhash.ptr[slot] = c;
1068 /* dispose old table */
1069 MFREE(class_hash.ptr, void*, class_hash.size);
1070 class_hash = newhash;
1073 /* Array classes need further initialization. */
1074 if (c->name->text[0] == '[') {
1075 /* Array classes are not loaded from classfiles. */
1078 c->packagename = array_packagename;
1081 /* Find the package name */
1082 /* Classes in the unnamed package keep packagename == NULL. */
1083 char *p = utf_end(c->name) - 1;
1084 char *start = c->name->text;
1085 for (;p > start; --p) {
1087 c->packagename = utf_new(start, p - start);
1093 /* we support eager class loading and linking on demand */
1096 /* all super classes are loaded implicitly */
1097 /* if (!c->loaded) */
1098 /* class_load(c); */
1100 /* if (!c->linked) */
1101 /* class_link(c); */
1108 classinfo *class_new(utf *classname)
1112 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1116 c = class_new_int(classname);
1118 /* we support eager class loading and linking on demand */
1128 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
1136 /******************** Function: class_get **************************************
1138 searches for the class with the specified name in the classes hashtable
1139 if there is no such class NULL is returned
1141 *******************************************************************************/
1143 classinfo *class_get(utf *u)
1145 classinfo *c; /* hashtable element */
1146 u4 key; /* hashkey computed from classname */
1147 u4 slot; /* slot in hashtable */
1150 key = utf_hashkey (u->text, u->blength);
1151 slot = key & (class_hash.size-1);
1152 c = class_hash.ptr[slot];
1154 /* search external hash-chain */
1156 if (c->name->blength == u->blength) {
1158 /* compare classnames */
1159 for (i=0; i<u->blength; i++)
1160 if (u->text[i] != c->name->text[i]) goto nomatch;
1162 /* class found in hashtable */
1170 /* class not found */
1175 /***************** Function: class_array_of ***********************************
1177 Returns an array class with the given component class.
1178 The array class is dynamically created if neccessary.
1180 *******************************************************************************/
1182 classinfo *class_array_of(classinfo *component)
1188 /* Assemble the array class name */
1189 namelen = component->name->blength;
1191 if (component->name->text[0] == '[') {
1192 /* the component is itself an array */
1193 namebuf = DMNEW(char, namelen + 1);
1195 memcpy(namebuf + 1, component->name->text, namelen);
1199 /* the component is a non-array class */
1200 namebuf = DMNEW(char, namelen + 3);
1203 memcpy(namebuf + 2, component->name->text, namelen);
1204 namebuf[2 + namelen] = ';';
1208 /* load this class ;-) and link it */
1209 c = class_new(utf_new(namebuf, namelen));
1216 /*************** Function: class_multiarray_of ********************************
1218 Returns an array class with the given dimension and element class.
1219 The array class is dynamically created if neccessary.
1221 *******************************************************************************/
1223 classinfo *class_multiarray_of(int dim, classinfo *element)
1229 panic("Invalid array dimension requested");
1231 /* Assemble the array class name */
1232 namelen = element->name->blength;
1234 if (element->name->text[0] == '[') {
1235 /* the element is itself an array */
1236 namebuf = DMNEW(char, namelen + dim);
1237 memcpy(namebuf + dim, element->name->text, namelen);
1241 /* the element is a non-array class */
1242 namebuf = DMNEW(char, namelen + 2 + dim);
1244 memcpy(namebuf + dim + 1, element->name->text, namelen);
1245 namelen += (2 + dim);
1246 namebuf[namelen - 1] = ';';
1248 memset(namebuf, '[', dim);
1250 return class_new(utf_new(namebuf, namelen));
1253 /************************** function: utf_strlen ******************************
1255 determine number of unicode characters in the utf string
1257 *******************************************************************************/
1259 u4 utf_strlen(utf *u)
1261 char *endpos = utf_end(u); /* points behind utf string */
1262 char *utf_ptr = u->text; /* current position in utf text */
1263 u4 len = 0; /* number of unicode characters */
1265 while (utf_ptr < endpos) {
1267 /* next unicode character */
1268 utf_nextu2(&utf_ptr);
1271 if (utf_ptr != endpos)
1272 /* string ended abruptly */
1273 panic("illegal utf string");
1280 * These are local overrides for various environment variables in Emacs.
1281 * Please do not remove this and leave it at the end of the file, where
1282 * Emacs will automagically detect them.
1283 * ---------------------------------------------------------------------
1286 * indent-tabs-mode: t