You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by ge...@apache.org on 2005/10/08 06:29:29 UTC

svn commit: r307257 [23/24] - in /incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm: ./ bootJVM/ bootJVM/jni/ bootJVM/jni/src/ bootJVM/jni/src/gnu/ bootJVM/jni/src/gnu/classpath/ bootJVM/jni/src/gnu/classpath/0.16/ bootJVM/jni/src/gnu/classpath...

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/threadutil.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/threadutil.c?rev=307257&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/threadutil.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/threadutil.c Fri Oct  7 21:27:56 2005
@@ -0,0 +1,599 @@
+/*!
+ * @file threadutil.c
+ *
+ * @brief Utilities for operating the JVM thread state model on this
+ * real machine implementation.
+ *
+ * @todo Timers for Thread.sleep() and Thread.wait() and Object.wait()
+ * that use millisecond timers @e are supported.  The variation
+ * that supports higher resolution of milliseconds and nanoseconds
+ * are @e not supported, but the millisecond version is used instead.
+ *
+ * @internal This file also serves the dual purpose as a catch-all for
+ * development experiments.  Due to the fact that the implementation
+ * of the Java thread and the supporting rthread structure is deeply
+ * embedded in the core of the development of this software, this
+ * file has contents that come and go during development.  Some
+ * functions get staged here before deciding where they @e really
+ * go; some are interim functions for debugging, some were glue
+ * that eventually went away.  Be careful to remove prototypes
+ * to such functions from the appropriate header file.
+ *
+ *
+ * @section Control
+ *
+ * \$URL: https://svn.apache.org/path/name/threadutil.c $ \$Id: threadutil.c 0 09/28/2005 dlydick $
+ *
+ * Copyright 2005 The Apache Software Foundation
+ * or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 ("the License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied.
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * @version \$LastChangedRevision: 0 $
+ *
+ * @date \$LastChangedDate: 09/28/2005 $
+ *
+ * @author \$LastChangedBy: dlydick $
+ *         Original code contributed by Daniel Lydick on 09/28/2005.
+ *
+ * @section Reference
+ *
+ */
+
+#include "arch.h"
+ARCH_COPYRIGHT_APACHE(threadutil, c, "$URL: https://svn.apache.org/path/name/threadutil.c $ $Id: threadutil.c 0 09/28/2005 dlydick $");
+
+
+#include "jvmcfg.h"
+#include "cfmacros.h"
+#include "classfile.h"
+#include "jvm.h"
+#include "jvmclass.h"
+#include "util.h"
+
+
+/*!
+ * @brief Update the interval timer for this thread from
+ * @c @b java.lang.Thread.sleep() or from a timed
+ * @c @b java.lang.Thread.wait() or @c @b java.lang.Thread.join().
+ *
+ * This function is designed to be invoked from the timeslice interrupt
+ * handler and @e only from thence.  It DOES NOT handle
+ * (millisec, nanosec) resolution, only millisecond resolution.
+ *
+ *
+ * @b Parameters: @link #rvoid rvoid@endlink
+ *
+ *
+ *       @returns @link #rvoid rvoid@endlink
+ *
+ */
+
+rvoid threadutil_update_sleeptime_interval(rvoid)
+{
+    jvm_thread_index thridx;
+
+    /* Lock out the @e world during timer update */
+    pthread_mutex_lock(&pjvm->sleeplock);
+
+    for (thridx = jvm_thread_index_null;
+         thridx < JVMCFG_MAX_THREADS;
+         thridx++)
+    {
+        if ((THREAD_STATUS_INUSE    & THREAD(thridx).status)    &&
+            ((THREAD_STATUS_SLEEP     |
+              THREAD_STATUS_JOINTIMED |
+              THREAD_STATUS_WAITTIMED  ) & THREAD(thridx).status))
+        {
+            /*
+             * Perform next interval update.  Stop decrementing
+             * when time reaches zero.
+             */
+            if (0 != THREAD(thridx).sleeptime)
+            {
+                THREAD(thridx).sleeptime--;
+            }
+        }
+    }
+
+    /* Unlock the @e world after timer update */
+    pthread_mutex_unlock(&pjvm->sleeplock);
+
+    return;
+
+} /* END of threadutil_update_sleeptime_interval() */
+
+
+/*!
+ * @brief Complete the UNtimed Thread.join() request and allow threads
+ * that have joined this one to resume execution.
+ *
+ * This function is typically called when a thread enters the
+ * @b COMPLETE state after finishing its JVM execution.
+ *
+ * Review state of thread table, looking for the following conditions.
+ * For those that meet them, move thread out of given state and
+ * forward to next state.  Three functions are used, depending on
+ * the current state, threadutil_update_blockingevent() and
+ * threadutil_update_wait() and threadutil_update_lock():
+ *
+ * @verbatim
+
+   Condition:         Current state: Next state:  threadutil_update_YYY:
+   ----------         -------------- -----------  ----------------------
+  
+   Thread.join()      COMPLETE       N/C              _blockingevents()
+   (forever, where
+   current thread
+   is COMPLETE, and
+   target thread is
+   BLOCKED, and is
+   moved to UNBLOCKED)
+  
+   Thread.join(n)     COMPLETE       N/C              _blockingevents()
+   (timed, where
+   n has expired
+   on current
+   thread or it is
+   COMPLETE, and
+   target thread
+   is BLOCKED, and
+   is moved to
+   UNBLOCKED)
+  
+   Thread.sleep(n)    BLOCKED        UNBLOCKED        _blockingevents()
+   (n has expired on
+   current thread)
+  
+   Interruptible I/O  BLOCKED        UNBLOCKED        _blockingevents()
+   from class
+   java.nio.channels
+   .InterruptibleChannel
+  
+   Object.wait()      WAIT           NOTIFY           _wait()
+   (forever on
+   current thread,
+   where target object
+   lock was released)
+  
+   Object.wait(n)     WAIT           NOTIFY           _wait()
+   (timed, where
+   @c @b n
+   has expired on
+   current thread
+   or target object
+   lock was released)
+  
+   One of:            LOCK           ACQUIRE          _lock()
+   Object.notify()
+   Object.notifyAll()
+   Thread.interrupt()
+   synchronized(Object)
+   ... put thread
+   into LOCK state.
+   Now it will
+   negotiate to
+   ACQUIRE its
+   object's
+   monitor lock.
+   
+  
+   Thread.suspend()   ANY            BLOCKED        threadutil_suspend()
+  
+   Thread.resume()    BLOCKED        UNBLOCKED       threadutil_resume()
+   moves a
+   Thread.suspend()
+   thread forward
+   to UNBLOCKED
+  
+   @endverbatim
+ *
+ * With the exception of threadutil_suspend() and threadutil_resume(),
+ * these functions is designed to be invoked from the JVM outer loop.
+ * CAVEAT EMPTOR:  Those two functions are deprecated.  Use
+ * at your own risk!
+ *
+ * @todo Interruptible from class
+ * @c @b java.nio.channels.InterruptibleChannel
+ *
+ *
+ * @param  thridxcurr   Thread for which to examine state changes
+ *
+ *
+ * @returns @link #rvoid rvoid@endlink
+ *
+ */
+
+rvoid threadutil_update_blockingevents(jvm_thread_index thridxcurr)
+{
+    /* Only examine INUSE threads in selected states */
+    if (!(THREAD_STATUS_INUSE & THREAD(thridxcurr).status))
+    {
+        return;
+    }
+
+    switch (THREAD(thridxcurr).this_state)
+    {
+        case THREAD_STATE_COMPLETE:  /* Untimed/untimed Thread.join() */
+
+        case THREAD_STATE_BLOCKED:   /* Thread.sleep() and */
+                                     /*! @todo interruptible I/O req's*/
+
+        default:                     /* Not meaningful for this logic */
+            return;
+    }
+
+    /* sleep() -- time period expired for only this thread */
+    if ((THREAD_STATE_BLOCKED == THREAD(thridxcurr).this_state) &&
+       (THREAD_STATUS_SLEEP   &  THREAD(thridxcurr).status)     &&
+       (0 == timeslice_get_thread_sleeptime(thridxcurr)))
+    {
+        /* Mark thread to continue now after sleep() */
+        THREAD(thridxcurr).status &= ~THREAD_STATUS_SLEEP;
+        threadstate_request_unblocked(thridxcurr);
+
+        /*
+         * Check if Thread.interrupt() was thrown
+         * against this thread.
+         *
+         * Also need to throw the exception in JVM outer loop.
+         */
+        if (THREAD_STATUS_INTERRUPTED & THREAD(thridxcurr).status)
+        {
+            THREAD(thridxcurr).status &= ~THREAD_STATUS_INTERRUPTED;
+
+            THREAD(thridxcurr).status |= THREAD_STATUS_THREW_EXCEPTION;
+
+            THREAD(thridxcurr).pThrowableEvent =
+                                JVMCLASS_JAVA_LANG_INTERRUPTEDEXCEPTION;
+        }
+    }
+    else
+
+    /*! @todo  First pass guess at interruptible I/O */
+    if ((THREAD_STATE_BLOCKED == THREAD(thridxcurr).this_state) &&
+        (THREAD_STATUS_INTERRUPTIBLEIO & THREAD(thridxcurr).status))
+    {
+        /*!
+         * Check if Thread.interrupt() was thrown
+         * against the interruptible I/O operation on this thread.
+         *
+         * @todo Is this the correct way to handle
+         *       interruptible I/O events?
+         *       Also need to throw the exception in JVM outer loop.
+         */
+        if (THREAD_STATUS_INTERRUPTED & THREAD(thridxcurr).status)
+        {
+            /* Mark thread to continue now after Thread.interrupt() */
+            THREAD(thridxcurr).status &= ~THREAD_STATUS_INTERRUPTIBLEIO;
+            threadstate_request_unblocked(thridxcurr);
+
+            THREAD(thridxcurr).status &= ~THREAD_STATUS_INTERRUPTED;
+
+            THREAD(thridxcurr).status |= THREAD_STATUS_THREW_EXCEPTION;
+
+            THREAD(thridxcurr).pThrowableEvent =
+                JVMCLASS_JAVA_NIO_CHANNELS_CLOSEDBYINTERRUPTEXCEPTION;
+        }
+    }
+    else
+
+    /*
+     * Examine Thread.join() conditions, both timed and untimed
+     */
+    if (THREAD_STATE_COMPLETE == THREAD(thridxcurr).this_state)
+    {
+        jvm_thread_index thridxjoin;
+
+                  /* Skip JVMCFG_NULL_THREAD */
+        for (thridxjoin = JVMCFG_SYSTEM_THREAD;
+             thridxjoin < JVMCFG_MAX_THREADS;
+             thridxjoin++)
+        {
+            /*
+             * Skip myself
+             */
+            if (thridxcurr == thridxjoin)
+            {
+                continue;
+            }
+
+            /* Only process threads in the BLOCKED state */
+            if (THREAD_STATE_BLOCKED != THREAD(thridxjoin).this_state)
+            {
+                continue; 
+            }
+
+            /*
+             * If current COMPLETE thread is the target of a join,
+             * check which type it is, timed or untimed.
+             */
+            if (thridxcurr == THREAD(thridxjoin).jointarget)
+            {
+                /* UNtimed join() -- where time period is zero/forever*/
+                if ((THREAD_STATUS_JOIN4EVER &
+                     THREAD(thridxjoin).status))
+                {
+                    /* Mark joined thread to be UNBLOCKED after join()*/
+                    THREAD(thridxjoin).jointarget =
+                                                  jvm_thread_index_null;
+                    THREAD(thridxjoin).status &= 
+                                               ~THREAD_STATUS_JOIN4EVER;
+                    threadstate_request_unblocked(thridxjoin);
+
+                    /*
+                     * Check if Thread.interrupted() was thrown
+                     * against this thread.
+                     */
+                    if (THREAD_STATUS_INTERRUPTED &
+                        THREAD(thridxjoin).status)
+                    {
+                        THREAD(thridxjoin).status &=
+                                             ~THREAD_STATUS_INTERRUPTED;
+
+                        THREAD(thridxjoin).status |=
+                                          THREAD_STATUS_THREW_EXCEPTION;
+
+                        THREAD(thridxjoin).pThrowableEvent =
+                            JVMCLASS_JAVA_LANG_INTERRUPTEDEXCEPTION;
+                    }
+
+                }
+                else
+
+                /* TIMED join() --time period is NON-zero,now expired */
+                if ((THREAD_STATUS_JOINTIMED &
+                                     THREAD(thridxjoin).status) &&
+                    (0 == timeslice_get_thread_sleeptime(thridxjoin)))
+                {
+                    /* Mark joined thread to be UNBLOCKED after join()*/
+                    THREAD(thridxjoin).jointarget =
+                                                  jvm_thread_index_null;
+                    THREAD(thridxjoin).status &=
+                                               ~THREAD_STATUS_JOINTIMED;
+                    threadstate_request_unblocked(thridxjoin);
+
+                    /*
+                     * Check if Thread.interrupted() was thrown
+                     * against this thread.
+                     */
+                    if (THREAD_STATUS_INTERRUPTED &
+                        THREAD(thridxjoin).status)
+                    {
+                        THREAD(thridxjoin).status &=
+                                             ~THREAD_STATUS_INTERRUPTED;
+
+                        THREAD(thridxjoin).status |=
+                            THREAD_STATUS_THREW_EXCEPTION;
+
+                        THREAD(thridxjoin).pThrowableEvent =
+                            JVMCLASS_JAVA_LANG_INTERRUPTEDEXCEPTION;
+                    }
+                }
+            }
+        }
+    }
+
+    return;
+
+} /* END of threadutil_update_blockingevents() */
+
+
+rvoid threadutil_update_wait(jvm_thread_index thridxcurr)
+{
+    /* Only examine INUSE threads in WAIT state */
+    if (!(THREAD_STATUS_INUSE & THREAD(thridxcurr).status))
+    {
+        return;
+    }
+
+    switch (THREAD(thridxcurr).this_state)
+    {
+        case THREAD_STATE_WAIT:      /* Timed/untimed Object.wait() */
+            break;
+
+        default:                     /* Not meaningful for this logic */
+            return;
+    }
+
+
+    /* wait() -- Check for notify() or notifyAll() or interrupt() */
+    if (THREAD_STATUS_WAIT4EVER & THREAD(thridxcurr).status)
+    {
+        /*
+         * Check if Thread.interrupt() was thrown against this thread
+         * or if Object.notify() against this object by this thread.
+         *
+         * (Also need to throw the exception in JVM outer loop.)
+         */
+        if (THREAD_STATUS_INTERRUPTED & THREAD(thridxcurr).status)
+        {
+            THREAD(thridxcurr).status &= ~THREAD_STATUS_INTERRUPTED;
+
+            THREAD(thridxcurr).status |= THREAD_STATUS_THREW_EXCEPTION;
+
+            THREAD(thridxcurr).pThrowableEvent =
+                                JVMCLASS_JAVA_LANG_INTERRUPTEDEXCEPTION;
+
+            /* Remove WAIT condition and move to NOTIFY state */
+            THREAD(thridxcurr).status &= ~THREAD_STATUS_WAIT4EVER;
+            threadstate_request_notify(thridxcurr);
+        }
+        else
+        if (THREAD_STATUS_NOTIFIED & THREAD(thridxcurr).status)
+        {
+            THREAD(thridxcurr).status &= ~THREAD_STATUS_NOTIFIED;
+
+            /* Remove WAIT condition and move to NOTIFY state */
+            THREAD(thridxcurr).status &= ~THREAD_STATUS_WAIT4EVER;
+            threadstate_request_notify(thridxcurr);
+        }
+    }
+    else
+
+    /* wait(n) -- TIMED, chk if monitor lock released on target object
+                  or if timer expired */
+    if ((THREAD_STATUS_WAITTIMED &  THREAD(thridxcurr).status)   &&
+        (jvm_object_hash_null    != THREAD(thridxcurr).locktarget))
+    {
+        /* Give up if timer expired */
+        if (0 == timeslice_get_thread_sleeptime(thridxcurr))
+        {
+            /* Remove @b WAIT condition and move to next state */
+            THREAD(thridxcurr).status &= ~THREAD_STATUS_WAITTIMED;
+            threadstate_request_notify(thridxcurr);
+        }
+        else
+        {
+            /*
+             * Check if Thread.interrupt() was thrown against this
+             * thread or if Object.notify() against this object by this
+             * thread.
+             *
+             * (Also need to throw the exception in JVM outer loop.)
+             */
+            if (THREAD_STATUS_INTERRUPTED & THREAD(thridxcurr).status)
+            {
+                THREAD(thridxcurr).status &= ~THREAD_STATUS_INTERRUPTED;
+
+                THREAD(thridxcurr).status |=
+                                          THREAD_STATUS_THREW_EXCEPTION;
+
+                THREAD(thridxcurr).pThrowableEvent =
+                                JVMCLASS_JAVA_LANG_INTERRUPTEDEXCEPTION;
+
+                /* Remove WAIT condition and move to NOTIFY state */
+                THREAD(thridxcurr).status &= ~THREAD_STATUS_WAITTIMED;
+                threadstate_request_notify(thridxcurr);
+            }
+            else
+            if (THREAD_STATUS_NOTIFIED & THREAD(thridxcurr).status)
+            {
+                THREAD(thridxcurr).status &= ~THREAD_STATUS_NOTIFIED;
+
+                /* Remove WAIT condition and move to NOTIFY state */
+                THREAD(thridxcurr).status &= ~THREAD_STATUS_WAITTIMED;
+                threadstate_request_notify(thridxcurr);
+            }
+        }
+    }
+
+    return;
+
+} /* END of threadutil_update_wait() */
+
+
+rvoid threadutil_update_lock(jvm_thread_index thridxcurr)
+{
+    /* Only examine INUSE threads in LOCK state */
+    if (!(THREAD_STATUS_INUSE & THREAD(thridxcurr).status))
+    {
+        return;
+    }
+
+    switch (THREAD(thridxcurr).this_state)
+    {
+        case THREAD_STATE_LOCK:      /* Lock arbitration */
+            break;
+
+        default:                     /* Not meaningful for this logic */
+            return;
+    }
+
+
+    /*
+     * One of java.lang.Object.notify() or java.lang.Object.notifyAll()
+     * or java.lang.Thread.interrupt() or a @c @b synchronize()
+     * block got the thread here, now try to wake up from @b LOCK with
+     * the target object's monitor lock acquired, if currently
+     * available.
+     *
+     * To do so, check if previous thread unlocked this object.  If so,
+     * go lock it for use by this thread.
+     */
+    if ((jvm_object_hash_null != THREAD(thridxcurr).locktarget) &&
+        (!(OBJECT_STATUS_MLOCK & OBJECT(THREAD(thridxcurr).locktarget)
+                                   .status)))
+    {
+        /* If fail, arbitrate here again next time around */
+        if (rtrue ==
+            objectutil_synchronize(THREAD(thridxcurr).locktarget,
+                                   thridxcurr))
+        {
+            /* Move to @b ACQUIRE state */
+            THREAD(thridxcurr).status &= ~THREAD_STATUS_WAIT4EVER;
+            threadstate_request_acquire(thridxcurr);
+        }
+    }
+
+    return;
+
+} /* END of threadutil_update_lock() */
+
+
+/*!
+ * @brief Examine an object to see if a thread owns its monitor lock
+ *
+ *
+ * @param thridx      Thread table index of thread to compare with.
+ *
+ * @param objhashlock Object table hash of object to examine.
+ *
+ *
+ * @returns @link #rtrue rtrue@endlink if this thread owns
+ *          this object's monitor lock.
+ *
+ */
+
+rboolean threadutil_holds_lock(jvm_thread_index thridx,
+                               jvm_object_hash  objhashlock)
+{
+    /*
+     * Make sure thread and object are both in use,
+     * make sure object is locked, then do @b BIDIRECTIONAL check
+     * to see if object and thread think each other is in sync
+     * and that @e this thread indeed @b DOES hold the lock on @e this
+     * object.
+     */
+
+    /* Prerequisite to this check */
+    if ((!(OBJECT_STATUS_INUSE & OBJECT(objhashlock).status)) ||
+        (OBJECT_STATUS_NULL    & OBJECT(objhashlock).status))
+    {
+        return(rfalse);
+    }
+
+    /* Prerequisite to this check */
+    if ((!(THREAD_STATUS_INUSE & THREAD(thridx).status)) ||
+        (THREAD_STATUS_NULL    & THREAD(thridx).status))
+    {
+        return(rfalse);
+    }
+
+    if ((OBJECT_STATUS_MLOCK & OBJECT(objhashlock).status) &&
+        (thridx             == OBJECT(objhashlock).mlock_thridx)  &&
+        ((THREAD_STATUS_WAIT4EVER |
+          THREAD_STATUS_WAITTIMED ) & THREAD(thridx).status) &&
+        (objhashlock        == THREAD(thridx).locktarget))
+    {
+        return(rtrue);
+    }
+
+    return(rfalse);
+
+} /* END of threadutil_holds_lock() */
+
+
+/* EOF */

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/timeslice.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/timeslice.c?rev=307257&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/timeslice.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/timeslice.c Fri Oct  7 21:27:56 2005
@@ -0,0 +1,315 @@
+/*!
+ * @file timeslice.c
+ *
+ * @brief JVM one millisecond time slice timer.
+ *
+ * The @link rjvm.timeslice_expired pjvm->timeslice_expired@endlink
+ * flag is set by the periodic @b SIGALRM herein and tested in the JVM
+ * virtual instruction inner loop to decide when a thread has finished
+ * using its time slice.
+ *
+ * @verbatim
+   function              flag value             meaning
+   --------              ----------             -------
+  
+   timeslice_init()      set rfalse             initial value
+  
+   timeslice_tick()      set rtrue              time slice finished
+  
+   jvm_run()             rfalse                 keep running this slice
+                         rtrue                  time slice finished
+   @endverbatim
+ *
+ *
+ * @section Control
+ *
+ * \$URL: https://svn.apache.org/path/name/timeslice.c $ \$Id: timeslice.c 0 09/28/2005 dlydick $
+ *
+ * Copyright 2005 The Apache Software Foundation
+ * or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 ("the License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied.
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * @version \$LastChangedRevision: 0 $
+ *
+ * @date \$LastChangedDate: 09/28/2005 $
+ *
+ * @author \$LastChangedBy: dlydick $
+ *         Original code contributed by Daniel Lydick on 09/28/2005.
+ *
+ * @section Reference
+ *
+ */
+
+#include "arch.h"
+ARCH_COPYRIGHT_APACHE(timeslice, c, "$URL: https://svn.apache.org/path/name/timeslice.c $ $Id: timeslice.c 0 09/28/2005 dlydick $");
+
+
+#include <unistd.h>
+#include <signal.h>
+
+#define _REENTRANT
+#include <pthread.h>
+#include <thread.h> /* WATCH OUT!  /usr/include, not application .h */
+
+#include "jvmcfg.h"
+#include "classfile.h"
+#include "jvm.h"
+#include "exit.h" 
+#include "util.h"
+
+
+/*!
+ * @brief Thread control structure for use by
+ * @c @b pthread_create(3), etc.
+ */
+static pthread_t posix_thread_id;
+
+/*!
+ * @brief Start the time slicing mechanism at JVM init time
+ *
+ *
+ * @b Parameters: @link #rvoid rvoid@endlink
+ *
+ *
+ *       @returns @link #rvoid rvoid@endlink
+ *
+ */
+rvoid timeslice_init()
+{
+    /* Time slice has not expired */
+    pjvm->timeslice_expired = rfalse;
+
+    /*
+     * Initialize the @link rthread#sleeptim rthread.sleeptime@endlink
+     * lock w/ defult attributes
+     */
+    pthread_mutex_init(&pjvm->sleeplock, (void *) rnull);
+
+    int rc = pthread_create(&posix_thread_id,
+                            (void *) rnull,
+                            timeslice_run,
+                            (void *) rnull);
+
+    if (0 != rc)
+    {
+        sysErrMsg("timeslice_init", "Cannot start timer");
+        exit_jvm(EXIT_TIMESLICE_START);
+/*NOTREACHED*/
+    }
+
+    /* Declare this module initialized */
+    jvm_timeslice_initialized = rtrue;
+
+    return;
+
+} /* END of timeslice_init() */
+
+
+/*!
+ * @brief Retrieve a thread's @link rthread#sleeptime sleeptime@endlink
+ * value @e safely during read of that variable on a given thread.
+ *
+ *
+ * @param  thridx   Thread index of thread to read its 
+ *                  @link rthread#sleeptime sleeptime@endlink
+ *                  value
+ *
+ *
+ * @returns remaining sleep time, in timer ticks
+ *
+ */
+jlong timeslice_get_thread_sleeptime(jvm_thread_index thridx)
+{
+    jlong rc;
+
+    /* Lock out the @e world while retrieving any thread's sleep time */
+    pthread_mutex_lock(&pjvm->sleeplock);
+
+    rc = THREAD(thridx).sleeptime;
+
+    /* Unlock the @e world after sleep time retrieved */
+    pthread_mutex_unlock(&pjvm->sleeplock);
+
+    /* Report sleep time value */
+    return(rc);
+
+} /* END of timeslice_get_thread_sleeptime() */
+
+
+/*!
+ * @brief Length of time slice interval as used by
+ * @c @b setitimer(2).
+ */
+static struct itimerval timeslice_period;
+
+
+/*!
+ * @brief Interval timer handler for the @b signal(SIGALRM) event.
+ *
+ *
+ * @b Parameters: @link #rvoid rvoid@endlink
+ *
+ *
+ *       @returns @link #rvoid rvoid@endlink
+ *
+ *
+ * @warning Eclipse users need to remember that setting a combination
+ *          of the value of @link #JVMCFG_TIMESLICE_PERIOD_ENABLE
+            JVMCFG_TIMESLICE_PERIOD_ENABLE@endlink
+ *          to @link #rtrue rtrue@endlink, the value
+ *          of @link #JVMCFG_TIMESLICE_PERIOD_SECONDS
+            JVMCFG_TIMESLICE_PERIOD_SECONDS@endlink to zero (0), and
+ *          the value of @link #JVMCFG_TIMESLICE_PERIOD_MICROSECONDS
+            JVMCFG_TIMESLICE_PERIOD_MICROSECONDS@endlink to a low
+ *          milliseconds value is @e certain to interfere with the
+ *          proper operation of the GDB debug process due to the high
+ *          frequency of thread context changes per second.
+ *          The debug session @b will terminate without rhyme nor
+ *          reason.  Setting the period to several seconds will
+ *          elminate this problem at the expense of time slicing
+ *          on a normal basis.  For unit testing, this is not a
+ *          problem.  For integration testing, you are on your own....
+ *
+ */
+
+static void timeslice_tick(/* void --GCC won't allow this declaration*/)
+{
+    /* Suppress SIGALRM until finished with this handler */
+    signal(SIGALRM, SIG_IGN);
+
+    /* Debug report of timer.  Use ONLY for SLOW INTERVALS! */
+    if (JVMCFG_TIMESLICE_DEBUG_REPORT_MIN_SECONDS != 0) /* 0:= disable*/
+    {
+        if (JVMCFG_TIMESLICE_DEBUG_REPORT_MIN_SECONDS <=
+            timeslice_period.it_interval.tv_sec)
+        {
+            sysDbgMsg(DML9, "timeslice_tick", "tick");
+        }
+    }
+
+    /*
+     * Process signal by telling JVM to go to next time slice.
+     * Also decrement sleep interval timers for sleeping, joining,
+     * and waiting threads.
+     */
+    pjvm->timeslice_expired = rtrue;
+    threadutil_update_sleeptime_interval();
+
+    /* Set next SIGALARM for next tick of the time slice timer */
+    signal(SIGALRM, timeslice_tick);
+
+} /* END of timeslice_tick() */
+
+
+/*!
+ * @brief Interval timer thread.
+ *
+ *
+ * @param  dummy The @c @b setitimer(2) system call requires
+ *               a <b><code>(void *)</code></b> that has no
+ *               meaning here.
+ *
+ *
+ * @returns The required <b><code>(void *)</code></b> is passed back,
+ *          but this function never returns until the time slice
+ *          thread is killed.
+ *
+ */
+void *timeslice_run(void *dummy)
+{
+    /* Start timer and make its first tick one period from now */
+    timeslice_period.it_interval.tv_sec =
+                                        JVMCFG_TIMESLICE_PERIOD_SECONDS;
+    timeslice_period.it_interval.tv_usec =
+                                   JVMCFG_TIMESLICE_PERIOD_MICROSECONDS;
+    timeslice_period.it_value.tv_sec =
+                                        JVMCFG_TIMESLICE_PERIOD_SECONDS;
+    timeslice_period.it_value.tv_usec =
+                                   JVMCFG_TIMESLICE_PERIOD_MICROSECONDS;
+
+    /* If timer is configured to run, get it going */
+    if (rtrue == JVMCFG_TIMESLICE_PERIOD_ENABLE)
+    {
+
+        /*
+         * Set initial SIGALARM for timer_tick(),
+         * arm timer to generate it.
+         */
+        signal(SIGALRM, timeslice_tick);
+
+        int rc = setitimer(ITIMER_REAL,
+                           &timeslice_period,
+                           (void *) rnull);
+
+        if (0 != rc)
+        {
+            sysErrMsg("timeslice_run", "Cannot start interval timer");
+            exit_jvm(EXIT_TIMESLICE_START);
+/*NOTREACHED*/
+        }
+    }
+
+    /*
+     * Do nothing except wait on timer ticks.
+     * Eventually, the main process exits and
+     * this thread will die along with it without
+     * ever having left the while() loop.
+     *
+     * If timer is not configured to run, this loop
+     * will never see SIGALRM and timer ticks.
+     */
+
+    while(rtrue)
+    {
+        yield();
+    }
+
+/*NOTREACHED*/
+    return((void *) rnull);
+
+} /* END of timeslice_run() */
+
+
+/*!
+ * @brief Shut down the time slicing mechanism for JVM shutdown.
+ *
+ *
+ * @b Parameters: @link #rvoid rvoid@endlink
+ *
+ *
+ *       @returns @link #rvoid rvoid@endlink
+ *
+ */
+rvoid timeslice_shutdown(rvoid)
+{
+    /* Suppress SIGALRM so future tick does not happen AT ALL */
+    signal(SIGALRM, SIG_IGN);
+
+    /* Ignore error */
+    pthread_cancel(posix_thread_id);
+
+    /*! @todo Is this necessary at JVM shutdown time? */
+    /* pthread_mutex_destroy(&pjvm->sleeplock); */
+
+    /* Declare this module uninitialized */
+    jvm_timeslice_initialized = rfalse;
+
+    return;
+
+} /* END of timeslice_shutdown() */
+
+
+/* EOF */

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/tmparea.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/tmparea.c?rev=307257&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/tmparea.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/tmparea.c Fri Oct  7 21:27:56 2005
@@ -0,0 +1,201 @@
+/*!
+ * @file tmparea.c
+ *
+ * @brief Create and manage temporary directory area for class files,
+ * etc.
+ *
+ *
+ * @section Control
+ *
+ * \$URL: https://svn.apache.org/path/name/tmparea.c $ \$Id: tmparea.c 0 09/28/2005 dlydick $
+ *
+ * Copyright 2005 The Apache Software Foundation
+ * or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 ("the License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied.
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * @version \$LastChangedRevision: 0 $
+ *
+ * @date \$LastChangedDate: 09/28/2005 $
+ *
+ * @author \$LastChangedBy: dlydick $
+ *         Original code contributed by Daniel Lydick on 09/28/2005.
+ *
+ * @section Reference
+ *
+ */
+
+#include "arch.h"
+ARCH_COPYRIGHT_APACHE(tmparea, c, "$URL: https://svn.apache.org/path/name/tmparea.c $ $Id: tmparea.c 0 09/28/2005 dlydick $");
+
+ 
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include "jvmcfg.h"
+#include "exit.h"
+#include "heap.h" 
+#include "util.h"
+
+
+/*!
+ * @brief Initialize the class area of the JVM model
+ *
+ *
+ * @b Parameters: @link #rvoid rvoid@endlink
+ *
+ *
+ *       @returns @link #rvoid rvoid@endlink
+ *
+ */
+static rchar *env_tmpdir = CHEAT_AND_USE_NULL_TO_INITIALIZE;
+
+static rchar tmparea[100];
+
+rvoid tmparea_init(char **argv)
+{
+    struct stat statbfr;
+    char *argv0name = strrchr(argv[0], JVMCFG_PATHNAME_DELIMITER_CHAR);
+
+    if (rnull != argv0name)
+    {
+        argv0name++;
+    }
+    else
+    {
+        argv0name = argv[0];
+    }
+
+    int pid = getpid();
+
+    env_tmpdir = getenv("TMPDIR");
+
+    if (rnull == env_tmpdir)
+    {
+        env_tmpdir = JVMCFG_TMPAREA_DEFAULT;
+    }
+
+    sprintfLocal(tmparea,
+                 "%s%ctmp.%s.%d",
+                 env_tmpdir,
+                 JVMCFG_PATHNAME_DELIMITER_CHAR,
+                 argv0name,
+                 pid);
+
+    int rc = mkdir(tmparea, 0755); /* Could use <sys/stat.h> constants*/
+
+    /* Verify existence of directory */
+    rc = stat(tmparea, &statbfr);
+
+    if (0 != rc)
+    {
+        sysErrMsg("tmparea_init",
+                  "Cannot create temp directory %s",
+                  tmparea);
+        exit_jvm(EXIT_TMPAREA_MKDIR);
+/*NOTREACHED*/
+    }
+    /* Declare this module initialized */
+    jvm_tmparea_initialized = rtrue;
+
+    return;
+
+} /* END of tmparea_init() */
+
+
+/*!
+ * Retrieve the temporary directory area path.
+ *
+ *
+ * @b Parameters: @link #rvoid rvoid@endlink
+ *
+ *
+ * @returns Null-terminated string to temp area.
+ *
+ */
+const rchar *tmparea_get()
+{
+    return((const rchar *) tmparea);
+
+} /* END of tmparea_get() */
+
+
+/*!
+ * @brief Shut down the temporary directory area after JVM execution.
+ *
+ *
+ * @b Parameters: @link #rvoid rvoid@endlink
+ *
+ *
+ *       @returns @link #rvoid rvoid@endlink
+ *
+ */
+rvoid tmparea_shutdown(rvoid)
+{
+
+/* Normal method requires directory to be empty:
+ *
+ *  int rc = rmdir(tmparea);
+ *
+ *  if (0 != rc)
+ *  {
+ *      sysErrMsg("tmparea_shutdown",
+ *                "Cannot remove temp directory %s",
+ *                tmparea);
+ *      exit_jvm(EXIT_TMPAREA_RMDIR);
+**NOTREACHED**
+ *  }
+ *
+ */
+
+    struct stat statbfr;
+
+/* Since there will be temp files here, cheat just a @e little bit: */
+
+
+    rchar *rmscript =        /* format spec %s make strlen longer than
+                                it needs to be, but it is benign */
+        HEAP_GET_DATA(strlen(JVMCFG_TMPAREA_REMOVE_SCRIPT) +
+                          strlen(tmparea) +
+                          sizeof(rchar) /* NUL byte */,
+                      rfalse);
+
+    sprintfLocal(rmscript, JVMCFG_TMPAREA_REMOVE_SCRIPT, tmparea);
+
+    int rc = system(rmscript);
+
+    /* Verify missing directory */
+    rc = stat(tmparea, &statbfr);
+
+    if (0 == rc)
+    {
+        sysErrMsg("tmparea_shutdown",
+                  "Cannot remove temp directory %s",
+                  tmparea);
+        exit_jvm(EXIT_TMPAREA_RMDIR);
+/*NOTREACHED*/
+    }
+
+    /* Declare this module uninitialized */
+    jvm_tmparea_initialized = rfalse;
+
+    return;
+
+} /* END of tmparea_shutdown() */
+
+
+/* EOF */

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/unicode.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/unicode.c?rev=307257&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/unicode.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/unicode.c Fri Oct  7 21:27:56 2005
@@ -0,0 +1,319 @@
+/*!
+ * @file unicode.c
+ *
+ * @brief Manipulate Unicode (@link #jchar jchar@endlink)[]
+ * character strings.
+ *
+ * There are three character string types in this program:
+ * null-terminated @link #rchar (rchar)@endlink strings
+ * @e ala 'C' language, UTF-8
+ * @link #CONSTANT_Utf8_info (CONSTANT_Utf8_info)@endlink strings,
+ * and Unicode @link #jchar (jchar)[]@endlink strings.
+ *
+ * Unicode (@link #jchar jchar@endlink) character utilities
+ * that do @e not involve UTF8.
+ *
+ * ALL referenced to type (@link #jchar jchar@endlink) involve
+ * Unicode characters throughout all of the code.  Manipulations
+ * of them should take place @e only through these utilities.
+ *
+ *
+ * @section Control
+ *
+ * \$URL: https://svn.apache.org/path/name/unicode.c $ \$Id: unicode.c 0 09/28/2005 dlydick $
+ *
+ * Copyright 2005 The Apache Software Foundation
+ * or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 ("the License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied.
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * @version \$LastChangedRevision: 0 $
+ *
+ * @date \$LastChangedDate: 09/28/2005 $
+ *
+ * @author \$LastChangedBy: dlydick $
+ *         Original code contributed by Daniel Lydick on 09/28/2005.
+ *
+ * @section Reference
+ *
+ */
+
+#include "arch.h"
+ARCH_COPYRIGHT_APACHE(unicode, c, "$URL: https://svn.apache.org/path/name/unicode.c $ $Id: unicode.c 0 09/28/2005 dlydick $");
+
+
+#include <string.h>
+
+#include "jvmcfg.h" 
+#include "cfmacros.h"
+#include "classfile.h"
+
+
+/*
+ *
+ * Convert Unicode buffer into UTF8 buffer.
+ *
+ *
+ * @param[in]  inbfr   Unicode character string
+ *
+ * @param[in]  length  Number of bytes in @b inbfr
+ *
+ * @param[out] outbfr  UTF8 byte string
+ *
+ *
+ * @returns  UTF8 structure containing length and character buffer (plus
+ *           tag), but return in (cp_info_dup) for full proper word
+ *           alignment. When done with the data, call HEAP_FREE_DATA()
+ *           on it.
+ *
+ *    @c @b rc-\>bytes    UTF8 version of @b inbfr string in @b outbfr
+ *
+ *    @c @b rc-\>length   Number of UTF8 bytes in
+ *                        @c @b rc-\>bytes.  This will
+ *                        only be the same as input @b length
+ *                        when ALL UTF8 characters are 7-bit
+ *                        ASCII.  It will otherwise be less
+ *                        than that.
+ */
+
+cp_info_dup *unicode_cnv2utf(jchar *inbfr, jshort length)
+{
+    jshort bytecnvcount = 0;
+    jshort unicodecnvcount;
+    jubyte *outbfr;
+
+    /*
+     * Make two passes through input string, one for UTF8 length (for
+     * proper heap allocation size), one for the conversion.
+     *
+     * Pass 1: calculate result size for heap allocation.  This is
+     *         merely a stripped-down edition of pass 2, only
+     *         incrementing input buffer pointer and byte count.
+     */
+    for (unicodecnvcount = 0;
+         unicodecnvcount < length;
+         unicodecnvcount++)
+    {
+        /* Process one-byte UTF8 conversion */
+        if ((UTF8_SINGLE_MIN <= *inbfr) &&
+            (UTF8_SINGLE_MAX >= *inbfr))
+        {
+            /*
+             * Calculate a narrowing conversion,
+             * but 9 MS bits are all zeroes, so no value change.
+             */
+            inbfr++;
+            bytecnvcount++;
+        }
+        else
+        {
+            /* Calculate two-byte UTF8 conversion */
+            if (((UNICODE_DOUBLE_MIN <= *inbfr) &&
+                 (UNICODE_DOUBLE_MAX >= *inbfr))
+
+            /* Also handle special case of NUL as two-byte character. */
+                || (UNICODE_DOUBLE_NUL == *inbfr))
+            {
+                outbfr++;
+                bytecnvcount++;
+
+                inbfr++;
+                bytecnvcount++;
+            }
+            else
+            {
+                /*
+                 * Calculate three-byte UTF8 conversion-- all remaining
+                 * cases, UNICODE_TRIPLE_MIN to UNICODE_TRIPLE_MAX
+                 */
+                bytecnvcount++;
+
+                bytecnvcount++;
+
+                inbfr++;
+                bytecnvcount++;
+            }
+        }
+    } /* for () */
+
+    /*
+     * Allocate enough heap space for output string, but within the
+     * context of the output result type.  The size calculation
+     * replaces generic (cp_info) with specifc (CONSTANT_Utf8_info)
+     * info, adjusting for the amount of string data to be stored
+     * into the result.
+     */
+    cp_info_dup *rc = HEAP_GET_DATA(sizeof(cp_info_dup) -
+                                        sizeof(cp_info) +
+                                        sizeof(CONSTANT_Utf8_info) -
+                                        sizeof(u1) +
+                                        bytecnvcount,
+                                    rfalse);
+
+    /* Prepare output structure with everything but character cnv */
+    CONSTANT_Utf8_info *pcpui = PTR_THIS_CP_Utf8(rc);
+    pcpui->tag = CONSTANT_Utf8;
+    pcpui->length = bytecnvcount;
+    outbfr = (jubyte *) pcpui->bytes;
+
+    /* Pass 2:  Perform conversion itself */
+    bytecnvcount = 0;
+
+    for (unicodecnvcount = 0;
+         unicodecnvcount < length;
+         unicodecnvcount++)
+    {
+        /* Process one-byte UTF8 conversion */
+        if ((UTF8_SINGLE_MIN <= *inbfr) &&
+            (UTF8_SINGLE_MAX >= *inbfr))
+        {
+            /*
+             * Perform a narrowing conversion,
+             * but 9 MS bits are all zeroes, so no value change.
+             */
+            *outbfr++ = UTF8_SINGLE_MASK0 & ((jbyte) (*inbfr++));
+            bytecnvcount++;
+        }
+        else
+        {
+            /* Process two-byte UTF8 conversion */
+            if (((UNICODE_DOUBLE_MIN <= *inbfr) &&
+                 (UNICODE_DOUBLE_MAX >= *inbfr))
+
+            /* Also handle special case of NUL as two-byte character. */
+                || (UNICODE_DOUBLE_NUL == *inbfr))
+            {
+                *outbfr    = (*inbfr >> UTF8_DOUBLE_FIRST_SHIFT) &
+                            UTF8_DOUBLE_FIRST_MASK0;
+                *outbfr++ |= UTF8_DOUBLE_FIRST_VAL;
+                bytecnvcount++;
+
+                *outbfr    = (*inbfr++) & UTF8_DOUBLE_SECOND_MASK0;
+                *outbfr++ |= UTF8_DOUBLE_SECOND_VAL;
+                bytecnvcount++;
+            }
+            else
+            {
+                /*
+                 * Process three-byte UTF8 conversion-- all remaining
+                 * cases, UNICODE_TRIPLE_MIN to UNICODE_TRIPLE_MAX
+                 */
+                *outbfr    = (*inbfr >> UTF8_TRIPLE_FIRST_SHIFT) &
+                            UTF8_TRIPLE_FIRST_MASK0;
+                *outbfr++ |= UTF8_TRIPLE_FIRST_VAL;
+                bytecnvcount++;
+
+                *outbfr    = (*inbfr >> UTF8_TRIPLE_SECOND_SHIFT) &
+                            UTF8_TRIPLE_SECOND_MASK0;
+                *outbfr++ |= UTF8_TRIPLE_SECOND_VAL;
+                bytecnvcount++;
+
+                *outbfr    = (*inbfr++) & UTF8_TRIPLE_THIRD_MASK0;
+                *outbfr++ |= UTF8_TRIPLE_THIRD_VAL;
+                bytecnvcount++;
+            }
+        }
+    } /* for () */
+
+    return(rc);
+
+} /* END of unicode_cnv2utf() */
+
+
+/*!
+ * @brief Compare two Unicode strings of any length, @b s1 minus @b s2
+ *
+ *
+ * @param  s1   First string to compare
+ *
+ * @param  l1   Length of first string
+ *
+ * @param  s2   Second string to compare
+ *
+ * @param  l2   Length of second string
+ *
+ *
+ * @returns lexicographical difference of <b><code>s1 - s2</code></b>.
+ *          Notice that the (jchar) data is unsigned, the (jshort)
+ *          result is signed, due to the arithmetic nature of the
+ *          calculation.
+ *
+ */
+jshort unicode_strcmp(jchar *s1, u2 l1, jchar *s2, u2 l2)
+{
+    /* Compare shortest common run length */
+    rint cmplen = (l1 < l2) ? l1 : l2;
+
+    /* Perform Unicode strlen() function */
+    rint i;
+    jshort rc = 0;
+
+    for (i = 0; i < cmplen; i++)
+    {
+        rc = s1[i] - s2[i];
+        if (0 != rc)
+        {
+            break;
+        }
+    }
+
+    /*
+     * THIS LOGIC IS THE SAME AS FOR s1_s2_strncmp(), BUT
+     * OPERATES ON (jchar) instead of (rchar).
+     */
+
+    /* Return from several permutations of strlen */
+    if (l1 == l2)
+    {
+        return(rc);
+    }
+    else
+    if (l1 > l2)
+    {
+        /*
+         * If a difference existed, return it, else use
+         * the last character of @b s1 as character minus
+         * NUL byte (or zero), which equals character.
+         */
+        if (0 != rc)
+        {
+            return(rc);
+        }
+
+        /*
+         * First character of @b s1 past length of @b s2 
+         */
+        return((jshort) s1[l2]);
+    }
+    else
+    {
+        /* If a difference existed, return it, else use end of @b s2 */
+        /*
+         * If a difference existed, return it, else use
+         * the last character of @b s1 as NUL byte (or zero)
+         * minus character, which equals negative of character.
+         */
+        if (0 != rc)
+        {
+            return(rc);
+        }
+
+        /* First character of @b s2 past length of @b s1 */
+        return((jshort) (0 - s2[l1]));
+    }
+} /* END of unicode_strcmp() */
+
+
+/* EOF */

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/unicode.h
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/unicode.h?rev=307257&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/unicode.h (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/unicode.h Fri Oct  7 21:27:56 2005
@@ -0,0 +1,61 @@
+#ifndef _unicode_h_defined_
+#define _unicode_h_defined_
+
+/*!
+ * @file unicode.h
+ *
+ * @brief Manipulate Unicode (@link #jchar jchar@endlink)[]
+ * character strings.
+ *
+ * There are three character string types in this program:
+ * null-terminated @link #rchar (rchar)@endlink strings
+ * @e ala 'C' language, UTF-8
+ * @link #CONSTANT_Utf8_info (CONSTANT_Utf8_info)@endlink strings,
+ * and Unicode @link #jchar (jchar)[]@endlink strings.
+ *
+ *
+ * @section Control
+ *
+ * \$URL: https://svn.apache.org/path/name/unicode.h $ \$Id: unicode.h 0 09/28/2005 dlydick $
+ *
+ * Copyright 2005 The Apache Software Foundation
+ * or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 ("the License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied.
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * @version \$LastChangedRevision: 0 $
+ *
+ * @date \$LastChangedDate: 09/28/2005 $
+ *
+ * @author \$LastChangedBy: dlydick $
+ *         Original code contributed by Daniel Lydick on 09/28/2005.
+ *
+ * @section Reference
+ *
+ */
+
+ARCH_COPYRIGHT_APACHE(unicode, h, "$URL: https://svn.apache.org/path/name/unicode.h $ $Id: unicode.h 0 09/28/2005 dlydick $");
+
+
+/* Prototypes for functions in 'unicode.c' */
+
+extern cp_info_dup *unicode_cnv2utf(jchar *inbfr, jshort length);
+
+extern jshort unicode_strcmp(jchar *us1, u2 l1, jchar *us2, u2 l2);
+
+#endif /* _unicode_h_defined_ */
+
+
+/* EOF */

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/utf.c
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/utf.c?rev=307257&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/utf.c (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/utf.c Fri Oct  7 21:27:56 2005
@@ -0,0 +1,836 @@
+/*!
+ * @file utf.c
+ *
+ * @brief Manipulate UTF-8 CONSTANT_Utf8_info character strings.
+ *
+ * There are three character string types in this program:
+ * null-terminated @link #rchar (rchar)@endlink strings
+ * @e ala 'C' language, UTF-8
+ * @link #CONSTANT_Utf8_info (CONSTANT_Utf8_info)@endlink strings,
+ * and Unicode @link #jchar (jchar)[]@endlink strings.
+ *
+ * Convert one or UTF-8 (jbyte) bytes to and from Unicode (jchar)
+ * characters, plus related functions, like comparison and string
+ * length.
+ *
+ * Why are these functions called @b utf_XXX() instead of @b utf8_XXX()?
+ * Originally, they were called such, but when the JDK 1.5 class file
+ * spec, section 4, was reviewed (after working with the 1.2/1.4
+ * versions), it was discovered that certain other @b UTF-xx formats
+ * were also provided in the spec, even if not accurately defined.
+ * (Due to errors in the revised class file specification, the 21-bit
+ * UTF characters (6 bytes) will not be implemented until a definitive
+ * correction is located.  However, in anticipation of this correction,
+ * the functions are now named utf_XXX() without respect to character
+ * bit width.)  Notice, however, that the spec, section 4, defines a
+ * CONSTANT_Utf8 and a CONSTANT_Utf8_info.  Therefore, these
+ * designations will remain in the code unless changed in the spec.
+ *
+ *
+ * @section Control
+ *
+ * \$URL: https://svn.apache.org/path/name/utf.c $ \$Id: utf.c 0 09/28/2005 dlydick $
+ *
+ * Copyright 2005 The Apache Software Foundation
+ * or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 ("the License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied.
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * @version \$LastChangedRevision: 0 $
+ *
+ * @date \$LastChangedDate: 09/28/2005 $
+ *
+ * @author \$LastChangedBy: dlydick $
+ *         Original code contributed by Daniel Lydick on 09/28/2005.
+ *
+ * @section Reference
+ *
+ */
+
+#include "arch.h"
+ARCH_COPYRIGHT_APACHE(utf, c, "$URL: https://svn.apache.org/path/name/utf.c $ $Id: utf.c 0 09/28/2005 dlydick $");
+
+
+#include <string.h>
+
+#include "jvmcfg.h" 
+#include "cfmacros.h"
+#include "classfile.h"
+#include "nts.h"
+#include "util.h"
+
+
+/*!
+ * Store a Unicode @c @b ? when invalid UTF state found,
+ * adj return code
+ */
+#define MAP_INVALID_UTF8_TO_QUESTION_MARK *outbfr++ = (jchar) '?'; \
+                                         inbfr++
+
+/*! Detect NUL character and quit when found */
+#define RETURN_IF_NUL_BYTE if (UTF8_FORBIDDEN_ZERO == *inbfr) \
+                           {return(charcnvcount); }
+
+/*!
+ * @brief Convert UTF8 buffer into Unicode buffer.
+ *
+ *
+ * @param[in]  utf_inbfr  UTF string structure
+ *
+ * @param[out] outbfr     Buffer for resulting Unicode character string
+ *
+ *
+ * @returns  Two returns, one a buffer, the other a count:
+ *
+ *    *outbfr        Unicode version of @b utf_inbfr string in @b outbfr
+ *
+ *    charcnvcount   (Return value of function)  Number of Unicode
+ *                     characters in @b outbfr.  This will only be the
+ *                     same as @b length when ALL UTF characters are
+ *                     ASCII.  It will otherwise be less than that.
+ *
+ * SPEC AMBIGUITY:  In case of invalid characters, a Unicode
+ * @c @b ? is inserted and processing continues.  In this way,
+ * the result string will still be invalid, but at least it will be
+ * proper Unicode.  This may prove more than is necessary, but the
+ * spec says nothing at all about this matter.  Since the NUL character
+ * may not appear in UTF-8, if a buffer is terminated by a NUL in the
+ * first @c @b utf_inbfr->length bytes, termination will be
+ * assumed.  If a @link #UTF8_FORBIDDEN_MIN UTF8_FORBIDDEN_xxx@endlink
+ * character is read, it is converted to a Unicode @c @b ? also.
+ *
+ */
+
+jshort utf_utf2unicode(CONSTANT_Utf8_info *utf_inbfr, jchar *outbfr)
+{
+    jshort charcnvcount;
+
+    jubyte *inbfr = (jubyte *) utf_inbfr->bytes;
+
+    for (charcnvcount = 0;
+         charcnvcount < utf_inbfr->length;
+         charcnvcount++)
+    {
+        RETURN_IF_NUL_BYTE;
+        if (UTF8_SINGLE_MAX >= *inbfr)
+        {
+            /* Process one-byte form */
+            *outbfr++ = (jchar) *inbfr++;
+        }
+        else
+        {
+            /* Process two-byte form */
+            if (UTF8_TRIPLE_FIRST_VAL > *inbfr)
+            {
+                if (UTF8_DOUBLE_FIRST_VAL > *inbfr)
+                {
+                    MAP_INVALID_UTF8_TO_QUESTION_MARK;
+                    continue;
+                }
+
+                /* Store top half of Unicode character */
+                *outbfr = (jchar)
+                          (((*inbfr++) & UTF8_DOUBLE_FIRST_MASK0)
+                            << UTF8_DOUBLE_FIRST_SHIFT);
+
+                /* Abort if next byte is NUL */
+                RETURN_IF_NUL_BYTE;
+
+                if ((UTF8_DOUBLE_SECOND_VAL | UTF8_DOUBLE_SECOND_MASK0)
+                    < *inbfr)
+                {
+                    /*
+                     * Map invalid forms to @c @b ? and
+                     * move to next char 
+                     */
+                    MAP_INVALID_UTF8_TO_QUESTION_MARK;
+                    continue;
+                }
+
+                /* Store bottom half of Unicode character */
+                *outbfr++ |= (jchar)
+                             ((*inbfr++) & UTF8_DOUBLE_SECOND_MASK0);
+            }
+            else
+            {
+                /* Process three-byte form */
+                if ((UTF8_TRIPLE_FIRST_VAL | UTF8_TRIPLE_FIRST_MASK0)
+                       < *inbfr)
+                {
+                    /* This also considers UTF8_FORBIDDEN_MIN/MAX
+                         bytes */
+                    MAP_INVALID_UTF8_TO_QUESTION_MARK;
+                    continue;
+                }
+
+                /* Store top third of Unicode character */
+                *outbfr = (jchar)
+                          (((*inbfr++) & UTF8_TRIPLE_FIRST_MASK0)
+                            << UTF8_TRIPLE_FIRST_SHIFT);
+
+                /* Abort if next byte is NUL */
+                RETURN_IF_NUL_BYTE;
+
+                if ((UTF8_TRIPLE_SECOND_VAL | UTF8_TRIPLE_SECOND_MASK0)
+                    < *inbfr)
+                {
+                    /*
+                     * Map invalid forms to @c @b ? and
+                     * move to next char 
+                     */
+                    MAP_INVALID_UTF8_TO_QUESTION_MARK;
+                    continue;
+                }
+
+                /* Store middle third of Unicode character */
+                *outbfr |= (jchar)
+                           (((*inbfr++) & UTF8_TRIPLE_SECOND_MASK0)
+                             << UTF8_TRIPLE_SECOND_SHIFT);
+
+                /* Abort if next byte is NUL */
+                RETURN_IF_NUL_BYTE;
+
+                if ((UTF8_TRIPLE_THIRD_VAL | UTF8_TRIPLE_THIRD_MASK0)
+                    < *inbfr)
+                {
+                    /*
+                     * Map invalid forms to @c @b ? and
+                     * move to next char 
+                     */
+                    MAP_INVALID_UTF8_TO_QUESTION_MARK;
+                    continue;
+                }
+
+                /* Store bottom third of Unicode character */
+                *outbfr++ |= (jchar)
+                             ((*inbfr++) & UTF8_TRIPLE_THIRD_MASK0);
+            }
+        }
+
+    } /* for (i) */
+
+    /* Done.  Return number of characters processed */
+    return(charcnvcount);
+
+} /* END of utf_utf2unicode() */
+
+
+/*!
+ * @brief Convert a UTF string from a (CONSTANT_Utf8_info *) into a
+ * null-terminated string by allocating heap and copying the UTF data.
+ *
+ * When done with result, perform HEAP_FREE_DATA(result).
+ *
+ * @param   src   Pointer to UTF string, most likely from constant pool
+ *
+ * @returns Null-terminated string in heap or
+ *          @link #rnull rnull@endlink if heap alloc error.
+ *
+ */
+
+rchar *utf_utf2prchar(CONSTANT_Utf8_info *src)
+{
+    /* Allocate heap for UTF data plus NUL byte */
+    rchar *rc = HEAP_GET_DATA(sizeof(rchar) + src->length, rfalse);
+
+    /* Copy to heap area */
+    memcpy(rc, &src->bytes[0], src->length);
+
+    /* Append NUL character */
+    rc[src->length] = '\0';
+
+    /* Produce result */
+    return(rc);
+
+} /* END of utf_utf2prchar() */
+
+
+/*!
+ * @brief Compare two strings of any length, and potentially neither
+ * null-terminated, that is, could be a UTF string.
+ *
+ * If strings are of equal length, this function is equivalent
+ * to @c @b strcmp(3).  If not of equal length, result is like
+ * comparing @c @b n bytes of @c @b strncmp(3), where non-equal
+ * result is returned, but if equal result, it is like
+ * @c @b n+1, where the final byte is a @c @b \\0 (NUL)
+ * character, so longer string's @c @b n+1 character
+ * is reported, either as positive value (@b s1 longer) or as
+ * negative value (@b s2 longer).
+ *
+ * This function should be used on ALL string comparisons that
+ * potentially involve lack of NUL termination, namely, @e anything
+ * to do with UTF strings of any sort.  It is recommended also for
+ * any null-terminated string just so all string comparisons work
+ * @e exactly alike, no matter whether (rchar *) or UTF, whether of
+ * equal length or not.
+ *
+ * @param  s1        (rchar *) to first string
+ *
+ * @param  l1        Length of string @b s1, regardless of any
+ *                     null termination being present or absent
+ *                    in @b s1.
+ *
+ * @param  s2        (rchar *) to second string
+ *
+ * @param  l2        length of string @b s2, regardless of any
+ *                     null termination being present or absent
+ *                     in @b s2.
+ *
+ * @returns lexicographical difference of <b><code>s1 - s2</code></b>.
+ *          Notice that the (rchar) data is implicitly unsigned
+ *          (although the actual signage is left to the compiler),
+ *          while the (jbyte) result is explicitly signed, due to the
+ *          arithmetic nature of the calculation.
+ *
+ */
+static jbyte s1_s2_strncmp(u1 *s1, int l1, u1 *s2, int l2)
+{
+    /* Compare shortest common run length */
+    int cmplen = (l1 < l2) ? l1 : l2;
+    jbyte rc = strncmp(s1, s2, cmplen);
+
+    /*
+     * THIS LOGIC IS THE SAME AS FOR unicode_strncmp(), BUT
+     * OPERATES ON (jchar) instead of (rchar)
+     */
+
+    /* Return from several permutations of strlen */
+    if (l1 == l2)
+    {
+        return(rc);
+    }
+    else
+    if (l1 > l2)
+    {
+        /*
+         * If a difference existed, return it, else use
+         * the last character of @b s1 as character minus
+         * NUL byte (or zero), which equals character.
+         */
+        if (0 != rc)
+        {
+            return(rc);
+        }
+
+        /*
+         * First character of @b s1 past length of @b s2 
+         */
+        return((jbyte) s1[l2]);
+    }
+    else
+    {
+        /* If a difference existed, return it, else use end of @b s2 */
+        /*
+         * If a difference existed, return it, else use
+         * the last character of @b s1 as NUL byte (or zero)
+         * minus character, which equals negative of character.
+         */
+        if (0 != rc)
+        {
+            return(rc);
+        }
+
+        /* First character of @b s2 past length of @b s1 */
+        return((jbyte) (0 - s2[l1]));
+    }
+} /* END of s1_s2_strncmp() */
+
+
+/*!
+ * @brief Compare two UTF strings from constant_pool, @b s1 minus @b s2
+ *
+ * @param s1   First of two UTF strings to compare
+ *
+ * @param s2   Second of two UTF strings to compare
+ *
+ * @returns lexicographical value of first difference in strings,
+ *          else 0.
+ *
+ */
+jbyte utf_utf_strcmp(CONSTANT_Utf8_info *s1, CONSTANT_Utf8_info *s2)
+{
+    /* Perform unified comparison of both UTF strings */
+    return(s1_s2_strncmp(s1->bytes, s1->length, s2->bytes, s2->length));
+
+} /* END of utf_utf_strcmp() */
+
+
+/*!
+ * @brief Compare contents of null-terminated string to contents of
+ * a UTF string from a class file structure.
+ *
+ * @param  s1     Null-terminated string name
+ *
+ * @param  pcfs2  ClassFile where UTF string is found
+ *
+ * @param  cpidx2 Index in @b pcfs2 constant_pool of UTF string
+ *
+ *
+ * @returns lexicographical value of first difference in strings,
+ *          else 0.
+ *
+ */
+jbyte utf_prchar_pcfs_strcmp(rchar                   *s1,
+                             ClassFile               *pcfs2,
+                             jvm_constant_pool_index  cpidx2)
+{
+    int l1 = strlen(s1);
+
+    u1 *s2 = PTR_CP_THIS_STRNAME(pcfs2, cpidx2);
+
+    int l2 = CP_THIS_STRLEN(pcfs2, cpidx2);
+
+    /* Perform unified comparison of null-terminated vs UTF string */
+    return(s1_s2_strncmp(s1, l1, s2, l2));
+
+} /* END of utf_prchar_pcfs_strcmp() */
+
+
+/*!
+ * @brief Compare contents of UTF string to contents of a UTF string
+ * from a class file structure.
+ *
+ * @param  s1     UTF string name
+ *
+ * @param  pcfs2  ClassFile where UTF string is found
+ *
+ * @param  cpidx2 Index in @b pcfs2 constant_pool of UTF string
+ *
+ *
+ * @returns lexicographical value of first difference in strings,
+ *          else 0.
+ *
+ */
+jbyte utf_pcfs_strcmp(CONSTANT_Utf8_info      *s1,
+                      ClassFile               *pcfs2,
+                      jvm_constant_pool_index  cpidx2)
+{
+    u1 *s2 = PTR_CP_THIS_STRNAME(pcfs2, cpidx2);
+
+    int l2 = CP_THIS_STRLEN(pcfs2, cpidx2);
+
+    /* Perform unified comparison of null-terminated vs UTF string */
+    return(s1_s2_strncmp(s1->bytes, s1->length, s2, l2));
+
+} /* END of utf_pcfs_strcmp() */
+
+
+/*!
+ * @brief Common generic comparison, all parameters regularized.
+ *
+ * Compare a UTF or null-terminated string containing a
+ * formatted or unformatted class name with an @e unformatted UTF
+ * string from constant_pool.
+ * Compare @b s1 minus @b s2, but skipping, where applicable,
+ * the @b s1 initial BASETYPE_CHAR_L and the terminating
+ * BASETYPE_CHAR_L_TERM, plus any array dimension modifiers.  The second
+ * string is specified by a constant_pool index.  Notice that there
+ * are @e NO formatted class string names in the (CONSTANT_Class_info)
+ * entries of the constant_pool because such would be redundant.  (Such
+ * entries @e are the @e formal definition of the class.)
+ *
+ *
+ * @param s1     UTF string pointer to u1 array of characters.
+ *
+ * @param l1     length of @b s1.
+ *
+ * @param pcfs2  ClassFile structure containing second string
+ *               (containing an @e unformatted class name)
+ *
+ * @param cpidx2 constant_pool index of CONSTANT_Class_info entry
+ *               whose name will be compared (by getting its
+ *               @link CONSTANT_Class_info#name_index name_index@endlink
+ *               and the UTF string name of it)
+ *
+ *
+ * @returns lexicographical value of first difference in strings,
+ *          else 0.
+ *
+ */
+static jbyte utf_common_classname_strcmp(u1                      *s1,
+                                         int                      l1,
+                                         ClassFile               *pcfs2,
+                                         jvm_constant_pool_index cpidx2)
+{
+    CONSTANT_Class_info *pci = PTR_CP_ENTRY_CLASS(pcfs2, cpidx2);
+
+    u1 *s2 = PTR_CP_THIS_STRNAME(pcfs2, pci->name_index);
+    int l2 = CP_THIS_STRLEN(pcfs2, pci->name_index);
+
+    if (rtrue == nts_prchar_isclassformatted(s1))
+    {
+        s1++; /* Point PAST the BASETYPE_CHAR_L character */
+        l1--;
+
+        u1 *ps1end = strchr(s1, BASETYPE_CHAR_L_TERM);
+
+        /* Should @e always be @link #rtrue rtrue@endlink */
+        if (rnull != ps1end)
+        {
+            l1 = ps1end - (u1 *) s1; /* Adjust for terminator */
+        }
+    }
+
+
+    /*
+     * Perform unified comparison of (possibly) null-terminated
+     * vs UTF string
+     */
+    return(s1_s2_strncmp(s1, l1, s2, l2));
+
+} /* END of utf_common_classname_strcmp() */
+
+
+/*!
+ * @brief Compare a null-terminated string containing a
+ * formatted or unformatted class name with an @e unformatted UTF
+ * string from constant_pool.
+ *
+ *
+ * @param s1     Null-terminated string to compare, containing
+ *               formatted @e or unformatted class name
+ *               (utf_prchar_classname_strcmp() only).
+ *
+ * @param pcfs2  ClassFile structure containing second string
+ *               (containing an @e unformatted class name)
+ *
+ * @param cpidx2 constant_pool index of CONSTANT_Class_info entry
+ *               whose name will be compared (by getting its
+ *               @link CONSTANT_Class_info#name_index name_index@endlink
+ *               and the UTF string name of it)
+ *
+ *
+ * @returns lexicographical value of first difference in strings,
+ *          else 0.
+ *
+ */
+jbyte utf_prchar_classname_strcmp(rchar                   *s1,
+                                  ClassFile               *pcfs2,
+                                  jvm_constant_pool_index  cpidx2)
+{
+    return(utf_common_classname_strcmp((u1 *) s1,
+                                       strlen(s1),
+                                       pcfs2,
+                                       cpidx2));
+
+} /* END of utf_prchar_classname_strcmp() */
+
+
+/*!
+ * @brief Compare a UTF string containing a
+ * formatted or unformatted class name with an @e unformatted UTF
+ * string from constant_pool.
+ *
+ *
+ * @param s1     UTF string to compare, containing formatted @e or
+ *               unformatted class name.
+ *
+ * @param pcfs2  ClassFile structure containing second string
+ *               (containing an @e unformatted class name)
+ *
+ * @param cpidx2 constant_pool index of CONSTANT_Class_info entry
+ *               whose name will be compared (by getting its
+ *               @link CONSTANT_Class_info#name_index name_index@endlink
+ *               and the UTF string name of it)
+ *
+ *
+ * @returns lexicographical value of first difference in strings,
+ *          else 0.
+ *
+ */
+jbyte utf_classname_strcmp(CONSTANT_Utf8_info      *s1,
+                           ClassFile               *pcfs2,
+                           jvm_constant_pool_index  cpidx2)
+{
+    return(utf_common_classname_strcmp(s1->bytes,
+                                       s1->length,
+                                       pcfs2,
+                                       cpidx2));
+
+} /* END of utf_classname_strcmp() */
+
+
+/*!
+ * @brief Report the number of array dimensions prefixing a Java type
+ * string.
+ *
+ * No overflow condition is reported since it is assumed that @b inbfr
+ * is formatted with correct length.  Notice that because this logic
+ * checks @e only for array specifiers and does not care about the rest
+ * of the string, it may be used to evaluate field descriptions, which
+ * will not contain any class formatting information.
+ *
+ * If there is even a @e remote possibility that more than
+ * CONSTANT_MAX_ARRAY_DIMS dimensions will be found, compare
+ * the result of this function with the result of utf_isarray().
+ * If there is a discrepancy, then there was an overflow here.
+ * Properly formatted class files will @e never contain code with
+ * this condition.
+ *
+ * @note  This function is identical to nts_get_arraydims() except
+ *        that it works on (CONSTANT_Utf8_info *) instead of (rchar *).
+ *
+ *
+ * @param    inbfr   CONSTANT_Utf8_info string.
+ *
+ *
+ * @returns  Number of array dimensions in string.  For example,
+ *           this string contains three array dimensions:
+ *
+ *               @c @b [[[Lsome/path/name/filename;
+ *
+ *           If more than CONSTANT_MAX_ARRAY_DIMS are located, the
+ *           result is zero-- no other error is reported.
+ *
+ */
+
+jvm_array_dim utf_get_utf_arraydims(CONSTANT_Utf8_info *inbfr)
+{
+    /* Make return code wider than max to check overflow */
+    u4 rc = 0;
+
+    /* Start scanning at beginning of string */
+    u1 *pclsname = (u1 *) &inbfr->bytes[0];
+
+    /* Keep scanning until no more array specifications are found */
+    while (BASETYPE_CHAR_ARRAY == *pclsname++)
+    {
+        rc++; 
+    }
+
+    /* Check overflow, return default if so, else number of dimensions*/
+    if (CONSTANT_MAX_ARRAY_DIMS < rc)
+    {
+        return(LOCAL_CONSTANT_NO_ARRAY_DIMS);
+    }
+    else
+    {
+        /* Perform narrowing conversion into proper type for max */
+        return((jvm_array_dim) rc);
+    }
+
+} /* END of utf_get_utf_arraydims() */
+
+
+/*!
+ * @brief Test whether or not a Java type string is an array or not.
+ *
+ *
+ * @param    inbfr   CONSTANT_Utf8_info string.
+ *
+ *
+ * @returns  @link #rtrue rtrue@endlink if this is an array
+ *           specfication, else @link #rfalse rfalse@endlink.
+ *
+ */
+
+rboolean utf_isarray(CONSTANT_Utf8_info *inbfr)
+{
+  return((BASETYPE_CHAR_ARRAY == (u1)inbfr->bytes[0]) ? rtrue : rfalse);
+
+} /* END of utf_isarray() */
+
+
+/*!
+ * @brief Convert and an un-formatted class name UTF string (of the
+ * type @c @b ClassName and not of type
+ * @c @b [[[LClassName) from a (CONSTANT_Utf8_info *) into
+ * a null-terminated string with Java class formatting items.  Result
+ * is delivered in a heap-allocated buffer.  When done with result,
+ * perform HEAP_FREE_DATA(result) to return that buffer to the heap.
+ *
+ * This function @e will work on formatted class names
+ * @c @b [[[LClassName; and the difference is benign,
+ * but that is not its purpose.
+ *
+ * @param  src   Pointer to UTF string, most likely from constant pool
+ *
+ * @returns Null-terminated string @c @b LClasSName; in heap
+ *          or @link #rnull rnull@endlink if heap alloc error.
+ *
+ */
+
+rchar *utf_utf2prchar_classname(CONSTANT_Utf8_info *src)
+{
+    /* Retrieve string from UTF data first */
+    rchar *pstr = utf_utf2prchar(src);
+
+    if (rnull == pstr)
+    {
+        return(pstr);
+    }
+
+    /* Allocate heap for formatted version */
+
+    rchar *rc = HEAP_GET_DATA(sizeof(rchar) + /* Type specifier */
+                              sizeof(rchar) + /* Type spec terminator */
+                              sizeof(rchar) + /* NUL character */
+                              src->length,    /* data */
+                             rfalse);
+
+    int pstrlen = strlen(pstr);
+    rboolean isfmt  = nts_prchar_isclassformatted(pstr);
+
+    if (rtrue == isfmt)
+    {
+        /*
+         * Copy entire string plus NUL character into heap area,
+         * ignoring excess allocation when formatting is @e added
+         * to string.
+         */
+        memcpy(&rc[0], pstr, pstrlen);
+        rc[pstrlen] = '\0';
+    }
+    else
+    {
+        /* Initial formatting */
+        rc[0] = BASETYPE_CHAR_L;
+
+        /* Copy to heap area */
+        memcpy(&rc[1], pstr, pstrlen);
+
+        /* Append end formatting and NUL character */
+        rc[1 + pstrlen] = BASETYPE_CHAR_L_TERM;
+        rc[2 + pstrlen] = '\0';
+    }
+
+    HEAP_FREE_DATA(pstr);
+
+
+    /* Produce result */
+    return(rc);
+
+} /* END of utf_utf2prchar_classname() */
+
+
+/*!
+ * @brief Verify if a UTF string contains class formatting or not.
+ *
+ *
+ * @param  src   Pointer to UTF string, most likely from constant pool
+ *
+ *
+ * @returns @link #rtrue rtrue@endlink if string is formtted as
+ *          @c @b LClasSName; but
+ *          @link #rfalse rfalse@endlink otherwise, may also have
+ *          array descriptor prefixed, thus @c @b [[LClassName;
+ *
+ *
+ * @note  This function works just like nts_prchar_isclassformatted()
+ *        except that it works on (CONSTANT_Utf8_info) strings rather
+ *        than on (rchar *) strings.
+ */
+
+rboolean utf_utf_isclassformatted(CONSTANT_Utf8_info *src)
+{
+    jvm_utf_string_index utfidx;
+    rboolean rc = rfalse;
+
+    /* Chk array or class specifier.  If neither, cannot be formatted */
+    switch (src->bytes[0])
+    {
+        case BASETYPE_CHAR_ARRAY:
+        case BASETYPE_CHAR_L:
+            break;
+        default:
+            return(rfalse);
+    }
+
+
+    /*
+     * Now assume a potentially formatted string.
+     * Check for termination byte next.  If not present,
+     * nothing else matters and string cannot be formatted.
+     */
+    u1 *pbytes = src->bytes;
+
+    for (utfidx = 0; utfidx < src->length; utfidx++)
+    {
+        if (BASETYPE_CHAR_L_TERM == pbytes[utfidx])
+        {
+            rc = rtrue;
+            break;
+        }
+    }
+
+    /* If not terminated, then cannot be class formatted */
+    if (rfalse == rc)
+    {
+        return(rc);
+    }
+
+    /* Check initial formatting, including array spec */
+    jvm_array_dim arraydims = utf_get_utf_arraydims(src);
+
+    /* If any array specs, look immediately past them for class spec */
+    if (BASETYPE_CHAR_L == pbytes[arraydims])
+    {
+        return(rtrue);
+    }
+    else
+    {
+        return(rfalse);
+    }
+
+} /* END of utf_utf_isclassformatted() */
+
+
+/*!
+ *
+ * @brief Strip a UTF string of any class formatting it contains
+ * and return result in a heap-allocated buffer.
+ *
+ * When done with this result, perform HEAP_DATA_FREE(result) to
+ * return buffer to heap.
+ *
+ *
+ * @param  inbfr   Pointer to UTF string that is potentially formatted
+ *                 as @c @b LClassName; and which may also have
+ *                 array descriptor prefixed, thus
+ *                 @c @b [[LClassName; .  This will
+ *                 typically be an entry from the constant_pool.
+ *
+ *
+ * @returns heap-allocated buffer containing @c @b ClassName
+ *          with no formatting, regardless of input formatting or
+ *          lack thereof.
+ *
+ *
+ * @note  This function works just like
+ *        nts_prchar2prchar_unformatted_classname() except that
+ *        it takes a (CONSTANT_Utf8_info) string rather
+ *        than a (rchar *) string and returns a (CONSTANT_Utf8_info *).
+ *
+ */
+
+cp_info_dup *utf_utf2utf_unformatted_classname(cp_info_dup *inbfr)
+{
+    rchar *pstr = utf_utf2prchar(PTR_THIS_CP_Utf8(inbfr));
+
+    rchar *punf = nts_prchar2prchar_unformatted_classname(pstr);
+
+    HEAP_FREE_DATA(pstr);
+
+    cp_info_dup *rc = nts_prchar2utf(punf);
+
+    HEAP_FREE_DATA(punf);
+
+    return(rc);
+
+} /* END of utf_utf2utf_unformatted_classname() */
+
+
+/* EOF */

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/utf.h
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/utf.h?rev=307257&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/utf.h (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/utf.h Fri Oct  7 21:27:56 2005
@@ -0,0 +1,91 @@
+#ifndef _utf_h_defined_
+#define _utf_h_defined_
+
+/*!
+ * @file utf.h
+ *
+ * @brief Manipulate UTF-8 CONSTANT_Utf8_info character strings.
+ *
+ * There are three character string types in this program:
+ * null-terminated @link #rchar (rchar)@endlink strings
+ * @e ala 'C' language, UTF-8
+ * @link #CONSTANT_Utf8_info (CONSTANT_Utf8_info)@endlink strings,
+ * and Unicode @link #jchar (jchar)[]@endlink strings.
+ *
+ *
+ * @section Control
+ *
+ * \$URL: https://svn.apache.org/path/name/utf.h $ \$Id: utf.h 0 09/28/2005 dlydick $
+ *
+ * Copyright 2005 The Apache Software Foundation
+ * or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 ("the License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied.
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * @version \$LastChangedRevision: 0 $
+ *
+ * @date \$LastChangedDate: 09/28/2005 $
+ *
+ * @author \$LastChangedBy: dlydick $
+ *         Original code contributed by Daniel Lydick on 09/28/2005.
+ *
+ * @section Reference
+ *
+ */
+
+
+/* Prototypes for functions in 'utf.c' */
+
+ARCH_COPYRIGHT_APACHE(utf, h, "$URL: https://svn.apache.org/path/name/utf.h $ $Id: utf.h 0 09/28/2005 dlydick $");
+
+extern jshort utf_utf2unicode(CONSTANT_Utf8_info *utf_inbfr,
+                              jchar              *outbfr);
+
+extern rchar *utf_utf2prchar(CONSTANT_Utf8_info *src);
+
+extern rchar *utf_utf2prchar_classname(CONSTANT_Utf8_info *src);
+
+extern jbyte utf_utf_strcmp(CONSTANT_Utf8_info *s1,
+                            CONSTANT_Utf8_info *s2);
+
+extern jbyte utf_prchar_pcfs_strcmp(rchar                   *s1,
+                                    ClassFile               *pcfs,
+                                    jvm_constant_pool_index  cpidx2);
+
+extern jbyte utf_pcfs_strcmp(CONSTANT_Utf8_info      *s1,
+                             ClassFile               *pcfs,
+                             jvm_constant_pool_index  cpidx2);
+
+extern jbyte utf_prchar_classname_strcmp(rchar                  *s1,
+                                         ClassFile              *pcfs,
+                                        jvm_constant_pool_index cpidx2);
+
+extern jbyte utf_classname_strcmp(CONSTANT_Utf8_info      *s1,
+                                  ClassFile               *pcfs2,
+                                  jvm_constant_pool_index  cpidx2);
+
+extern jvm_array_dim utf_get_utf_arraydims(CONSTANT_Utf8_info *inbfr);
+
+extern rboolean utf_utf_isarray(CONSTANT_Utf8_info *inbfr);
+
+extern rboolean utf_utf_isclassformatted(CONSTANT_Utf8_info *src);
+
+extern cp_info_dup
+                 *utf_utf2utf_unformatted_classname(cp_info_dup *inbfr);
+
+#endif /* _utf_h_defined_ */
+
+
+/* EOF */

Added: incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/util.h
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/util.h?rev=307257&view=auto
==============================================================================
--- incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/util.h (added)
+++ incubator/harmony/enhanced/trunk/sandbox/contribs/bootjvm/bootJVM/jvm/src/util.h Fri Oct  7 21:27:56 2005
@@ -0,0 +1,241 @@
+#ifndef _util_h_defined_
+#define _util_h_defined_
+
+/*!
+ * @file util.h
+ *
+ * @brief Miscellaneous utility macros and function prototypes.
+ *
+ * Source files whose function prototypes are defined
+ * herein include:
+ *
+ *     @link jvm/src/argv.c argv.c@endlink
+ *
+ *     @link jvm/src/bytegames.c bytegames.c@endlink
+ *
+ *     @link jvm/src/classpath.c classpath.c@endlink
+ *
+ *     @link jvm/src/jvmutil.c jvm.c@endlink
+ *
+ *     @link jvm/src/manifest.c manifest.c@endlink
+ *
+ *     @link jvm/src/stdio.c stdio.c@endlink
+ *
+ *     @link jvm/src/timeslice.c timeslice.c@endlink
+ *
+ *     @link jvm/src/tmparea.c tmparea.c@endlink
+ *
+ * In order to separate the structure packing demands of
+ * <b><code>typedef struct {} ClassFile</code></b>, the
+ * following files will @e not have their prototypes
+ * defined here, even though they are utility functions:
+ * 
+ *     @link jvm/src/nts.c nts.c@endlink
+ *
+ *     @link jvm/src/unicode.c unicode.c@endlink
+ *
+ *     @link jvm/src/utf.c utf.c@endlink
+ *
+ *
+ * @section Control
+ *
+ * \$URL: https://svn.apache.org/path/name/util.h $ \$Id: util.h 0 09/28/2005 dlydick $
+ *
+ * Copyright 2005 The Apache Software Foundation
+ * or its licensors, as applicable.
+ *
+ * Licensed under the Apache License, Version 2.0 ("the License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
+ * either express or implied.
+ *
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * @version \$LastChangedRevision: 0 $
+ *
+ * @date \$LastChangedDate: 09/28/2005 $
+ *
+ * @author \$LastChangedBy: dlydick $
+ *         Original code contributed by Daniel Lydick on 09/28/2005.
+ *
+ * @section Reference
+ *
+ */
+
+ARCH_COPYRIGHT_APACHE(util, h, "$URL: https://svn.apache.org/path/name/util.h $ $Id: util.h 0 09/28/2005 dlydick $");
+
+
+/* Prototypes for functions in 'bytegames.c' */
+extern rushort bytegames_getrs2(rushort *ptr2);
+extern ruint   bytegames_getri4(ruint   *ptr4);
+extern rulong  bytegames_getrl8(rulong  *ptr8);
+
+extern rvoid   bytegames_putrs2(rushort *ptr2, rushort val2);
+extern rvoid   bytegames_putri4(ruint   *ptr4, ruint   val4);
+extern rvoid   bytegames_putrl8(rulong  *ptr8, rulong  val8);
+
+extern rushort bytegames_swap2(rushort val);
+extern ruint   bytegames_swap4(ruint   val);
+
+extern rulong  bytegames_swap8(rulong  val);
+extern rulong  bytegames_mix8(rulong   val);
+
+extern jlong   bytegames_combine_jlong(jint msword, jint lsword);
+extern jdouble bytegames_combine_jdouble(jint msword, jint lsword);
+
+extern rvoid bytegames_split_jlong(jlong splitlong,
+                                   jint *msword,
+                                   jint *lsword);
+extern rvoid bytegames_split_jdouble(jdouble  splitdouble,
+                                     jint    *msword,
+                                     jint    *lsword);
+/*!
+ * @todo  Make sure GETRI4() works with -m64 compilations (64-bit ptrs)
+ *
+ * @todo  Make sure GETRL8() works with -m64 compilations (64-bit ptrs)
+ *
+ *
+ * @internal See @link jvm/src/arch.h arch.h@endlink for the
+ * origin of architecture-specific @c @b \#define's as used below:
+ *
+ */
+#ifdef ARCH_ODD_ADDRESS_SIGSEGV
+#define GETRS2(ptr) bytegames_getrs2(ptr)
+#define GETRI4(ptr) bytegames_getri4(ptr)
+#define GETRL8(ptr) bytegames_getrl8(ptr)
+#else
+#ifdef ARCH_BIG_ENDIAN
+#define GETRS2(ptr) (*(signed rushort *) ptr)
+#define GETRI4(ptr) (*(signed ruint   *) ptr)
+#define GETRL8(ptr) (*(signed rulong  *) ptr)
+#else
+#define GETRS2(ptr) bytegames_getrs2(ptr)
+#define GETRI4(ptr) bytegames_getri4(ptr)
+#define GETRL8(ptr) bytegames_getrl8(ptr)
+#endif
+#endif
+
+
+#ifdef ARCH_LITTLE_ENDIAN
+
+#define MACHINE_JSHORT_SWAP(rsval) rsval = bytegames_swap2(rsval)
+#define MACHINE_JINT_SWAP(rival)   rival = bytegames_swap4(rival)
+#define MACHINE_JLONG_SWAP(rlval)  rlval = bytegames_swap8(rlval)
+#define MACHINE_JLONG_MIX(rlval)   rlval = bytegames_mix8(rlval)
+
+#define MACHINE_JSHORT_SWAP_PTR(prsval) *prsval = \
+                                             bytegames_swap2(*prsval)
+#define MACHINE_JINT_SWAP_PTR(prival)   *prival = \
+                                             bytegames_swap4(*prival)
+#define MACHINE_JLONG_SWAP_PTR(prlval)  *prlval = \
+                                             bytegames_swap8(*prlval)
+#define MACHINE_JLONG_MIX_PTR(prlval)   *prlval = \
+                                             bytegames_mix8(*prlval)
+
+#else
+
+/*!
+ * @internal Big endian architectures do not need to swap anything
+ * since the JVM spec declares its (short) and (int) structures
+ * as big endian.
+ *
+ */
+
+#define MACHINE_JSHORT_SWAP(p1)
+#define MACHINE_JINT_SWAP(p1)
+#define MACHINE_JLONG_SWAP(p1)
+#define MACHINE_JLONG_MIX(p1)
+
+#define MACHINE_JSHORT_SWAP_PTR(p1)
+#define MACHINE_JLONG_SWAP_PTR(p1)
+#define MACHINE_JLONG_MIX_PTR(p1)
+
+#endif
+
+
+/* Prototypes for functions in 'stdio.c' */
+
+#ifndef I_AM_STDIO_C
+extern rvoid sysDbgMsg(jvm_debug_level_enum dml,
+                       rchar *fn,
+                       rchar *fmt,
+                       ...);
+extern rvoid sysErrMsg(rchar *fn, rchar *fmt, ...);
+extern rvoid sysErrMsgBfrFormat(rchar *bfr, rchar *fn, rchar *fmt, ...);
+extern rvoid sprintfLocal(rchar *bfr, rchar *fmt, ...);
+extern rvoid fprintfLocalStderr(rchar *fmt, ...);
+extern rvoid fprintfLocalStdout(rchar *fmt, ...);
+#endif
+
+/*!
+ * @internal <b>DO NOT</b> (!) define prototypes for
+ * _printfLocal() or _fprintfLocal() or _sprintfLocal().
+ * They are meant to promote use of printfLocal() and
+ * fprintfLocal() and sprintfLocal() instead, so let
+ * compile warnings help.
+ *
+ */
+
+
+/* Prototypes for functions in 'argv.c' */
+
+extern rvoid argv_init(int argc, char **argv, char **envp);
+
+extern rvoid argv_shutdown(rvoid);
+
+extern rvoid argv_versionmsg(rvoid);
+
+extern rvoid argv_copyrightmsg(rvoid);
+
+extern rvoid argv_licensemsg(rvoid);
+
+extern rvoid argv_helpmsg(rvoid);
+
+extern rvoid argv_showmsg(rvoid);
+
+
+/* Prototypes for small utility functions in 'jvmutil.c' */
+
+extern rvoid                jvmutil_set_dml(jvm_debug_level_enum level);
+extern jvm_debug_level_enum jvmutil_get_dml(rvoid);
+
+extern rvoid jvmutil_print_stack(jvm_thread_index  thridx,
+                                 rchar            *pheader);
+extern rvoid jvmutil_print_stack_details(jvm_thread_index  thridx,
+                                         rchar            *pheader);
+extern rvoid jvmutil_print_stack_locals(jvm_thread_index  thridx,
+                                        rchar            *pheader);
+extern rvoid jvmutil_print_error_stack(jvm_thread_index thridx);
+extern rvoid jvmutil_print_exception_stack(jvm_thread_index thridx);
+
+
+/* Prototypes for functions in 'manifest.c' */
+
+extern rchar *manifest_get_main(rchar *mnfname);
+
+
+/* Prototypes for functions in 'timeslice.c' */
+
+extern rvoid timeslice_shutdown(rvoid);
+extern jlong timeslice_get_thread_sleeptime(jvm_thread_index thridx);
+extern void *timeslice_run(void *dummy);
+extern rvoid timeslice_init(rvoid);
+
+
+/* Prototypes for functions in 'tmparea.c' */
+
+extern rvoid tmparea_init(char **argv);
+extern const rchar *tmparea_get(rvoid);
+extern rvoid tmparea_shutdown(rvoid);
+
+#endif /* _util_h_defined_ */
+
+
+/* EOF */