GNU header update.
[cacao.git] / src / vm / tables.c
index ffb21c2041ed21bcf7153dd6a973759800628eed..63a3894ed126625149863dc08588e8545aec430a 100644 (file)
@@ -1,9 +1,9 @@
-/* tables.c - 
+/* vm/tables.c - 
 
-   Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
-   R. Grafl, A. Krall, C. Kruegel, C. Oates, R. Obermaisser,
-   M. Probst, S. Ring, E. Steiner, C. Thalinger, D. Thuernbeck,
-   P. Tomsich, J. Wenninger
+   Copyright (C) 1996-2005 R. Grafl, A. Krall, C. Kruegel, C. Oates,
+   R. Obermaisser, M. Platter, M. Probst, S. Ring, E. Steiner,
+   C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich, J. Wenninger,
+   Institut f. Computersprachen - TU Wien
 
    This file is part of CACAO.
 
        - the heap
        - additional support functions
 
-   $Id: tables.c 1019 2004-04-10 13:33:21Z twisti $
+   $Id: tables.c 1735 2004-12-07 14:33:27Z twisti $
 
 */
 
-#include "global.h"
-
 #include <string.h>
 #include <stdlib.h>
 #include <assert.h>
 #include <sys/types.h>
 #include <sys/mman.h>
 #include <unistd.h>
-#include "types.h"
-#include "main.h"
-#include "tables.h"
-#include "loader.h"
-#include "asmpart.h"
-#include "threads/thread.h"
-#include "threads/locks.h"
-#include "toolbox/loging.h"
-#include "toolbox/memory.h"
 
+#include "types.h"
+#include "mm/memory.h"
+#include "native/native.h"
+#include "toolbox/logging.h"
+#include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/loader.h"
+#include "vm/options.h"
+#include "vm/statistics.h"
+#include "vm/tables.h"
 
-/* statistics */
-int count_utf_len = 0;         /* size of utf hash                  */
-int count_utf_new = 0;         /* calls of utf_new                  */
-int count_utf_new_found  = 0;  /* calls of utf_new with fast return */
 
 hashtable utf_hash;     /* hashtable for utf8-symbols */
 hashtable string_hash;  /* hashtable for javastrings  */
 hashtable class_hash;   /* hashtable for classes      */
 
+list unlinkedclasses;   /* this is only used for eager class loading          */
+
+
 /******************************************************************************
  *********************** hashtable functions **********************************
  ******************************************************************************/
@@ -109,11 +108,14 @@ void tables_init()
        init_hashtable(&utf_hash,    UTF_HASHSTART);  /* hashtable for utf8-symbols */
        init_hashtable(&string_hash, HASHSTART);      /* hashtable for javastrings */
        init_hashtable(&class_hash,  HASHSTART);      /* hashtable for classes */ 
-       
-#ifdef STATISTICS
-       count_utf_len += sizeof(utf*) * utf_hash.size;
-#endif
 
+/*     if (opt_eager) */
+/*             list_init(&unlinkedclasses, OFFSET(classinfo, listnode)); */
+
+#if defined(STATISTICS)
+       if (opt_stat)
+               count_utf_len += sizeof(utf*) * utf_hash.size;
+#endif
 }
 
 
@@ -123,7 +125,7 @@ void tables_init()
        
 *****************************************************************************/
 
