/*
 * The contents of this file are subject to the Netscape Public
 * License Version 1.1 (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.mozilla.org/NPL/

 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.

 * The Original Code is Rhino code, released
 * May 6, 1999.

 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
 * Rights Reserved.

 * Contributor(s): 

 * Alternatively, the contents of this file may be used under the
 * terms of the GNU Public License (the "GPL"), in which case the
 * provisions of the GPL are applicable instead of those above.
 * If you wish to allow use of your version of this file only
 * under the terms of the GPL and not to allow others to use your
 * version of this file under the NPL, indicate your decision by
 * deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL.  If you do not delete
 * the provisions above, a recipient may use your version of this
 * file under either the NPL or the GPL.
 */
/**
 * This class saves decompilation information about the source.
 * Source information is returned from the parser as a jsString_t
 * associated with function nodes and with the toplevel script.  When
 * saved in the constant pool of a class, this string will be UTF-8
 * encoded, and token values will occupy a single byte.

 * Source is saved (mostly) as token numbers.  The tokens saved pretty
 * much correspond to the token stream of a 'canonical' representation
 * of the input program, as directed by the parser.  (There were a few
 * cases where tokens could have been left out where decompiler could
 * easily reconstruct them, but I left them in for clarity).  (I also
 * looked adding source collection to JSTokenStream instead, where I
 * could have limited the changes to a few lines in getToken... but
 * this wouldn't have saved any space in the resulting source
 * representation, and would have meant that I'd have to duplicate
 * parser logic in the decompiler to disambiguate situations where
 * newlines are important.)  NativeFunction.decompile expands the
 * tokens back into their string representations, using simple
 * lookahead to correct spacing and indentation.

 * Token types with associated ops (ASSIGN, SHOP, PRIMARY, etc.) are
 * saved as two-token pairs.  Number tokens are stored inline, as a
 * NUMBER token, a character representing the type, and either 1 or 4
 * characters representing the bit-encoding of the number.  jsString_t
 * types NAME, STRING and OBJECT are currently stored as a token type,
 * followed by a character giving the length of the string (assumed to
 * be less than 2^16), followed by the characters of the string
 * inlined into the source string.  Changing this to some reference to
 * to the string in the compiled class' constant pool would probably
 * save a lot of space... but would require some method of deriving
 * the final constant pool entry from information available at parse
 * time.

 * Nested functions need a similar mechanism... fortunately the nested
 * functions for a given function are generated in source order.
 * Nested functions are encoded as FUNCTION followed by a function
 * number (encoded as a character), which is enough information to
 * find the proper generated NativeFunction instance.

 * OPT source info collection is a potential performance bottleneck;
 * Source wraps a java.lang.jsString_tBuffer, which is synchronized.  It
 * might be faster to implement Source with its own char buffer and
 * toString method.
 */
/* Header file */
#include <stdio.h>
#include <math.h>
#include <limits.h>
#ifdef VX
#include <string.h>
#include <private/mathP.h>
#endif
#include "js-tokenstream.h"
#include "js-utils.h"
#include "js-source.h"

/* Procedures */
#ifndef FASTER	// to save gc memory and calls, we don't save
void
JSSource::append(jsChar_t c)
{
    buf.append(c);
}
void
JSSource::addString(int type, jsString_t str)
{
    buf.append((jsChar_t) type);
    // java string length < 2^16?
    buf.append((jsChar_t) strlen(str));
    buf.append(str);
}
/* encode the number in the source stream.
 * Save as NUMBER type (char | char char char char)
 * where type is
 * 'D' - double, 'S' - short, 'J' - long.

 * We need to retain float vs. integer type info to keep the
 * behavior of liveconnect type-guessing the same after
 * decompilation.  (Liveconnect tries to present 1.0 to Java
 * as a float/double)
 * OPT: This is no longer true. We could compress the format.

 * This may not be the most space-efficient encoding;
 * the chars created below may take up to 3 bytes in
 * constant pool UTF-8 encoding, so a Double could take
 * up to 12 bytes.
 */
int64_t
JSSource::doubleToLongBits(double d)
{
    union {
        double	d;
        int64_t	l;
    } v;

#ifdef VX
    if (isNan(d)) {
#else
    if (isnan(d)) {
#endif
        return ((int64_t) 0x7ff80000) << ((int64_t) 32);
    }

    v.d = d;
    return v.l;
}
void
JSSource::addNumber(double d)
{
    buf.append((jsChar_t) JSTokenStream::NUMBER);

    buf.append('D');

    int64_t i = doubleToLongBits(d);

    buf.append((jsChar_t) ((i >> 56) & 0xFF));
    buf.append((jsChar_t) ((i >> 48) & 0xFF));
    buf.append((jsChar_t) ((i >> 40) & 0xFF));
    buf.append((jsChar_t) ((i >> 32) & 0xFF));
    buf.append((jsChar_t) ((i >> 24) & 0xFF));
    buf.append((jsChar_t) ((i >> 16) & 0xFF));
    buf.append((jsChar_t) ((i >> 8) & 0xFF));
    buf.append((jsChar_t) (i & 0xFF));
}
void
JSSource::addNumber(int64_t i)
{
    if (i <= CHAR_MAX) {
        buf.append('S');
        buf.append((jsChar_t) i);
    } else { // Integral, but won't fit in a char. Store as a long.
        buf.append('J');
        buf.append((jsChar_t) ((i >> 56) & 0xFF));
        buf.append((jsChar_t) ((i >> 48) & 0xFF));
        buf.append((jsChar_t) ((i >> 40) & 0xFF));
        buf.append((jsChar_t) ((i >> 32) & 0xFF));
        buf.append((jsChar_t) ((i >> 24) & 0xFF));
        buf.append((jsChar_t) ((i >> 16) & 0xFF));
        buf.append((jsChar_t) ((i >> 8) & 0xFF));
        buf.append((jsChar_t) (i & 0xFF));
    }
}
#endif /* FASTER */

JSSource::JSSource(JSContext *cx)
		: buf(cx, 64)
{
    // OPT the default 16 is probably too small, but it's not
    // clear just what size would work best for most javascript.
    // It'd be nice to know what characterizes the javascript
    // that's out there.
    functionNumber = 0;  //avoid purify UMR error
}

