* config.h, vm/types.h: Added.
[cacao.git] / src / vm / string.c
1 /* src/vm/string.c - java.lang.String related functions
2
3    Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
4    R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
5    C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
6    Institut f. Computersprachen - TU Wien
7
8    This file is part of CACAO.
9
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.
14
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.
19
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
23    02111-1307, USA.
24
25    Contact: cacao@complang.tuwien.ac.at
26
27    Authors: Reinhard Grafl
28             Roman Obermaisser
29             Andreas Krall
30
31    Changes: Christian Thalinger
32
33    $Id: string.c 3581 2005-11-05 19:44:38Z twisti $
34
35 */
36
37
38 #include <assert.h>
39
40 #include "config.h"
41 #include "vm/types.h"
42
43 #include "vm/global.h"
44
45 #include "mm/memory.h"
46 #include "native/include/java_lang_String.h"
47 #include "vm/exceptions.h"
48 #include "vm/loader.h"
49 #include "vm/options.h"
50 #include "vm/stringlocal.h"
51 #include "vm/utf8.h"
52
53
54 /* global string definitions **************************************************/
55
56 /* exception/error super class */
57
58 const char *string_java_lang_Throwable =
59     "java/lang/Throwable";
60
61 const char *string_java_lang_VMThrowable =
62     "java/lang/VMThrowable";
63
64
65 /* specify some exception strings for code generation */
66
67 const char *string_java_lang_ArithmeticException =
68     "java/lang/ArithmeticException";
69
70 const char *string_java_lang_ArithmeticException_message =
71     "/ by zero";
72
73 const char *string_java_lang_ArrayIndexOutOfBoundsException =
74     "java/lang/ArrayIndexOutOfBoundsException";
75
76 const char *string_java_lang_ArrayStoreException =
77     "java/lang/ArrayStoreException";
78
79 const char *string_java_lang_ClassCastException =
80     "java/lang/ClassCastException";
81
82 const char *string_java_lang_ClassNotFoundException =
83         "java/lang/ClassNotFoundException";
84
85 const char *string_java_lang_CloneNotSupportedException =
86     "java/lang/CloneNotSupportedException";
87
88 const char *string_java_lang_Exception =
89     "java/lang/Exception";
90
91 const char *string_java_lang_IllegalAccessException =
92     "java/lang/IllegalAccessException";
93
94 const char *string_java_lang_IllegalArgumentException =
95     "java/lang/IllegalArgumentException";
96
97 const char *string_java_lang_IllegalMonitorStateException =
98     "java/lang/IllegalMonitorStateException";
99
100 const char *string_java_lang_IndexOutOfBoundsException =
101     "java/lang/IndexOutOfBoundsException";
102
103 const char *string_java_lang_InstantiationException =
104     "java/lang/InstantiationException";
105
106 const char *string_java_lang_InterruptedException =
107     "java/lang/InterruptedException";
108
109 const char *string_java_lang_NegativeArraySizeException =
110     "java/lang/NegativeArraySizeException";
111
112 const char *string_java_lang_NoSuchFieldException =
113         "java/lang/NoSuchFieldException";
114
115 const char *string_java_lang_NoSuchMethodException =
116         "java/lang/NoSuchMethodException";
117
118 const char *string_java_lang_NullPointerException =
119     "java/lang/NullPointerException";
120
121 const char *string_java_lang_reflect_InvocationTargetException =
122     "java/lang/reflect/InvocationTargetException";
123
124
125 /* specify some error strings for code generation */
126
127 const char *string_java_lang_AbstractMethodError =
128     "java/lang/AbstractMethodError";
129
130 const char *string_java_lang_ClassCircularityError =
131     "java/lang/ClassCircularityError";
132
133 const char *string_java_lang_ClassFormatError =
134     "java/lang/ClassFormatError";
135
136 const char *string_java_lang_Error =
137     "java/lang/Error";
138
139 const char *string_java_lang_ExceptionInInitializerError =
140     "java/lang/ExceptionInInitializerError";
141
142 const char *string_java_lang_IncompatibleClassChangeError =
143     "java/lang/IncompatibleClassChangeError";
144
145 const char *string_java_lang_InstantiationError =
146     "java/lang/InstantiationError";
147
148 const char *string_java_lang_InternalError =
149     "java/lang/InternalError";
150
151 const char *string_java_lang_LinkageError =
152     "java/lang/LinkageError";
153
154 const char *string_java_lang_NoClassDefFoundError =
155     "java/lang/NoClassDefFoundError";
156
157 const char *string_java_lang_NoSuchFieldError =
158         "java/lang/NoSuchFieldError";
159
160 const char *string_java_lang_NoSuchMethodError =
161         "java/lang/NoSuchMethodError";
162
163 const char *string_java_lang_OutOfMemoryError =
164     "java/lang/OutOfMemoryError";
165
166 const char *string_java_lang_UnsatisfiedLinkError =
167     "java/lang/UnsatisfiedLinkError";
168
169 const char *string_java_lang_UnsupportedClassVersionError =
170     "java/lang/UnsupportedClassVersionError";
171
172 const char *string_java_lang_VerifyError =
173     "java/lang/VerifyError";
174
175 const char *string_java_lang_VirtualMachineError =
176     "java/lang/VirtualMachineError";
177
178
179 /* stringtable_update **********************************************************
180
181    Traverses the javastring hashtable and sets the vftbl-entries of
182    javastrings which were temporarily set to NULL, because
183    java.lang.Object was not yet loaded.
184
185 *******************************************************************************/
186  
187 void stringtable_update(void)
188 {
189         java_lang_String *js;   
190         java_chararray *a;
191         literalstring *s;       /* hashtable entry */
192         int i;
193
194         for (i = 0; i < string_hash.size; i++) {
195                 s = string_hash.ptr[i];
196                 if (s) {
197                         while (s) {
198                                                                
199                                 js = (java_lang_String *) s->string;
200                                
201                                 if (!js || !js->value) {
202                                         /* error in hashtable found */
203                                         log_text("invalid literalstring in hashtable");
204                                         assert(0);
205                                 }
206
207                                 a = js->value;
208
209                                 if (!js->header.vftbl) 
210                                         /* vftbl of javastring is NULL */ 
211                                         js->header.vftbl = class_java_lang_String->vftbl;
212
213                                 if (!a->header.objheader.vftbl) 
214                                         /* vftbl of character-array is NULL */ 
215                                         a->header.objheader.vftbl = primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
216
217                                 /* follow link in external hash chain */
218                                 s = s->hashlink;
219                         }       
220                 }               
221         }
222 }
223
224
225 /* javastring_new **************************************************************
226
227    creates a new object of type java/lang/String with the text of 
228    the specified utf8-string
229
230    return: pointer to the string or NULL if memory is exhausted.        
231
232 *******************************************************************************/
233
234 java_lang_String *javastring_new(utf *u)
235 {
236         char *utf_ptr;                  /* current utf character in utf string    */
237         u4 utflength;                   /* length of utf-string if uncompressed   */
238         java_lang_String *s;            /* result-string                          */
239         java_chararray *a;
240         s4 i;
241
242         if (!u) {
243                 *exceptionptr = new_nullpointerexception();
244                 return NULL;
245         }
246
247         utf_ptr = u->text;
248         utflength = utf_strlen(u);
249
250         s = (java_lang_String *) builtin_new(class_java_lang_String);
251         a = builtin_newarray_char(utflength);
252
253         /* javastring or character-array could not be created */
254         if (!a || !s)
255                 return NULL;
256
257         /* decompress utf-string */
258         for (i = 0; i < utflength; i++)
259                 a->data[i] = utf_nextu2(&utf_ptr);
260         
261         /* set fields of the javastring-object */
262         s->value  = a;
263         s->offset = 0;
264         s->count  = utflength;
265
266         return s;
267 }
268
269 /* javastring_new_slash_to_dot *************************************************
270
271    creates a new object of type java/lang/String with the text of 
272    the specified utf8-string with slashes changed to dots
273
274    return: pointer to the string or NULL if memory is exhausted.        
275
276 *******************************************************************************/
277
278 java_lang_String *javastring_new_slash_to_dot(utf *u)
279 {
280         char *utf_ptr;                  /* current utf character in utf string    */
281         u4 utflength;                   /* length of utf-string if uncompressed   */
282         java_lang_String *s;            /* result-string                          */
283         java_chararray *a;
284         s4 i;
285         u2 ch;
286
287         if (!u) {
288                 *exceptionptr = new_nullpointerexception();
289                 return NULL;
290         }
291
292         utf_ptr = u->text;
293         utflength = utf_strlen(u);
294
295         s = (java_lang_String *) builtin_new(class_java_lang_String);
296         a = builtin_newarray_char(utflength);
297
298         /* javastring or character-array could not be created */
299         if (!a || !s)
300                 return NULL;
301
302         /* decompress utf-string */
303         for (i = 0; i < utflength; i++) {
304                 ch = utf_nextu2(&utf_ptr);
305                 if (ch == '/')
306                         ch = '.';
307                 a->data[i] = ch;
308         }
309         
310         /* set fields of the javastring-object */
311         s->value  = a;
312         s->offset = 0;
313         s->count  = utflength;
314
315         return s;
316 }
317
318
319 /* javastring_new_char *********************************************************
320
321    creates a new java/lang/String object which contains the convertet
322    C-string passed via text.
323
324    return: the object pointer or NULL if memory is exhausted.
325
326 *******************************************************************************/
327
328 java_lang_String *javastring_new_char(const char *text)
329 {
330         s4 i;
331         s4 len;                             /* length of the string               */
332         java_lang_String *s;                /* result-string                      */
333         java_chararray *a;
334
335         if (!text) {
336                 *exceptionptr = new_nullpointerexception();
337                 return NULL;
338         }
339
340         len = strlen(text);
341
342         s = (java_lang_String *) builtin_new(class_java_lang_String);
343         a = builtin_newarray_char(len);
344
345         /* javastring or character-array could not be created */
346         if (!a || !s)
347                 return NULL;
348
349         /* copy text */
350         for (i = 0; i < len; i++)
351                 a->data[i] = text[i];
352         
353         /* set fields of the javastring-object */
354         s->value  = a;
355         s->offset = 0;
356         s->count  = len;
357
358         return s;
359 }
360
361
362 /* javastring_tochar ***********************************************************
363
364    converts a Java string into a C string.
365         
366    return: pointer to C string
367         
368    Caution: calling method MUST release the allocated memory!
369         
370 *******************************************************************************/
371
372 char *javastring_tochar(java_objectheader *so) 
373 {
374         java_lang_String *s = (java_lang_String *) so;
375         java_chararray *a;
376         char *buf;
377         s4 i;
378         
379         if (!s)
380                 return "";
381
382         a = s->value;
383
384         if (!a)
385                 return "";
386
387         buf = MNEW(char, s->count + 1);
388
389         for (i = 0; i < s->count; i++)
390                 buf[i] = a->data[s->offset + i];
391
392         buf[i] = '\0';
393
394         return buf;
395 }
396
397
398 /* javastring_toutf ************************************************************
399
400    Make utf symbol from javastring.
401
402 *******************************************************************************/
403
404 utf *javastring_toutf(java_lang_String *string, bool isclassname)
405 {
406         java_lang_String *str = (java_lang_String *) string;
407
408         return utf_new_u2(str->value->data + str->offset, str->count, isclassname);
409 }
410
411
412 /* javastring_strlen ***********************************************************
413
414    Returns the length of the Java string.
415         
416 *******************************************************************************/
417
418 s4 javastring_strlen(java_objectheader *so)
419 {
420         java_lang_String *s = (java_lang_String *) so;
421         
422         if (!s)
423                 return 0;
424
425         return s->count;
426 }
427
428
429 /* literalstring_u2 ************************************************************
430
431    Searches for the javastring with the specified u2-array in the
432    string hashtable, if there is no such string a new one is created.
433
434    If copymode is true a copy of the u2-array is made.
435
436 *******************************************************************************/
437
438 java_objectheader *literalstring_u2(java_chararray *a, u4 length, u4 offset,
439                                                                         bool copymode)
440 {
441     literalstring    *s;                /* hashtable element                  */
442     java_lang_String *js;               /* u2-array wrapped in javastring     */
443     java_chararray   *stringdata;       /* copy of u2-array                   */
444     u4                key;
445     u4                slot;
446     u2                i;
447
448     /* find location in hashtable */
449     key  = unicode_hashkey(a->data + offset, length);
450     slot = key & (string_hash.size - 1);
451     s    = string_hash.ptr[slot];
452
453     while (s) {
454                 js = (java_lang_String *) s->string;
455
456                 if (length == js->count) {
457                         /* compare text */
458                         for (i = 0; i < length; i++) {
459                                 if (a->data[offset + i] != js->value->data[i])
460                                         goto nomatch;
461                         }
462
463                         /* string already in hashtable, free memory */
464                         if (!copymode)
465                                 mem_free(a, sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10);
466
467                         return (java_objectheader *) js;
468                 }
469
470         nomatch:
471                 /* follow link in external hash chain */
472                 s = s->hashlink;
473     }
474
475     if (copymode) {
476                 /* create copy of u2-array for new javastring */
477                 u4 arraysize = sizeof(java_chararray) + sizeof(u2) * (length - 1) + 10;
478                 stringdata = mem_alloc(arraysize);
479 /*              memcpy(stringdata, a, arraysize); */
480                 memcpy(&(stringdata->header), &(a->header), sizeof(java_arrayheader));
481                 memcpy(&(stringdata->data), &(a->data) + offset, sizeof(u2) * (length - 1) + 10);
482
483     } else {
484                 stringdata = a;
485         }
486
487     /* location in hashtable found, complete arrayheader */
488
489     stringdata->header.objheader.vftbl =
490                 primitivetype_table[ARRAYTYPE_CHAR].arrayvftbl;
491     stringdata->header.size = length;
492
493         /* XXX TWISTI: is this necessary? */
494         if (!class_java_lang_String)
495                 class_java_lang_String = load_class_bootstrap(utf_java_lang_String);
496
497         assert(class_java_lang_String);
498         assert(class_java_lang_String->loaded);
499
500         /* if we use eager loading, we have to check loaded String class */
501
502         if (opt_eager)
503                 list_addfirst(&unlinkedclasses, class_java_lang_String);
504
505         /* create new javastring */
506
507         js = NEW(java_lang_String);
508
509 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
510         initObjectLock(&js->header);
511 #endif
512
513         js->header.vftbl = class_java_lang_String->vftbl;
514         js->value  = stringdata;
515         js->offset = 0;
516         js->count  = length;
517
518         /* create new literalstring */
519
520         s = NEW(literalstring);
521         s->hashlink = string_hash.ptr[slot];
522         s->string   = (java_objectheader *) js;
523         string_hash.ptr[slot] = s;
524
525         /* update number of hashtable entries */
526
527         string_hash.entries++;
528
529         /* reorganization of hashtable */       
530
531         if (string_hash.entries > (string_hash.size * 2)) {
532                 /* reorganization of hashtable, average length of the external
533                    chains is approx. 2 */
534
535                 u4                i;
536                 literalstring    *s;
537                 literalstring    *nexts;
538                 java_lang_String *tmpjs;
539                 hashtable         newhash; /* the new hashtable */
540       
541                 /* create new hashtable, double the size */
542
543                 init_hashtable(&newhash, string_hash.size * 2);
544                 newhash.entries = string_hash.entries;
545       
546                 /* transfer elements to new hashtable */
547
548                 for (i = 0; i < string_hash.size; i++) {
549                         s = string_hash.ptr[i];
550
551                         while (s) {
552                                 nexts = s->hashlink;
553                                 tmpjs = (java_lang_String *) s->string;
554                                 slot  = unicode_hashkey(tmpjs->value->data, tmpjs->count) & (newhash.size - 1);
555           
556                                 s->hashlink = newhash.ptr[slot];
557                                 newhash.ptr[slot] = s;
558         
559                                 /* follow link in external hash chain */
560                                 s = nexts;
561                         }
562                 }
563         
564                 /* dispose old table */
565
566                 MFREE(string_hash.ptr, void*, string_hash.size);
567                 string_hash = newhash;
568         }
569
570         return (java_objectheader *) js;
571 }
572
573
574 /* literalstring_new ***********************************************************
575
576    Creates a new javastring with the text of the utf-symbol and inserts it into
577    the string hashtable.
578
579 *******************************************************************************/
580
581 java_objectheader *literalstring_new(utf *u)
582 {
583     char           *utf_ptr;         /* pointer to current unicode character  */
584                                          /* utf string                            */
585     u4              utflength;       /* length of utf-string if uncompressed  */
586     java_chararray *a;               /* u2-array constructed from utf string  */
587     u4              i;
588
589         utf_ptr = u->text;
590         utflength = utf_strlen(u);
591
592     /* allocate memory */ 
593     a = mem_alloc(sizeof(java_chararray) + sizeof(u2) * (utflength - 1) + 10);
594
595     /* convert utf-string to u2-array */
596     for (i = 0; i < utflength; i++)
597                 a->data[i] = utf_nextu2(&utf_ptr);
598
599     return literalstring_u2(a, utflength, 0, false);
600 }
601
602
603 /* literalstring_free **********************************************************
604
605    Removes a javastring from memory.
606
607 *******************************************************************************/
608
609 void literalstring_free(java_objectheader* sobj)
610 {
611         java_lang_String *s;
612         java_chararray *a;
613
614         s = (java_lang_String *) sobj;
615         a = s->value;
616
617         /* dispose memory of java.lang.String object */
618         FREE(s, java_lang_String);
619
620         /* dispose memory of java-characterarray */
621         FREE(a, sizeof(java_chararray) + sizeof(u2) * (a->header.size - 1)); /* +10 ?? */
622 }
623
624
625 /*
626  * These are local overrides for various environment variables in Emacs.
627  * Please do not remove this and leave it at the end of the file, where
628  * Emacs will automagically detect them.
629  * ---------------------------------------------------------------------
630  * Local variables:
631  * mode: c
632  * indent-tabs-mode: t
633  * c-basic-offset: 4
634  * tab-width: 4
635  * End:
636  */