-void tables_close(stringdeleter del)
+void tables_close()
 {
        utf *u = NULL;
        literalstring *s;
@@ -147,7 +149,7 @@ void tables_close(stringdeleter del)
                while (u) {
                        /* process elements in external hash chain */
                        literalstring *nexts = s->hashlink;
-                       del(s->string);
+                       literalstring_free(s->string);
                        FREE(s, literalstring);
                        s = nexts;
                }       
@@ -164,15 +166,21 @@ void tables_close(stringdeleter del)
 
        write utf symbol to stdout (debugging purposes)
 
-******************************************************************************/
+*******************************************************************************/
 
 void utf_display(utf *u)
 {
-    char *endpos  = utf_end(u);  /* points behind utf string       */
-    char *utf_ptr = u->text;     /* current position in utf text   */
+    char *endpos;                       /* points behind utf string           */
+    char *utf_ptr;                      /* current position in utf text       */
 
-       if (!u)
+       if (!u) {
+               printf("NULL");
+               fflush(stdout);
                return;
+       }
+
+    endpos = utf_end(u);
+    utf_ptr = u->text;
 
     while (utf_ptr < endpos) {
                /* read next unicode character */                
@@ -185,19 +193,25 @@ void utf_display(utf *u)
 }
 
 
-/********************* function: utf_display *********************************
+/* utf_display_classname *******************************************************
 
-       write utf symbol to stdout (debugging purposes)
+   write utf symbol to stdout (debugging purposes)
 
-******************************************************************************/
+*******************************************************************************/
 
 void utf_display_classname(utf *u)
 {
-    char *endpos  = utf_end(u);  /* points behind utf string       */
-    char *utf_ptr = u->text;     /* current position in utf text   */
+    char *endpos;                       /* points behind utf string           */
+    char *utf_ptr;                      /* current position in utf text       */
 
-       if (!u)
+       if (!u) {
+               printf("NULL");
+               fflush(stdout);
                return;
+       }
+
+    endpos = utf_end(u);
+    utf_ptr = u->text;
 
     while (utf_ptr < endpos) {
                /* read next unicode character */                
@@ -239,17 +253,25 @@ void log_plain_utf(utf *u)
 }
 
 
-/************************ function: utf_sprint *******************************
+/* utf_sprint ******************************************************************
        
-    write utf symbol into c-string (debugging purposes)                                                 
+   write utf symbol into c-string (debugging purposes)
 
-******************************************************************************
+*******************************************************************************/
 
 void utf_sprint(char *buffer, utf *u)
 {
-    char *endpos  = utf_end(u);  /* points behind utf string       */
-    char *utf_ptr = u->text;     /* current position in utf text   */ 
-    u2 pos = 0;                  /* position in c-string           */
+    char *endpos;                       /* points behind utf string           */
+    char *utf_ptr;                      /* current position in utf text       */
+    u2 pos = 0;                         /* position in c-string               */
+
+       if (!u) {
+               memcpy(buffer, "NULL", 5);      /* 4 chars + terminating \0           */
+               return;
+       }
+
+    endpos = utf_end(u);
+    utf_ptr = u->text;
 
     while (utf_ptr < endpos) 
                /* copy next unicode character */       
@@ -260,17 +282,25 @@ void utf_sprint(char *buffer, utf *u)
 }
 
 
-/************************ function: utf_sprint_classname *********************
+/* utf_sprint_classname ********************************************************
        
-    write utf symbol into c-string (debugging purposes)
+   write utf symbol into c-string (debugging purposes)
 
-******************************************************************************
+*******************************************************************************/
 
 void utf_sprint_classname(char *buffer, utf *u)
 {
-    char *endpos  = utf_end(u);  /* points behind utf string       */
-    char *utf_ptr = u->text;     /* current position in utf text   */ 
-    u2 pos = 0;                  /* position in c-string           */
+    char *endpos;                       /* points behind utf string           */
+    char *utf_ptr;                      /* current position in utf text       */
+    u2 pos = 0;                         /* position in c-string               */
+
+       if (!u) {
+               memcpy(buffer, "NULL", 5);      /* 4 chars + terminating \0           */
+               return;
+       }
+
+    endpos = utf_end(u);
+    utf_ptr = u->text;
 
     while (utf_ptr < endpos) {
                /* copy next unicode character */       
@@ -288,7 +318,7 @@ void utf_sprint_classname(char *buffer, utf *u)
        
     write utf symbol into file         
 
-******************************************************************************/ 
+******************************************************************************/
 
 void utf_fprint(FILE *file, utf *u)
 {
@@ -308,6 +338,31 @@ void utf_fprint(FILE *file, utf *u)
 }
 
 
+/********************* Funktion: utf_fprint **********************************
+       
+    write utf symbol into file         
+
+******************************************************************************/
+
+void utf_fprint_classname(FILE *file, utf *u)
+{
+    char *endpos  = utf_end(u);  /* points behind utf string       */
+    char *utf_ptr = u->text;     /* current position in utf text   */ 
+
+    if (!u)
+               return;
+
+    while (utf_ptr < endpos) { 
+               /* read next unicode character */                
+               u2 c = utf_nextu2(&utf_ptr);                            
+               if (c == '/') c = '.';
+
+               if (c >= 32 && c <= 127) fprintf(file, "%c", c);
+               else fprintf(file, "?");
+       }
+}
+
+
 /****************** internal function: utf_hashkey ***************************
 
        The hashkey is computed from the utf-text by using up to 8 characters.
@@ -457,16 +512,16 @@ u4 unicode_hashkey(u2 *text, u2 len)
 
 ******************************************************************************/
 
-utf *utf_new_int(char *text, u2 length)
+utf *utf_new_intern(char *text, u2 length)
 {
        u4 key;            /* hashkey computed from utf-text */
        u4 slot;           /* slot in hashtable */
        utf *u;            /* hashtable element */
        u2 i;
 
-/*     log_text("utf_new entered");*/
 #ifdef STATISTICS
-       count_utf_new++;
+       if (opt_stat)
+               count_utf_new++;
 #endif
 
        key  = utf_hashkey(text, length);
@@ -482,7 +537,8 @@ utf *utf_new_int(char *text, u2 length)
                                if (text[i] != u->text[i]) goto nomatch;
                        
 #ifdef STATISTICS
-                       count_utf_new_found++;
+                       if (opt_stat)
+                               count_utf_new_found++;
 #endif
 /*                     log_text("symbol found in hash table");*/
                        /* symbol found in hashtable */
@@ -500,19 +556,20 @@ utf *utf_new_int(char *text, u2 length)
        }
 
 #ifdef STATISTICS
-       count_utf_len += sizeof(utf) + length;
+       if (opt_stat)
+               count_utf_len += sizeof(utf) + length;
 #endif
 
        /* location in hashtable found, create new utf element */
-       u = NEW (utf);
-       u->blength  = length;             /* length in bytes of utfstring */
-       u->hashlink = utf_hash.ptr[slot]; /* link in external hashchain   */            
-       u->text     = mem_alloc(length/*JOWENN*/+1);  /* allocate memory for utf-text */
-       memcpy(u->text,text,length);      /* copy utf-text                */
-       u->text[length] = '\0';/*JOWENN*/
-       utf_hash.ptr[slot] = u;           /* insert symbol into table     */ 
+       u = NEW(utf);
+       u->blength  = length;               /* length in bytes of utfstring       */
+       u->hashlink = utf_hash.ptr[slot];   /* link in external hashchain         */
+       u->text     = mem_alloc(length + 1);/* allocate memory for utf-text       */
+       memcpy(u->text, text, length);      /* copy utf-text                      */
+       u->text[length] = '\0';
+       utf_hash.ptr[slot] = u;             /* insert symbol into table           */
 
-       utf_hash.entries++;               /* update number of entries     */
+       utf_hash.entries++;                 /* update number of entries           */
 
        if (utf_hash.entries > (utf_hash.size * 2)) {
 
@@ -528,7 +585,8 @@ utf *utf_new_int(char *text, u2 length)
                newhash.entries = utf_hash.entries;
 
 #ifdef STATISTICS
-               count_utf_len += sizeof(utf*) * utf_hash.size;
+               if (opt_stat)
+                       count_utf_len += sizeof(utf*) * utf_hash.size;
 #endif
 
                /* transfer elements to new hashtable */
@@ -550,20 +608,25 @@ utf *utf_new_int(char *text, u2 length)
                MFREE(utf_hash.ptr, void*, utf_hash.size);
                utf_hash = newhash;
        }
-               /*utf_display(u);*/
+
        return u;
 }
 
+
 utf *utf_new(char *text, u2 length)
 {
     utf *r;
+
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
     tables_lock();
 #endif
-    r = utf_new_int(text, length);
+
+    r = utf_new_intern(text, length);
+
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
     tables_unlock();
 #endif
+
     return r;
 }
 
@@ -781,7 +844,7 @@ u2 utf_nextu2(char **utf_ptr)
     switch ((ch1 = utf[0]) >> 4) {
        default: /* 1 byte */
                (*utf_ptr)++;
-               return ch1;
+               return (u2) ch1;
        case 0xC: 
        case 0xD: /* 2 bytes */
                if (((ch2 = utf[1]) & 0xC0) == 0x80) {
@@ -925,22 +988,22 @@ is_valid_name_utf(utf *u)
 
 *******************************************************************************/
 
-classinfo *class_new_int(utf *u)
+classinfo *class_new_intern(utf *classname)
 {
        classinfo *c;     /* hashtable element */
        u4 key;           /* hashkey computed from classname */
        u4 slot;          /* slot in hashtable */
        u2 i;
 
-       key  = utf_hashkey(u->text, u->blength);
+       key  = utf_hashkey(classname->text, classname->blength);
        slot = key & (class_hash.size - 1);
        c    = class_hash.ptr[slot];
 
        /* search external hash chain for the class */
        while (c) {
-               if (c->name->blength == u->blength) {
-                       for (i = 0; i < u->blength; i++)
-                               if (u->text[i] != c->name->text[i]) goto nomatch;
+               if (c->name->blength == classname->blength) {
+                       for (i = 0; i < classname->blength; i++)
+                               if (classname->text[i] != c->name->text[i]) goto nomatch;
                                                
                        /* class found in hashtable */
                        return c;
@@ -952,14 +1015,23 @@ classinfo *class_new_int(utf *u)
 
        /* location in hashtable found, create new classinfo structure */
 
-#ifdef STATISTICS
-       count_class_infos += sizeof(classinfo);
+#if defined(STATISTICS)
+       if (opt_stat)
+               count_class_infos += sizeof(classinfo);
 #endif
 
+       if (initverbose) {
+               char logtext[MAXLOGTEXT];
+               sprintf(logtext, "Creating class: ");
+               utf_sprint_classname(logtext + strlen(logtext), classname);
+               log_text(logtext);
+       }
+
        c = GCNEW(classinfo, 1); /*JOWENN: NEW*/
+       /*c=NEW(classinfo);*/
        c->vmClass = 0;
        c->flags = 0;
-       c->name = u;
+       c->name = classname;
        c->packagename = NULL;
        c->cpcount = 0;
        c->cptags = NULL;
@@ -982,15 +1054,13 @@ classinfo *class_new_int(utf *u)
        c->innerclass = NULL;
        c->vftbl = NULL;
        c->initialized = false;
+       c->initializing = false;
        c->classvftbl = false;
     c->classUsed = 0;
     c->impldBy = NULL;
        c->classloader = NULL;
        c->sourcefile = NULL;
        
-       /* prepare loading of the class */
-       list_addlast(&unloadedclasses, c);
-
        /* insert class into the hashtable */
        c->hashlink = class_hash.ptr[slot];
        class_hash.ptr[slot] = c;
@@ -1013,7 +1083,7 @@ classinfo *class_new_int(utf *u)
 
                /* transfer elements to new hashtable */
                for (i = 0; i < class_hash.size; i++) {
-                       c = (classinfo*) class_hash.ptr[i];
+                       c = (classinfo *) class_hash.ptr[i];
                        while (c) {
                                classinfo *nextc = c->hashlink;
                                u4 slot = (utf_hashkey(c->name->text, c->name->blength)) & (newhash.size - 1);
@@ -1029,38 +1099,98 @@ classinfo *class_new_int(utf *u)
                MFREE(class_hash.ptr, void*, class_hash.size);
                class_hash = newhash;
        }
-                       
+
     /* Array classes need further initialization. */
-    if (u->text[0] == '[') {
+    if (c->name->text[0] == '[') {
+               /* Array classes are not loaded from classfiles. */
+               c->loaded = true;
         class_new_array(c);
                c->packagename = array_packagename;
-       }
-       else {
+
+       else {
                /* Find the package name */
                /* Classes in the unnamed package keep packagename == NULL. */
                char *p = utf_end(c->name) - 1;
                char *start = c->name->text;
-               for (;p > start; --p)
+               for (;p > start; --p) {
                        if (*p == '.') {
-                               c->packagename = utf_new(start,p-start);
+                               c->packagename = utf_new(start, p - start);
                                break;
                        }
+               }
        }
-        
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+       initObjectLock(&c->header);
+#endif
+
        return c;
 }
 
-classinfo *class_new(utf *u)
+
+classinfo *class_new(utf *classname)
 {
-    classinfo *r;
+    classinfo *c;
+
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
     tables_lock();
 #endif
-    r = class_new_int(u);
+
+    c = class_new_intern(classname);
+
+       /* we support eager class loading and linking on demand */
+
+       if (opt_eager) {
+               classinfo *tc;
+               classinfo *tmp;
+
+               list_init(&unlinkedclasses, OFFSET(classinfo, listnode));
+
+               if (!c->loaded) {
+                       if (!class_load(c)) {
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+                               tables_unlock();
+#endif
+                               return c;
+                       }
+               }
+
+               /* link all referenced classes */
+
+               tc = list_first(&unlinkedclasses);
+
+               while (tc) {
+                       /* skip the current loaded/linked class */
+                       if (tc != c) {
+                               if (!class_link(tc)) {
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+                                       tables_unlock();
+#endif
+                                       return c;
+                               }
+                       }
+
+                       /* we need a tmp variable here, because list_remove sets prev and
+                          next to NULL */
+                       tmp = list_next(&unlinkedclasses, tc);
+                       list_remove(&unlinkedclasses, tc);
+                       tc = tmp;
+               }
+
+               if (!c->linked) {
+                       if (!class_link(c)) {
+#if defined(USE_THREADS) && defined(NATIVE_THREADS)
+                               tables_unlock();
+#endif
+                               return c;
+                       }
+               }
+       }
+
 #if defined(USE_THREADS) && defined(NATIVE_THREADS)
     tables_unlock();
 #endif
-    return r;
+
+    return c;
 }
 
 
@@ -1071,32 +1201,25 @@ classinfo *class_new(utf *u)
 
 *******************************************************************************/
 
-classinfo *class_get(utf *u)
+classinfo *class_get(utf *classname)
 {
        classinfo *c;  /* hashtable element */ 
        u4 key;        /* hashkey computed from classname */   
        u4 slot;       /* slot in hashtable */
        u2 i;  
 
-       key  = utf_hashkey (u->text, u->blength);
+       key  = utf_hashkey(classname->text, classname->blength);
        slot = key & (class_hash.size-1);
        c    = class_hash.ptr[slot];
 
-/*
-       log_text("class_get: looking for class:");
-       utf_display(u); */
        /* search external hash-chain */
        while (c) {
-               if (c->name->blength == u->blength) {
-                       
+               if (c->name->blength == classname->blength) {
                        /* compare classnames */
-                       for (i=0; i<u->blength; i++) 
-                               if (u->text[i] != c->name->text[i]) goto nomatch;
-/*
-                       log_text("class_get: class found");
-                       utf_display(u);
-                       log_text("");
-                       utf_display(c->name); */
+                       for (i = 0; i < classname->blength; i++) 
+                               if (classname->text[i] != c->name->text[i])
+                                       goto nomatch;
+
                        /* class found in hashtable */                          
                        return c;
                }
@@ -1109,6 +1232,60 @@ classinfo *class_get(utf *u)
        return NULL;
 }
 
+
+/* class_remove ****************************************************************
+
+   removes the class entry wth the specified name in the classes hashtable,
+   furthermore the class' resources are freed
+   if there is no such class false is returned
+
+*******************************************************************************/
+
+bool class_remove(classinfo *c)
+{
+       classinfo *tc;  /* hashtable element */
+       classinfo *pc;
+       u4 key;         /* hashkey computed from classname */   
+       u4 slot;        /* slot in hashtable */
+       u2 i;  
+
+       key  = utf_hashkey(c->name->text, c->name->blength);
+       slot = key & (class_hash.size - 1);
+       tc   = class_hash.ptr[slot];
+       pc   = NULL;
+
+       /* search external hash-chain */
+       while (tc) {
+               if (tc->name->blength == c->name->blength) {
+                       
+                       /* compare classnames */
+                       for (i = 0; i < c->name->blength; i++)
+                               if (tc->name->text[i] != c->name->text[i])
+                                       goto nomatch;
+
+                       /* class found in hashtable */
+                       if (!pc) {
+                               class_hash.ptr[slot] = tc->hashlink;
+
+                       } else {
+                               pc->hashlink = tc->hashlink;
+                       }
+
+                       class_free(tc);
+
+                       return true;
+               }
+                       
+       nomatch:
+               pc = tc;
+               tc = tc->hashlink;
+       }
+
+       /* class not found */
+       return false;
+}
+
+
 /***************** Function: class_array_of ***********************************
 
     Returns an array class with the given component class.
@@ -1120,28 +1297,34 @@ classinfo *class_array_of(classinfo *component)
 {
     int namelen;
     char *namebuf;
+       classinfo *c;
 
     /* Assemble the array class name */
     namelen = component->name->blength;
     
     if (component->name->text[0] == '[') {
         /* the component is itself an array */
-        namebuf = DMNEW(char,namelen+1);
+        namebuf = DMNEW(char, namelen + 1);
         namebuf[0] = '[';
-        memcpy(namebuf+1,component->name->text,namelen);
+        memcpy(namebuf + 1, component->name->text, namelen);
         namelen++;
-    }
-    else {
+
+    else {
         /* the component is a non-array class */
-        namebuf = DMNEW(char,namelen+3);
+        namebuf = DMNEW(char, namelen + 3);
         namebuf[0] = '[';
         namebuf[1] = 'L';
-        memcpy(namebuf+2,component->name->text,namelen);
-        namebuf[2+namelen] = ';';
-        namelen+=3;
+        memcpy(namebuf + 2, component->name->text, namelen);
+        namebuf[2 + namelen] = ';';
+        namelen += 3;
     }
 
-    return class_new( utf_new(namebuf,namelen) );
+       /* load this class ;-) and link it */
+       c = class_new(utf_new(namebuf, namelen));
+       c->loaded = 1;
+       class_link(c);
+
+    return c;
 }
 
 /*************** Function: class_multiarray_of ********************************
@@ -1151,12 +1334,12 @@ classinfo *class_array_of(classinfo *component)
 
 *******************************************************************************/
 
-classinfo *class_multiarray_of(int dim,classinfo *element)
+classinfo *class_multiarray_of(int dim, classinfo *element)
 {
     int namelen;
     char *namebuf;
 
-       if (dim<1)
+       if (dim < 1)
                panic("Invalid array dimension requested");
 
     /* Assemble the array class name */
@@ -1164,21 +1347,21 @@ classinfo *class_multiarray_of(int dim,classinfo *element)
     
     if (element->name->text[0] == '[') {
         /* the element is itself an array */
-        namebuf = DMNEW(char,namelen+dim);
-        memcpy(namebuf+dim,element->name->text,namelen);
+        namebuf = DMNEW(char, namelen + dim);
+        memcpy(namebuf + dim, element->name->text, namelen);
         namelen += dim;
     }
     else {
         /* the element is a non-array class */
-        namebuf = DMNEW(char,namelen+2+dim);
+        namebuf = DMNEW(char, namelen + 2 + dim);
         namebuf[dim] = 'L';
-        memcpy(namebuf+dim+1,element->name->text,namelen);
-        namelen += (2+dim);
-        namebuf[namelen-1] = ';';
+        memcpy(namebuf + dim + 1, element->name->text, namelen);
+        namelen += (2 + dim);
+        namebuf[namelen - 1] = ';';
     }
-       memset(namebuf,'[',dim);
+       memset(namebuf, '[', dim);
 
-    return class_new( utf_new(namebuf,namelen) );
+    return class_new(utf_new(namebuf, namelen));
 }
 
 /************************** function: utf_strlen ******************************
@@ -1189,9 +1372,17 @@ classinfo *class_multiarray_of(int dim,classinfo *element)
 
 u4 utf_strlen(utf *u) 
 {
-    char *endpos  = utf_end(u);  /* points behind utf string       */
-    char *utf_ptr = u->text;     /* current position in utf text   */
-    u4 len = 0;                  /* number of unicode characters   */
+    char *endpos;                   /* points behind utf string       */
+    char *utf_ptr;                  /* current position in utf text   */
+    u4 len = 0;                     /* number of unicode characters   */
+
+       if (!u) {
+               *exceptionptr = new_nullpointerexception();
+               return 0;
+       }
+
+       endpos = utf_end(u);
+       utf_ptr = u->text;
 
     while (utf_ptr < endpos) {
                len++;