// $Id: platform.cpp,v 1.47 2004/03/23 14:03:56 ericb Exp $
//
// This software is subject to the terms of the IBM Jikes Compiler
// License Agreement available at the following URL:
// http://ibm.com/developerworks/opensource/jikes.
// Copyright (C) 2000, 2004 IBM Corporation and others.  All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
//
// NOTE: The code for accurate conversions between floating point
// and decimal strings, in double.h, double.cpp, platform.h, and
// platform.cpp, is adapted from dtoa.c.  The original code can be
// found at http://netlib2.cs.utk.edu/fp/dtoa.c.
//
// The code in dtoa.c is copyrighted as follows:
//****************************************************************
//*
//* The author of this software is David M. Gay.
//*
//* Copyright (c) 1991, 2000, 2001 by Lucent Technologies.
//*
//* Permission to use, copy, modify, and distribute this software for any
//* purpose without fee is hereby granted, provided that this entire notice
//* is included in all copies of any software which is or includes a copy
//* or modification of this software and in all copies of the supporting
//* documentation for such software.
//*
//* THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED
//* WARRANTY.  IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY
//* REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY
//* OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE.
//*
//***************************************************************/
//
//

#include "platform.h"
#include "long.h"
#include "double.h"

#ifdef HAVE_JIKES_NAMESPACE
namespace Jikes { // Open namespace Jikes block
#endif

// Define the PathSeparator() function with the proper
// impl for each platform.

#ifdef HAVE_PATHNAME_STYLE_DOS
char PathSeparator() { return U_SEMICOLON; } // ";"
#else
char PathSeparator() { return U_COLON; } // ":"
#endif // ! HAVE_PATHNAME_STYLE_DOS


// Define the SystemMkdir() function with the proper
// impl for each platform.

int SystemMkdir(char* dirname)
{
#ifdef HAVE_GLIBC_MKDIR
    return mkdir(dirname, S_IRWXU | S_IRWXG | S_IRWXO);
#endif // HAVE_GLIBC_MKDIR

#ifdef HAVE_LIBC5_MKDIR
    reteurn mkdir(dirname, S_IRWXU);
#endif // HAVE_LIBC5_MKDIR

#ifdef HAVE_WIN32_MKDIR
    return mkdir(dirname);
#endif // HAVE_WIN32_MKDIR

#ifdef HAVE_MAC_MKDIR
    return mkdir(dirname, 0);
#endif // HAVE_MAC_MKDIR
    assert(false);
    return 0;
}

//
// The configure script checks each of these to see if we need our own
// implementation.
//
#ifndef HAVE_WCSLEN
size_t wcslen(const wchar_t* cs)
{
    int n = 0;
    while (*cs++)
        n++;
    return n;
}
#endif // HAVE_WCSLEN

#ifndef HAVE_WCSCPY
wchar_t* wcscpy(wchar_t* s, const wchar_t* ct)
{
    wchar_t* ptr;
    for (ptr = s; *ct; ptr++, ct++)
        *ptr = *ct;
    *ptr = U_NULL;
    return s;
}
#endif // HAVE_WCSCPY

#ifndef HAVE_WCSNCPY
wchar_t* wcsncpy(wchar_t* s, const wchar_t* ct, size_t n)
{
    wchar_t* ptr;
    for (ptr = s; *ct && n-- > 0; ptr++, ct++)
        *ptr = *ct;
    while (n-- > 0)
        *ptr++ = U_NULL;
    return s;
}
#endif // HAVE_WCSNCPY

#ifndef HAVE_WCSCAT
wchar_t* wcscat(wchar_t* s, const wchar_t* ct)
{
    wchar_t* ptr = s;
    while (*ptr)
        ptr++;
    wcscpy(ptr, ct);
    return s;
}
#endif // HAVE_WCSCAT

#ifndef HAVE_WCSCMP
int wcscmp(const wchar_t* cs, const wchar_t* ct)
{
    while (*cs == *ct && *cs && *ct)
    {
        cs++;
        ct++;
    }
    return (*cs == *ct ? 0 : (*cs < *ct ? -1 : 1));
}
#endif // HAVE_WCSCMP

#ifndef HAVE_WCSNCMP
int wcsncmp(const wchar_t* cs, const wchar_t* ct, size_t n)
{
    while (*cs == *ct && *cs && *ct && n-- > 0)
    {
        cs++;
        ct++;
    }
    return (n <= 0 || *cs == *ct ? 0 : (*cs < *ct ? -1 : 1));
}
#endif // HAVE_WCSNCMP


//
// If the system runs out of memory, this function is invoked
// This is tricky because VC++ on windows uses a non standard
// implementation of the set_new_handler function.
//
#ifdef HAVE_VCPP_SET_NEW_HANDLER
int OutOfMemory(size_t)
#else
void OutOfMemory()
#endif // ! HAVE_VCPP_SET_NEW_HANDLER
{
    fprintf(stderr, "***System Failure: Out of memory\n");
    exit(1);
#ifdef HAVE_VCPP_SET_NEW_HANDLER
    return 0;
#endif // HAVE_VCPP_SET_NEW_HANDLER
}

void SetNewHandler()
{
#ifdef HAVE_VCPP_SET_NEW_HANDLER
    _set_new_handler(OutOfMemory);
#else
    set_new_handler(OutOfMemory);
#endif // ! HAVE_VCPP_SET_NEW_HANDLER
}


//
// When using the ICC compiler on Win95 or OS/2, we need to disable
// testing for various floating point exceptions. Default behavior
// was causing problems reading some standard class files.
//
// We obviously don't need this on AIX (non x86), which uses xlC/ICC
//
void FloatingPointCheck()
{
#ifdef HAVE_ICC_FP_BUGS
    _control87(EM_UNDERFLOW, EM_UNDERFLOW);
    _control87(EM_ZERODIVIDE, EM_ZERODIVIDE);
    _control87(EM_OVERFLOW, EM_OVERFLOW);
    _control87(EM_INVALID, EM_INVALID);
#endif // HAVE_ICC_FP_BUGS
}


//
// This next set of functions may need some porting to work on various systems
//
int SystemStat(const char* name, struct stat* stat_struct)
{
    int result = ::stat(name, stat_struct);
#ifdef HAVE_SYS_CYGWIN_H
    //
    // Up through cygwin 1.3.10, the hash function which determines inodes
    // was not strong enough, so java/net and java/nio occasionally get the
    // same inode without this hack.
    //
    if (result == 0)
        stat_struct -> st_ino += name[strlen(name) - 1];
#endif // HAVE_SYS_CYGWIN_H
    return result;
}

FILE* SystemFopen(const char* name, const char* mode)
{
    return fopen(name, mode);
}

size_t SystemFread(char* ptr, size_t element_size, size_t count, FILE* stream)
{
    return fread(ptr, element_size, count, stream);
}

int SystemIsDirectory(char* name)
{
    struct stat status;
    return ((SystemStat(name, &status) == 0 &&
             (status.st_mode & JIKES_STAT_S_IFDIR)) ? 1 : 0);
}

int SystemMkdirhier(char* dirname)
{
    if (SystemIsDirectory(dirname))
        return 0;

    for (char* ptr = dirname; *ptr; ptr++)
    {
        char delimiter = *ptr;
        if (delimiter == U_SLASH)
        {
            *ptr = U_NULL;
            if (! SystemIsDirectory(dirname))
                SystemMkdir(dirname);
            *ptr = delimiter;
        }
    }
    SystemMkdir(dirname);
    return (! SystemIsDirectory(dirname));
}


// Create the specified directory and also any missing parent directories.
int SystemMkdirhierForFile(char* filename)
{
    for (int i = strlen(filename); i >= 0; i--)
    {
        if (filename[i] == U_SLASH)
        {
            int result = 0;
            filename[i] = U_NULL;
            if (! SystemIsDirectory(filename))
            {
                Ostream() << "making directory " << filename << "\n";
                result = SystemMkdirhier(filename);
            }
            filename[i] = U_SLASH;
            return result;
        }
    }
    return 0;
}


// FIXME: These next two should definitely be inlined; but when I
// add the "inline" keyword , I get linker problems.


// Given three strings, return a newly-allocated string which is their
// concatenation.
char* strcat3(const char* prefix, const char* middle, const char* suffix)
{
    int prefix_len = strlen(prefix);
    int prefix_middle_len = prefix_len + strlen(middle);

    char* result = new char[prefix_middle_len + strlen(suffix) + 1];
    strcpy(result, prefix);
    // The below is more efficient than this commented-out code.
    // strcat(result, middle);
    // strcat(result, suffix);
    strcpy(result + prefix_len, middle);
    strcpy(result + prefix_middle_len, suffix);
    return result;
}

// It's inconceivable that this is the right way to go about this.
// One alternative is to use ConvertUnicodeToUtf8.
char* wstring2string(wchar_t* in)
{
    char* result = new char[wcslen(in) + 1];
    result[wcslen(in)] = 0;
    for (size_t i=0; i<wcslen(in); i++) {
        wchar_t ch = in[i];
        result[i] = (ch >> 8 == 0 ? (char)ch : '?');
    }
    return result;
}


// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//
// End of platform specific defines in this file, the rest of the code
// in this file should work on any system
//
// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


IntToString::IntToString(i4 num)
{
    str = &info[TAIL_INDEX];
    *str = U_NULL;
    u4 n = num < 0 ? - num : num;
    do
    {
        *--str = U_0 + n % 10;
        n /= 10;
    } while (n != 0);
    if (num < 0)
        *--str = U_MINUS;
}

IntToString::IntToString(u4 num, int width)
{
    str = &info[width];
    *str = U_NULL;
    do
    {
        char c = num & 0xf;
        *--str = c < 10 ? U_0 + c : U_a - 10 + c;
        num >>= 4;
    } while (str != info);
}


IntToWstring::IntToWstring(i4 num)
{
    wstr = &winfo[TAIL_INDEX];
    *wstr = U_NULL;
    u4 n = num < 0 ? - num : num;
    do
    {
        *--wstr = U_0 + n % 10;
        n /= 10;
    } while (n != 0);
    if (num < 0)
        *--wstr = U_MINUS;
}


LongToString::LongToString(const LongInt& num)
{
    str = &info[TAIL_INDEX];
    *str = U_NULL;
    ULongInt n = num < 0 ? (ULongInt) - num : (ULongInt) num;
    do
    {
        *--str = U_0 + (n % 10).LowWord();
        n /= 10;
    } while (n != 0);
    if (num.HighWord() & 0x80000000)
        *--str = U_MINUS;
    base = str;
}

LongToString::LongToString(const ULongInt& num)
{
    str = &info[TAIL_INDEX];
    *str = U_NULL;
    ULongInt n = num;
    do
    {
        *--str = U_0 + (n % 10).LowWord();
        n /= 10;
    } while (n != 0);
    base = str;
}

LongToString::LongToString(const BaseLong& num, bool octal)
{
    str = &info[TAIL_INDEX];
    *str = U_NULL;
    ULongInt value = num;
    do
    {
        char c = value.LowWord() & (octal ? 7 : 0xf);
        *--str = c < 10 ? U_0 + c : U_a - 10 + c;
        value >>= (octal ? 3 : 4);
    } while (value != 0);
    base = str - 1;
    if (! octal)
        *base-- = U_x;
    *base = U_0;
}


//
// Convert an double to its character string representation.
//
FloatToString::FloatToString(const IEEEfloat& f)
{
    int bbits, b2, b5, be, i,
        j, j1, k, m2, m5, s2, s5;
    bool neg,      // f is negative
        k_check,   // need to check if k is near power of ten
        spec_case, // f is normalized power of two
        denorm,    // f is denormalized
        round;     // round trailing 9's up
    IEEEfloat fs, f1;
    char* s;
    char dig;

    //
    // Start with exceptional cases: zero, infinity, NaN
    //
    neg = f.IsNegative();
    if (f.IsNaN())
    {
        strcpy(str, StringConstant::U8S_NaN);
        length = strlen(str);
        return;
    }
    else if (f.IsInfinite())
    {
        if (neg)
            strcpy(str, StringConstant::U8S_neg_Infinity);
        else
            strcpy(str, StringConstant::U8S_pos_Infinity);
        length = strlen(str);
        return;
    }
    else if (f.IsZero())
    {
        if (neg)
            strcpy(str, StringConstant::U8S_neg_Zero);
        else
            strcpy(str, StringConstant::U8S_pos_Zero);
        length = strlen(str);
        return;
    }

    //
    // Create BigInt holding f.
    // bbits = # significant bits in f
    // be = log2(least significant bit)
    // i = log2(most significant bit)
    // f1 = mantissa of f
    // Therefore, f == f1 * 2**i, and i == be + bbits - 1.
    //
    s = str;
    BigInt b(f, be, bbits);
    u4 x;
    i = f.SplitInto(x);
    f1 = IEEEfloat((i4) x) / (1 << IEEEfloat::FractSize());
    denorm = i <= -IEEEfloat::Bias();
    //
    // log(x)   ~=~ log(1.5) + (x-1.5)/1.5
    // log10(x)  =  log(x) / log(10)
    //          ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
    // log10(f)  =  log10(f1 * 2**i)
    //           =  i*log10(2) + log10(f1)
    //
    // This suggests computing an approximation k to log10(f) by
    //
    // k = i*0.30103 + ( 0.17609125 + (f1-1.5)*0.28952965 );
    //
    // We want k to be too large rather than too small.
    // The error in the first-order Taylor series approximation
    // is in our favor, so we just round up the constant enough
    // to compensate for any error in the multiplication of
    // i by 0.30103; since |i| <= 152,
    // and 152 * 0.30103 * 2^-23 ~=~ 5.5e-6,
    // adding 1e-5 to the constant term more than suffices.
    // Hence we adjust the constant term to 0.1761.
    // (We could get a more accurate k by invoking log10,
    //  but this is probably not worthwhile.)
    //
    fs = IEEEfloat(i) * 0.30103f + 0.1761f + (f1 - 1.5f) * 0.28952965f;
    k = fs.IntValue();
    f1 = f.IsNegative() ? -f : f;
    k_check = true;
    if (fs < 0 && fs != k)
        k--;
    else if (k >= 0 && k <= 10)
    {
        if (f1 < IEEEfloat::tens[k])
            k--;
        k_check = false;
    }

    //
    // We have an integer (no fraction) represented in 24 bits.
    // For this special case, math on floats has no rounding errors.
    //
    if (be >= 0 && k <= 6)
    {
        fs = IEEEfloat::tens[k];
        do
        {
            dig = (char) (f1 / fs).IntValue();
            f1 -= fs * (i4) dig;
            *s++ = U_0 + dig;
        } while ((f1 *= 10) != 0);
        Format(s, k, neg);
        return;
    }

    //
    // Begin work. Find S = 2**s2 * 5**s5, and b adjustment 2**b2 * 5**b5,
    // that will be needed later on.
    //
    if (be <= 0)
    {
        b2 = 0;
        s2 = -be;
    }
    else
    {
        b2 = be;
        s2 = 0;
    }
    if (k >= 0)
    {
        b5 = 0;
        s5 = k;
        s2 += k;
    }
    else
    {
        b2 -= k;
        b5 = -k;
        s5 = 0;
    }

    m2 = b2;
    m5 = b5;
    i = denorm ? be + IEEEfloat::Bias() + IEEEfloat::FractSize()
               : 2 + IEEEfloat::FractSize() - bbits;
    b2 += i;
    s2 += i;
    BigInt mhi(1);
    if (m2 > 0 && s2 > 0)
    {
        i = m2 < s2 ? m2 : s2;
        b2 -= i;
        m2 -= i;
        s2 -= i;
    }
    if (b5 > 0)
    {
        if (m5 > 0)
        {
            mhi.pow5mult(m5);
            b *= mhi;
        }
        if ((j = b5 - m5) != 0)
            b.pow5mult(j);
    }
    BigInt S(1);
    if (s5 > 0)
        S.pow5mult(s5);
    spec_case = false;
    if (! (f.FractBits()) && f.Exponent())
    {
        b2++;
        s2++;
        spec_case = true;
    }

    // Arrange for convenient computation of quotients:
    // shift left if necessary so divisor has 4 leading 0 bits.
    //
    // Perhaps we should just compute leading 28 bits of S once
    // and for all and pass them and a shift to quorem, so it
    // can do shifts and ors to compute the numerator for q.
    //
    if ((i = ((s5 ? 32 - S.hi0bits() : 1) + s2) & 0x1f) != 0)
        i = 32 - i;
    if (i > 4)
    {
        i -= 4;
        b2 += i;
        m2 += i;
        s2 += i;
    }
    else if (i < 4)
    {
        i += 28;
        b2 += i;
        m2 += i;
        s2 += i;
    }
    if (b2 > 0)
        b <<= b2;
    if (s2 > 0)
        S <<= s2;
    if (k_check && b.compareTo(S) < 0)
    {
        k--;
        b *= 10;
        mhi *= 10;
    }
    if (m2 > 0)
        mhi <<= m2;
    BigInt mlo(mhi);
    if (spec_case)
        mhi = mlo << 1;
    round = false;
    while (true)
    {
        dig = (char) b.quorem(S) + U_0;
        //
        // Do we have the shortest decimal string that will round to f?
        //
        j = b.compareTo(mlo);
        BigInt delta = S - mhi;
        j1 = delta.IsNegative() ? 1 : b.compareTo(delta);
        if (j1 == 0 && ! (f.value.word & 1))
        {
            if (dig == U_9)
                round = true;
            else if (j > 0)
                dig++;
            *s++ = dig;
            break;
        }
        if ((j < 0 || j == 0 && ! (f.value.word & 1)) && s != str)
        {
            if (! b.IsZero() && j1 > 0)
            {
                b <<= 1;
                j1 = b.compareTo(S);
                if ((j1 > 0 || j1 == 0 && dig & 1) && dig++ == U_9)
                {
                    *s++ = U_9;
                    round = true;
                    break;
                }
            }
            *s++ = dig;
            break;
        }
        if (j1 > 0 && s != str)
        {
            if (dig == U_9)
            {
                *s++ = U_9;
                round = true;
            }
            else
                *s++ = dig + 1;
            break;
        }
        *s++ = dig;
        b *= 10;
        mlo *= 10;
        mhi *= 10;
    }
    if (round)
    {
        while (*--s == U_9)
            if (s == str)
            {
                k++;
                *s = U_0;
                break;
            }
        ++*s++;
    }
    Format(s, k, neg);
}

void FloatToString::Format(char* s, int exp, bool neg)
{
    //
    // at this point, str contains just the precise digits in the answer,
    // and s points to the slot just after the last digit
    //
    length = s - str + 1; // strlen(str) + '.'
    bool eneg;
    int i;
    switch (exp)
    {
    case -3: case -2: case -1:
        // remove final trailing 0, not needed in this format
        if (*(s - 1) == U_0)
        {
            length--;
            s--;
        }
        s--;
        // add enough of leading "0.00"
        length += -exp;
        do
            *(s + (neg ? 2 : 1) - exp) = *s;
        while (s-- != str);
        for (i = (neg ? 1 : 0); i < (neg ? 2 : 1) - exp; i++)
            str[i] = U_0;
        if (neg)
            str[0] = U_MINUS;
        str[neg ? 2 : 1] = U_DOT;
        break;
    case 0: case 1: case 2: case 3:
    case 4: case 5: case 6:
        while (length < exp + 3)
            // add trailing '0's
            str[length++ - 1] = U_0;
        s = &str[length - 2];
        do
            *(s + (neg ? 2 : 1)) = *s;
        while (s-- != str + exp + 1);
        if (neg)
        {
            do
                *(s + 1) = *s;
            while (s-- != str);
            str[0] = U_MINUS;
        }
        str[exp + (neg ? 2 : 1)] = U_DOT;
        break;
    default:
        if (length == 2)
            // add trailing '0', so at least one digit follows '.'
            str[length++ - 1] = U_0;
        eneg = exp < 0;
        if (eneg)
        {
            length++; // exponent '-'
            exp = -exp;
        }
        if (exp < 10)
            length += 2; // 'E' + 1 digit exponent
        else if (exp < 100)
            length += 3; // 'E' + 2 digit exponent
        else
            assert (! "unexpected exponent");
        s = &str[length + (neg ? 1 : 0)];
        do
            *--s = exp % 10 + U_0;
        while ((exp /= 10) != 0);
        if (eneg)
            *--s = U_MINUS;
        *--s = U_E;
        --s;
        do
            *s = *(s - (neg ? 2 : 1)); // shift digits right, to add '.'
        while (--s != str + (neg ? 2 : 1));
        if (neg)
        {
            str[1] = str[0];
            str[0] = U_MINUS;
        }
        str[neg ? 2 : 1] = U_DOT;
    }
    if (neg)
        length++;
    str[length] = U_NULL;
    assert(length <= MAXIMUM_STR_LENGTH);
}


//
// Convert an double to its character string representation.
//
DoubleToString::DoubleToString(const IEEEdouble& d)
{
    int bbits, b2, b5, be, i,
        j, j1, k, m2, m5, s2, s5;
    bool neg,      // f is negative
        k_check,   // need to check if k is near power of ten
        spec_case, // f is normalized power of two
        denorm,    // f is denormalized
        round;     // round trailing 9's up
    IEEEdouble ds, d1;
    char* s;
    char dig;

    //
    // Start with exceptional cases: zero, infinity, NaN
    //
    neg = d.IsNegative();
    if (d.IsNaN())
    {
        strcpy(str, StringConstant::U8S_NaN);
        length = strlen(str);
        return;
    }
    else if (d.IsInfinite())
    {
        if (neg)
            strcpy(str, StringConstant::U8S_neg_Infinity);
        else
            strcpy(str, StringConstant::U8S_pos_Infinity);
        length = strlen(str);
        return;
    }
    else if (d.IsZero())
    {
        if (neg)
            strcpy(str, StringConstant::U8S_neg_Zero);
        else
            strcpy(str, StringConstant::U8S_pos_Zero);
        length = strlen(str);
        return;
    }

    //
    // Create BigInt holding d.
    // bbits = # significant bits in d
    // be = log2(least significant bit)
    // i = log2(most significant bit)
    // d1 = mantissa of d
    // Therefore, d == d1 * 2**i, and i == be + bbits - 1.
    //
    s = str;
    BigInt b(d, be, bbits);
    LongInt x;
    i = d.SplitInto(x);
    d1 = IEEEdouble(x) /
        IEEEdouble(LongInt(LongInt(1) << IEEEdouble::FractSize()));
    denorm = i <= -IEEEdouble::Bias();
    //
    // log(x)   ~=~ log(1.5) + (x-1.5)/1.5
    // log10(x)  =  log(x) / log(10)
    //          ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10))
    // log10(d)  =  log10(d2 * 2**i)
    //           =  i*log10(2) + log10(d2)
    //
    // This suggests computing an approximation k to log10(d) by
    //
    // k = i*0.301029995663981
    //   + ( 0.176091259055681 + (d2-1.5)*0.289529654602168 );
    //
    // We want k to be too large rather than too small.
    // The error in the first-order Taylor series approximation
    // is in our favor, so we just round up the constant enough
    // to compensate for any error in the multiplication of
    // i by 0.301029995663981; since |i| <= 1077,
    // and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14,
    // adding 1e-13 to the constant term more than suffices.
    // Hence we adjust the constant term to 0.1760912590558.
    // (We could get a more accurate k by invoking log10,
    //  but this is probably not worthwhile.)
    //
    ds = IEEEdouble(i) * 0.301029995663981 + 0.1760912590558
        + (d1 - 1.5) * 0.289529654602168;
    k = ds.IntValue();
    d1 = d.IsNegative() ? -d : d;
    k_check = true;
    if (ds < 0 && ds != k)
        k--;
    else if (k >= 0 && k <= 22)
    {
        if (d1 < IEEEdouble::tens[k])
            k--;
        k_check = false;
    }

    //
    // We have an integer (no fraction) represented in 53 bits.
    // For this special case, math on doubles has no rounding errors.
    //
    if (be >= 0 && k <= 14)
    {
        ds = IEEEdouble::tens[k];
        do
        {
            dig = (char) (d1 / ds).IntValue();
            d1 -= ds * (i4) dig;
            *s++ = U_0 + dig;
        } while ((d1 *= 10) != 0);
        Format(s, k, neg);
        return;
    }

    //
    // Begin work. Find S = 2**s2 * 5**s5, and b adjustment 2**b2 * 5**b5,
    // that will be needed later on.
    //
    if (be <= 0)
    {
        b2 = 0;
        s2 = -be;
    }
    else
    {
        b2 = be;
        s2 = 0;
    }
    if (k >= 0)
    {
        b5 = 0;
        s5 = k;
        s2 += k;
    }
    else
    {
        b2 -= k;
        b5 = -k;
        s5 = 0;
    }

    m2 = b2;
    m5 = b5;
    i = denorm ? be + IEEEdouble::Bias() + IEEEdouble::FractSize()
               : 2 + IEEEdouble::FractSize() - bbits;
    b2 += i;
    s2 += i;
    BigInt mhi(1);
    if (m2 > 0 && s2 > 0)
    {
        i = m2 < s2 ? m2 : s2;
        b2 -= i;
        m2 -= i;
        s2 -= i;
    }
    if (b5 > 0)
    {
        if (m5 > 0)
        {
            mhi.pow5mult(m5);
            b *= mhi;
        }
        if ((j = b5 - m5) != 0)
            b.pow5mult(j);
    }
    BigInt S(1);
    if (s5 > 0)
        S.pow5mult(s5);
    spec_case = false;
    if (! (d.FractBits()) && d.Exponent())
    {
        b2++;
        s2++;
        spec_case = true;
    }

    // Arrange for convenient computation of quotients:
    // shift left if necessary so divisor has 4 leading 0 bits.
    //
    // Perhaps we should just compute leading 28 bits of S once
    // and for all and pass them and a shift to quorem, so it
    // can do shifts and ors to compute the numerator for q.
    //
    if ((i = ((s5 ? 32 - S.hi0bits() : 1) + s2) & 0x1f) != 0)
        i = 32 - i;
    if (i > 4)
    {
        i -= 4;
        b2 += i;
        m2 += i;
        s2 += i;
    }
    else if (i < 4)
    {
        i += 28;
        b2 += i;
        m2 += i;
        s2 += i;
    }
    if (b2 > 0)
        b <<= b2;
    if (s2 > 0)
        S <<= s2;
    if (k_check && b.compareTo(S) < 0)
    {
        k--;
        b *= 10;
        mhi *= 10;
    }
    if (m2 > 0)
        mhi <<= m2;
    BigInt mlo(mhi);
    if (spec_case)
        mhi = mlo << 1;
    round = false;
    while (true)
    {
        dig = (char) b.quorem(S) + U_0;
        //
        // Do we have the shortest decimal string that will round to d?
        //
        j = b.compareTo(mlo);
        BigInt delta = S - mhi;
        j1 = delta.IsNegative() ? 1 : b.compareTo(delta);
        if (j1 == 0 && ! (d.LowWord() & 1))
        {
            if (dig == U_9)
                round = true;
            else if (j > 0)
                dig++;
            *s++ = dig;
            break;
        }
        if ((j < 0 || j == 0 && ! (d.LowWord() & 1)) && s != str)
        {
            if (! b.IsZero() && j1 > 0)
            {
                b <<= 1;
                j1 = b.compareTo(S);
                if ((j1 > 0 || j1 == 0 && dig & 1) && dig++ == U_9)
                {
                    *s++ = U_9;
                    round = true;
                    break;
                }
            }
            *s++ = dig;
            break;
        }
        if (j1 > 0 && s != str)
        {
            if (dig == U_9)
            {
                *s++ = U_9;
                round = true;
            }
            else
                *s++ = dig + 1;
            break;
        }
        *s++ = dig;
        b *= 10;
        mlo *= 10;
        mhi *= 10;
    }
    if (round)
    {
        while (*--s == U_9)
            if (s == str)
            {
                k++;
                *s = U_0;
                break;
            }
        ++*s++;
    }
    Format(s, k, neg);
}

void DoubleToString::Format(char* s, int exp, bool neg)
{
    //
    // at this point, str contains just the precise digits in the answer,
    // and s points to the slot just after the last digit
    //
    length = s - str + 1; // strlen(str) + '.'
    bool eneg;
    int i;
    switch (exp)
    {
    case -3: case -2: case -1:
        // remove final trailing 0, not needed in this format
        if (*(s - 1) == U_0)
        {
            length--;
            s--;
        }
        s--;
        // add enough of leading "0.00"
        length += -exp;
        do
            *(s + (neg ? 2 : 1) - exp) = *s;
        while (s-- != str);
        for (i = (neg ? 1 : 0); i < (neg ? 2 : 1) - exp; i++)
            str[i] = U_0;
        if (neg)
            str[0] = U_MINUS;
        str[neg ? 2 : 1] = U_DOT;
        break;
    case 0: case 1: case 2: case 3:
    case 4: case 5: case 6:
        while (length < exp + 3)
            // add trailing '0's
            str[length++ - 1] = U_0;
        s = &str[length - 2];
        do
            *(s + (neg ? 2 : 1)) = *s;
        while (s-- != str + exp + 1);
        if (neg)
        {
            do
                *(s + 1) = *s;
            while (s-- != str);
            str[0] = U_MINUS;
        }
        str[exp + (neg ? 2 : 1)] = U_DOT;
        break;
    default:
        if (length == 2)
            // add trailing '0', so at least one digit follows '.'
            str[length++ - 1] = U_0;
        eneg = exp < 0;
        if (eneg)
        {
            length++; // exponent '-'
            exp = -exp;
        }
        if (exp < 10)
            length += 2; // 'E' + 1 digit exponent
        else if (exp < 100)
            length += 3; // 'E' + 2 digit exponent
        else if (exp < 1000)
            length += 4; // 'E' + 3 digit exponent
        else
            assert (! "unexpected exponent");
        s = &str[length + (neg ? 1 : 0)];
        do
            *--s = exp % 10 + U_0;
        while ((exp /= 10) != 0);
        if (eneg)
            *--s = U_MINUS;
        *--s = U_E;
        --s;
        do
            *s = *(s - (neg ? 2 : 1)); // shift digits right, to add '.'
        while (--s != str + (neg ? 2 : 1));
        if (neg)
        {
            str[1] = str[0];
            str[0] = U_MINUS;
        }
        str[neg ? 2 : 1] = U_DOT;
    }
    if (neg)
        length++;
    str[length] = U_NULL;
    assert(length <= MAXIMUM_STR_LENGTH);
}


Ostream& Ostream::operator<<(LongInt a)
{
    if (os -> flags() & os -> dec)
    {
        LongToString long_int(a);
        *os << long_int.String();
    }
    else if (os -> flags() & os -> oct)
    {
        LongToString long_int(a, true);
        *os << (os -> flags() & os -> showbase
                ? long_int.StringWithBase() : long_int.String());
    }
    else if (os -> flags() & os -> hex)
    {
        LongToString long_int(a, false);
        *os << (os -> flags() & os -> showbase
                ? long_int.StringWithBase() : long_int.String());
    }
    else
    {
         os -> flush();
         assert(false && "invalid format for printing signed long");
    }

    return *this;
}

Ostream& Ostream::operator<<(ULongInt a)
{
    if (os -> flags() & os -> dec)
    {
        LongToString ulong_int(a);
        *os << ulong_int.String();
    }
    else if (os -> flags() & os -> oct)
    {
        LongToString ulong_int(a, true);
        *os << (os -> flags() & os -> showbase
                ? ulong_int.StringWithBase() : ulong_int.String());
    }
    else if (os -> flags() & os -> hex)
    {
        LongToString ulong_int(a, false);
        *os << (os -> flags() & os -> showbase
                ? ulong_int.StringWithBase() : ulong_int.String());
    }
    else
    {
        os -> flush();
        assert(false && "invalid format for printing unsigned long");
    }

    return *this;
}

//
// Punctuation and operators
//
const wchar_t StringConstant::US_AND[] = {U_AM, U_NU}; // L"&"
const wchar_t StringConstant::US_AND_AND[] = {U_AM, U_AM, U_NU}; // L"&&"
const wchar_t StringConstant::US_AND_EQUAL[] = {U_AM, U_EQ, U_NU}; // L"&="
const wchar_t StringConstant::US_AT[] = {U_AT, U_NU}; // L"@"
const wchar_t StringConstant::US_COLON[] = {U_CO, U_NU}; // L":"
const wchar_t StringConstant::US_COMMA[] = {U_CM, U_NU}; // L","
const wchar_t StringConstant::US_DIVIDE[] = {U_SL, U_NU}; // L"/"
const wchar_t StringConstant::US_DIVIDE_EQUAL[] = {U_SL, U_EQ, U_NU}; // L"/="
const wchar_t StringConstant::US_DOT[] = {U_DO, U_NU}; // L"."
const wchar_t StringConstant::US_DOT_DOT_DOT[] = {
    U_DO, U_DO, U_DO, U_NU}; // L"..."
const wchar_t StringConstant::US_EMPTY[] = {U_NU}; // L""
const wchar_t StringConstant::US_EOF[] = {U_E, U_O, U_F, U_NU}; // L"EOF"
const wchar_t StringConstant::US_EQUAL[] = {U_EQ, U_NU}; // L"="
const wchar_t StringConstant::US_EQUAL_EQUAL[] = {U_EQ, U_EQ, U_NU}; // L"=="
const wchar_t StringConstant::US_GREATER[] = {U_GT, U_NU}; // L">"
const wchar_t StringConstant::US_GREATER_EQUAL[] = {U_GT, U_EQ, U_NU}; // L">="
const wchar_t StringConstant::US_LBRACE[] = {U_OS, U_NU}; // L"{"
const wchar_t StringConstant::US_LBRACKET[] = {U_LB, U_NU}; // L"["
const wchar_t StringConstant::US_LEFT_SHIFT[] = {U_LT, U_LT, U_NU}; // L"<<"
const wchar_t StringConstant::US_LEFT_SHIFT_EQUAL[] = {
    U_LT, U_LT, U_EQ, U_NU}; // L"<<="
const wchar_t StringConstant::US_LESS[] = {U_LT, U_NU}; // L"<"
const wchar_t StringConstant::US_LESS_EQUAL[] = {U_LT, U_EQ, U_NU}; // L"<="
const wchar_t StringConstant::US_LPAREN[] = {U_LP, U_NU}; // L"("
const wchar_t StringConstant::US_MINUS[] = {U_MI, U_NU}; // L"-"
const wchar_t StringConstant::US_MINUS_EQUAL[] = {U_MI, U_EQ, U_NU}; // L"-="
const wchar_t StringConstant::US_MINUS_MINUS[] = {U_MI, U_MI, U_NU}; // L"--"
const wchar_t StringConstant::US_MULTIPLY[] = {U_ST, U_NU}; // L"*"
const wchar_t StringConstant::US_MULTIPLY_EQUAL[] = {
    U_ST, U_EQ, U_NU}; // L"*="
const wchar_t StringConstant::US_NOT[] = {U_EX, U_NU}; // L"!"
const wchar_t StringConstant::US_NOT_EQUAL[] = {U_EX, U_EQ, U_NU}; // L"!="
const wchar_t StringConstant::US_OR[] = {U_BA, U_NU}; // L"|"
const wchar_t StringConstant::US_OR_EQUAL[] = {U_BA, U_EQ, U_NU}; // L"|="
const wchar_t StringConstant::US_OR_OR[] = {U_BA, U_BA, U_NU}; // L"||"
const wchar_t StringConstant::US_PLUS[] = {U_PL, U_NU}; // L"+"
const wchar_t StringConstant::US_PLUS_EQUAL[] = {U_PL, U_EQ, U_NU}; // L"+="
const wchar_t StringConstant::US_PLUS_PLUS[] = {U_PL, U_PL, U_NU}; // L"++"
const wchar_t StringConstant::US_QUESTION[] = {U_QU, U_NU}; // L"?"
const wchar_t StringConstant::US_RBRACE[] = {U_CS, U_NU}; // L"}"
const wchar_t StringConstant::US_RBRACKET[] = {U_RB, U_NU}; // L"]"
const wchar_t StringConstant::US_REMAINDER[] = {U_PE, U_NU}; // L"%"
const wchar_t StringConstant::US_REMAINDER_EQUAL[] = {
    U_PE, U_EQ, U_NU}; // L"%="
const wchar_t StringConstant::US_RIGHT_SHIFT[] = {U_GT, U_GT, U_NU}; // L">>"
const wchar_t StringConstant::US_RIGHT_SHIFT_EQUAL[] = {
    U_GT, U_GT, U_EQ, U_NU}; // L">>="
const wchar_t StringConstant::US_RPAREN[] = {U_RP, U_NU}; // L")"
const wchar_t StringConstant::US_SEMICOLON[] = {U_SC, U_NU}; // L";"
const wchar_t StringConstant::US_TWIDDLE[] = {U_TI, U_NU}; // L"~"
const wchar_t StringConstant::US_UNSIGNED_RIGHT_SHIFT[] = {
    U_GT, U_GT, U_GT, U_NU}; // L">>>"
const wchar_t StringConstant::US_UNSIGNED_RIGHT_SHIFT_EQUAL[] = {
    U_GT, U_GT, U_GT, U_EQ, U_NU}; // L">>>="
const wchar_t StringConstant::US_XOR[] = {U_CA, U_NU}; // L"^"
const wchar_t StringConstant::US_XOR_EQUAL[] = {U_CA, U_EQ, U_NU}; // L"^="

//
// Common constant pool entries
//
const wchar_t StringConstant::US_DS[] = {U_DS, U_NU}; // L"$"
const wchar_t StringConstant::US_LB_RB[] = {U_LB, U_RB, U_NU}; // L"[]"
const wchar_t StringConstant::US_MI[] = {U_MI, U_NU}; // L"-"
const wchar_t StringConstant::US_SC[] = {U_SC, U_NU}; // L";"
const wchar_t StringConstant::US_SL[] = {U_SL, U_NU}; // L"/"
const wchar_t StringConstant::US_jar[] = {U_j, U_a, U_r, U_NU}; // L"jar"
const wchar_t StringConstant::US_java_SL_io[] = {
    U_j, U_a, U_v, U_a, U_SL, U_i, U_o, U_NU}; // L"java/io"
const wchar_t StringConstant::US_java_SL_lang[] = {
    U_j, U_a, U_v, U_a, U_SL, U_l, U_a, U_n, U_g, U_NU}; // L"java/lang"
const wchar_t StringConstant::US_java_SL_lang_SL_annotation[] = {
    U_j, U_a, U_v, U_a, U_SL, U_l, U_a, U_n, U_g, U_SL,
    U_a, U_n, U_n, U_o, U_t, U_a, U_t, U_i, U_o, U_n,
    U_NU}; // L"java/lang/annotation"
const wchar_t StringConstant::US_java_SL_util[] = {
    U_j, U_a, U_v, U_a, U_SL, U_u, U_t, U_i, U_l, U_NU}; // L"java/util"
const wchar_t StringConstant::US_zip[] = {U_z, U_i, U_p, U_NU}; // L"zip"

//
// Java keywords.
//
const wchar_t StringConstant::US_abstract[] = {
    U_a, U_b, U_s, U_t, U_r, U_a, U_c, U_t, U_NU}; // L"abstract"
const wchar_t StringConstant::US_assert[] = {
    U_a, U_s, U_s, U_e, U_r, U_t, U_NU}; // L"assert"
const wchar_t StringConstant::US_boolean[] = {
    U_b, U_o, U_o, U_l, U_e, U_a, U_n, U_NU}; // L"boolean"
const wchar_t StringConstant::US_break[] = {
    U_b, U_r, U_e, U_a, U_k, U_NU}; // L"break"
const wchar_t StringConstant::US_byte[] = {
    U_b, U_y, U_t, U_e, U_NU}; // L"byte"
const wchar_t StringConstant::US_case[] = {
    U_c, U_a, U_s, U_e, U_NU}; // L"case"
const wchar_t StringConstant::US_catch[] = {
    U_c, U_a, U_t, U_c, U_h, U_NU}; // L"catch"
const wchar_t StringConstant::US_char[] = {
    U_c, U_h, U_a, U_r, U_NU}; // L"char"
const wchar_t StringConstant::US_class[] = {
    U_c, U_l, U_a, U_s, U_s, U_NU}; // L"class"
const wchar_t StringConstant::US_const[] = {
    U_c, U_o, U_n, U_s, U_t, U_NU}; // L"const"
const wchar_t StringConstant::US_continue[] = {
    U_c, U_o, U_n, U_t, U_i, U_n, U_u, U_e, U_NU}; // L"continue"
const wchar_t StringConstant::US_default[] = {
    U_d, U_e, U_f, U_a, U_u, U_l, U_t, U_NU}; // L"default"
const wchar_t StringConstant::US_do[] = {U_d, U_o, U_NU}; // L"do"
const wchar_t StringConstant::US_double[] = {
    U_d, U_o, U_u, U_b, U_l, U_e, U_NU}; // L"double"
const wchar_t StringConstant::US_else[] = {
    U_e, U_l, U_s, U_e, U_NU}; // L"else"
const wchar_t StringConstant::US_enum[] = {
    U_e, U_n, U_u, U_m, U_NU}; // L"enum"
const wchar_t StringConstant::US_extends[] = {
    U_e, U_x, U_t, U_e, U_n, U_d, U_s, U_NU}; // L"extends"
const wchar_t StringConstant::US_false[] = {
    U_f, U_a, U_l, U_s, U_e, U_NU}; // L"false"
const wchar_t StringConstant::US_final[] = {
    U_f, U_i, U_n, U_a, U_l, U_NU}; // L"final"
const wchar_t StringConstant::US_finally[] = {
    U_f, U_i, U_n, U_a, U_l, U_l, U_y, U_NU}; // L"finally"
const wchar_t StringConstant::US_float[] = {
    U_f, U_l, U_o, U_a, U_t, U_NU}; // L"float"
const wchar_t StringConstant::US_for[] = {U_f, U_o, U_r, U_NU}; // L"for"
const wchar_t StringConstant::US_goto[] = {
    U_g, U_o, U_t, U_o, U_NU}; // L"goto"
const wchar_t StringConstant::US_if[] = {U_i, U_f, U_NU}; // L"if"
const wchar_t StringConstant::US_implements[] = {
    U_i, U_m, U_p, U_l, U_e, U_m, U_e, U_n, U_t, U_s, U_NU}; // L"implements"
const wchar_t StringConstant::US_import[] = {
    U_i, U_m, U_p, U_o, U_r, U_t, U_NU}; // L"import"
const wchar_t StringConstant::US_instanceof[] = {
    U_i, U_n, U_s, U_t, U_a, U_n, U_c, U_e, U_o, U_f, U_NU}; // L"instanceof"
const wchar_t StringConstant::US_int[] = {U_i, U_n, U_t, U_NU}; // L"int"
const wchar_t StringConstant::US_interface[] = {
    U_i, U_n, U_t, U_e, U_r, U_f, U_a, U_c, U_e, U_NU}; // L"interface"
const wchar_t StringConstant::US_long[] = {
    U_l, U_o, U_n, U_g, U_NU}; // L"long"
const wchar_t StringConstant::US_native[] = {
    U_n, U_a, U_t, U_i, U_v, U_e, U_NU}; // L"native"
const wchar_t StringConstant::US_new[] = {U_n, U_e, U_w, U_NU}; // L"new"
const wchar_t StringConstant::US_null[] = {
    U_n, U_u, U_l, U_l, U_NU}; // L"null"
const wchar_t StringConstant::US_package[] = {
    U_p, U_a, U_c, U_k, U_a, U_g, U_e, U_NU}; // L"package"
const wchar_t StringConstant::US_private[] = {
    U_p, U_r, U_i, U_v, U_a, U_t, U_e, U_NU}; // L"private"
const wchar_t StringConstant::US_protected[] = {
    U_p, U_r, U_o, U_t, U_e, U_c, U_t, U_e, U_d, U_NU}; // L"protected"
const wchar_t StringConstant::US_public[] = {
    U_p, U_u, U_b, U_l, U_i, U_c, U_NU}; // L"public"
const wchar_t StringConstant::US_return[] = {
    U_r, U_e, U_t, U_u, U_r, U_n, U_NU}; // L"return"
const wchar_t StringConstant::US_short[] = {
    U_s, U_h, U_o, U_r, U_t, U_NU}; // L"short"
const wchar_t StringConstant::US_static[] = {
    U_s, U_t, U_a, U_t, U_i, U_c, U_NU}; // L"static"
const wchar_t StringConstant::US_strictfp[] = {
    U_s, U_t, U_r, U_i, U_c, U_t, U_f, U_p, U_NU}; // L"strictfp"
const wchar_t StringConstant::US_super[] = {
    U_s, U_u, U_p, U_e, U_r, U_NU}; // L"super"
const wchar_t StringConstant::US_switch[] = {
    U_s, U_w, U_i, U_t, U_c, U_h, U_NU}; // L"switch"
const wchar_t StringConstant::US_synchronized[] = {
    U_s, U_y, U_n, U_c, U_h, U_r, U_o, U_n, U_i, U_z, U_e, U_d,
    U_NU}; // L"synchronized"
const wchar_t StringConstant::US_this[] = {
    U_t, U_h, U_i, U_s, U_NU}; // L"this"
const wchar_t StringConstant::US_throw[] = {
    U_t, U_h, U_r, U_o, U_w, U_NU}; // L"throw"
const wchar_t StringConstant::US_throws[] = {
    U_t, U_h, U_r, U_o, U_w, U_s, U_NU}; // L"throws"
const wchar_t StringConstant::US_transient[] = {
    U_t, U_r, U_a, U_n, U_s, U_i, U_e, U_n, U_t, U_NU}; // L"transient"
const wchar_t StringConstant::US_true[] = {
    U_t, U_r, U_u, U_e, U_NU}; // L"true"
const wchar_t StringConstant::US_try[] = {U_t, U_r, U_y, U_NU}; // L"try"
const wchar_t StringConstant::US_void[] = {
    U_v, U_o, U_i, U_d, U_NU}; // L"void"
const wchar_t StringConstant::US_volatile[] = {
    U_v, U_o, U_l, U_a, U_t, U_i, U_l, U_e, U_NU}; // L"volatile"
const wchar_t StringConstant::US_while[] = {
    U_w, U_h, U_i, U_l, U_e, U_NU}; // L"while"

//
// Miscellaneous strings.
//
const char StringConstant::U8S_help_header[] =
    "Jikes Compiler - " JIKES_VERSION_STRING
    "\nCopyright (C) IBM Corporation 1997-2003, 2004.\n"
    "- Licensed Materials - Program Property of IBM - All Rights Reserved.\n";
const char StringConstant::U8S_command_format[] =
    "use: jikes [options] [@files] file.java...\n";

//
// Constant pool entries.
//
const char StringConstant::U8S_AnnotationDefault[] = {
    U_A, U_n, U_n, U_o, U_t, U_a, U_t, U_i, U_o, U_n,
    U_D, U_e, U_f, U_a, U_u, U_l, U_t, U_NU}; // "AnnotationDefault
const char StringConstant::U8S_Code[] = {U_C, U_o, U_d, U_e, U_NU}; // "Code"
const char StringConstant::U8S_ConstantValue[] = {
    U_C, U_o, U_n, U_s, U_t, U_a, U_n, U_t,
    U_V, U_a, U_l, U_u, U_e, U_NU}; // "ConstantValue"
const char StringConstant::U8S_Deprecated[] = {
    U_D, U_e, U_p, U_r, U_e, U_c, U_a, U_t, U_e, U_d, U_NU}; // "Deprecated"
const char StringConstant::U8S_EnclosingMethod[] = {
    U_E, U_n, U_c, U_l, U_o, U_s, U_i, U_n, U_g,
    U_M, U_e, U_t, U_h, U_o, U_d, U_NU}; // "EnclosingMethod"
const char StringConstant::U8S_Exceptions[] = {
    U_E, U_x, U_c, U_e, U_p, U_t, U_i, U_o, U_n, U_s, U_NU}; // "Exceptions"
const char StringConstant::U8S_InnerClasses[] = {
    U_I, U_n, U_n, U_e, U_r,
    U_C, U_l, U_a, U_s, U_s, U_e, U_s, U_NU}; // "InnerClasses"
const char StringConstant::U8S_LineNumberTable[] = {
    U_L, U_i, U_n, U_e, U_N, U_u, U_m, U_b, U_e, U_r,
    U_T, U_a, U_b, U_l, U_e, U_NU}; // "LineNumberTable"
const char StringConstant::U8S_LocalVariableTable[] = {
    U_L, U_o, U_c, U_a, U_l, U_V, U_a, U_r, U_i, U_a, U_b, U_l, U_e,
    U_T, U_a, U_b, U_l, U_e, U_NU}; // "LocalVariableTable"
const char StringConstant::U8S_LocalVariableTypeTable[] = {
    U_L, U_o, U_c, U_a, U_l, U_V, U_a, U_r, U_i, U_a, U_b, U_l, U_e,
    U_T, U_y, U_p, U_e, U_T, U_a, U_b, U_l, U_e,
    U_NU}; // "LocalVariableTypeTable"
const char StringConstant::U8S_RuntimeInvisibleAnnotations[] = {
    U_R, U_u, U_n, U_t, U_i, U_m, U_e,
    U_I, U_n, U_v, U_i, U_s, U_i, U_b, U_l, U_e,
    U_A, U_n, U_n, U_o, U_t, U_a, U_t, U_i, U_o, U_n, U_s,
    U_NU}; // 'RuntimeInvisibleAnnotations"
const char StringConstant::U8S_RuntimeVisibleAnnotations[] = {
    U_R, U_u, U_n, U_t, U_i, U_m, U_e, U_V, U_i, U_s, U_i, U_b, U_l, U_e,
    U_A, U_n, U_n, U_o, U_t, U_a, U_t, U_i, U_o, U_n, U_s,
    U_NU}; // 'RuntimeVisibleAnnotations"
const char StringConstant::U8S_RuntimeInvisibleParameterAnnotations[] = {
    U_R, U_u, U_n, U_t, U_i, U_m, U_e,
    U_I, U_n, U_v, U_i, U_s, U_i, U_b, U_l, U_e,
    U_P, U_a, U_r, U_a, U_m, U_e, U_t, U_e, U_r,
    U_A, U_n, U_n, U_o, U_t, U_a, U_t, U_i, U_o, U_n, U_s,
    U_NU}; // 'RuntimeInvisibleParameterAnnotations"
const char StringConstant::U8S_RuntimeVisibleParameterAnnotations[] = {
    U_R, U_u, U_n, U_t, U_i, U_m, U_e, U_V, U_i, U_s, U_i, U_b, U_l, U_e,
    U_P, U_a, U_r, U_a, U_m, U_e, U_t, U_e, U_r,
    U_A, U_n, U_n, U_o, U_t, U_a, U_t, U_i, U_o, U_n, U_s,
    U_NU}; // 'RuntimeVisibleParameterAnnotations"
const char StringConstant::U8S_Signature[] = {
    U_S, U_i, U_g, U_n, U_a, U_t, U_u, U_r, U_e, U_NU}; // "Signature"
const char StringConstant::U8S_SourceFile[] = {
    U_S, U_o, U_u, U_r, U_c, U_e, U_F, U_i, U_l, U_e, U_NU}; // "SourceFile"
const char StringConstant::U8S_StackMap[] = {
    U_S, U_t, U_a, U_c, U_k, U_M, U_a, U_p, U_NU}; // "StackMap"
const char StringConstant::U8S_Synthetic[] = {
    U_S, U_y, U_n, U_t, U_h, U_e, U_t, U_i, U_c, U_NU}; // "Synthetic"

//
// ASCII file names.
//
const char StringConstant::U8S_DO_class[] = {
    U_DO, U_c, U_l, U_a, U_s, U_s, U_NU}; // ".class"
const char StringConstant::U8S_DO_java[] = {
    U_DO, U_j, U_a, U_v, U_a, U_NU}; // ".java"
const char StringConstant::U8S_DO_tok[] = {
    U_DO, U_t, U_o, U_k, U_NU}; // ".tok"
const char StringConstant::U8S_DO_u[] = {U_DO, U_u, U_NU}; // ".u"
const char StringConstant::U8S_LP[] = {U_LP, U_NU}; // "("
const char StringConstant::U8S_RP[] = {U_RP, U_NU}; // ")"
const char StringConstant::U8S_SL[] = {U_SL, U_NU}; // "/"

//
// Convert number to string.
//
const char StringConstant::U8S_NaN[] = {U_N, U_a, U_N, U_NU}; // "NaN"
const char StringConstant::U8S_pos_Infinity[] = {
    U_I, U_n, U_f, U_i, U_n, U_i, U_t, U_y, U_NU}; // "Infinity"
const char StringConstant::U8S_neg_Infinity[] = {
    U_MINUS, U_I, U_n, U_f, U_i, U_n, U_i, U_t, U_y, U_NU}; // "-Infinity"
const char StringConstant::U8S_pos_Zero[] = {U_0, U_DOT, U_0, U_NU}; // "0.0"
const char StringConstant::U8S_neg_Zero[] = {
    U_MINUS, U_0, U_DOT, U_0, U_NU}; // "-0.0"

Ostream Coutput;

#ifdef HAVE_JIKES_NAMESPACE
} // Close namespace Jikes block
#endif
