001 /* -*- Mode: java; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
002 *
003 * The contents of this file are subject to the Netscape Public
004 * License Version 1.1 (the "License"); you may not use this file
005 * except in compliance with the License. You may obtain a copy of
006 * the License at http://www.mozilla.org/NPL/
007 *
008 * Software distributed under the License is distributed on an "AS
009 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
010 * implied. See the License for the specific language governing
011 * rights and limitations under the License.
012 *
013 * The Original Code is Rhino code, released
014 * May 6, 1999.
015 *
016 * The Initial Developer of the Original Code is Netscape
017 * Communications Corporation. Portions created by Netscape are
018 * Copyright (C) 1997-2000 Netscape Communications Corporation. All
019 * Rights Reserved.
020 *
021 * Contributor(s):
022 * Patrick Beard
023 * Norris Boyd
024 * Igor Bukanov
025 * Roger Lawrence
026 * Frank Mitchell
027 * Andrew Wason
028 *
029 * Alternatively, the contents of this file may be used under the
030 * terms of the GNU Public License (the "GPL"), in which case the
031 * provisions of the GPL are applicable instead of those above.
032 * If you wish to allow use of your version of this file only
033 * under the terms of the GPL and not to allow others to use your
034 * version of this file under the NPL, indicate your decision by
035 * deleting the provisions above and replace them with the notice
036 * and other provisions required by the GPL. If you do not delete
037 * the provisions above, a recipient may use your version of this
038 * file under either the NPL or the GPL.
039 */
040 // Modified by Google
041
042 package com.google.gwt.dev.js.rhino;
043
044 /**
045 * This is the class that implements the runtime.
046 */
047
048 public class ScriptRuntime {
049
050 public static double NaN = 0.0d / 0.0;
051
052 /*
053 * Helper function for toNumber, parseInt, and TokenStream.getToken.
054 */
055 static double stringToNumber(String s, int start, int radix) {
056 char digitMax = '9';
057 char lowerCaseBound = 'a';
058 char upperCaseBound = 'A';
059 int len = s.length();
060 if (radix < 10) {
061 digitMax = (char) ('0' + radix - 1);
062 }
063 if (radix > 10) {
064 lowerCaseBound = (char) ('a' + radix - 10);
065 upperCaseBound = (char) ('A' + radix - 10);
066 }
067 int end;
068 double sum = 0.0;
069 for (end=start; end < len; end++) {
070 char c = s.charAt(end);
071 int newDigit;
072 if ('0' <= c && c <= digitMax)
073 newDigit = c - '0';
074 else if ('a' <= c && c < lowerCaseBound)
075 newDigit = c - 'a' + 10;
076 else if ('A' <= c && c < upperCaseBound)
077 newDigit = c - 'A' + 10;
078 else
079 break;
080 sum = sum*radix + newDigit;
081 }
082 if (start == end) {
083 return NaN;
084 }
085 if (sum >= 9007199254740992.0) {
086 if (radix == 10) {
087 /* If we're accumulating a decimal number and the number
088 * is >= 2^53, then the result from the repeated multiply-add
089 * above may be inaccurate. Call Java to get the correct
090 * answer.
091 */
092 try {
093 return Double.valueOf(s.substring(start, end)).doubleValue();
094 } catch (NumberFormatException nfe) {
095 return NaN;
096 }
097 } else if (radix == 2 || radix == 4 || radix == 8 ||
098 radix == 16 || radix == 32)
099 {
100 /* The number may also be inaccurate for one of these bases.
101 * This happens if the addition in value*radix + digit causes
102 * a round-down to an even least significant mantissa bit
103 * when the first dropped bit is a one. If any of the
104 * following digits in the number (which haven't been added
105 * in yet) are nonzero then the correct action would have
106 * been to round up instead of down. An example of this
107 * occurs when reading the number 0x1000000000000081, which
108 * rounds to 0x1000000000000000 instead of 0x1000000000000100.
109 */
110 BinaryDigitReader bdr = new BinaryDigitReader(radix, s, start, end);
111 int bit;
112 sum = 0.0;
113
114 /* Skip leading zeros. */
115 do {
116 bit = bdr.getNextBinaryDigit();
117 } while (bit == 0);
118
119 if (bit == 1) {
120 /* Gather the 53 significant bits (including the leading 1) */
121 sum = 1.0;
122 for (int j = 52; j != 0; j--) {
123 bit = bdr.getNextBinaryDigit();
124 if (bit < 0)
125 return sum;
126 sum = sum*2 + bit;
127 }
128 /* bit54 is the 54th bit (the first dropped from the mantissa) */
129 int bit54 = bdr.getNextBinaryDigit();
130 if (bit54 >= 0) {
131 double factor = 2.0;
132 int sticky = 0; /* sticky is 1 if any bit beyond the 54th is 1 */
133 int bit3;
134
135 while ((bit3 = bdr.getNextBinaryDigit()) >= 0) {
136 sticky |= bit3;
137 factor *= 2;
138 }
139 sum += bit54 & (bit | sticky);
140 sum *= factor;
141 }
142 }
143 }
144 /* We don't worry about inaccurate numbers for any other base. */
145 }
146 return sum;
147 }
148
149 }