зеркало из https://github.com/mozilla/pjs.git
Updated for VC6
This commit is contained in:
Родитель
a808c9c7e8
Коммит
5acd2ebc45
|
@ -17,8 +17,8 @@
|
|||
// Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
// Rights Reserved.
|
||||
|
||||
#include <new>
|
||||
#include "hash.h"
|
||||
#include <new>
|
||||
namespace JS = JavaScript;
|
||||
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ namespace JavaScript {
|
|||
}
|
||||
|
||||
|
||||
const HashNumber goldenRatio = 0x9E3779B9U;
|
||||
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
|
@ -66,6 +69,7 @@ namespace JavaScript {
|
|||
|
||||
|
||||
// private
|
||||
class GenericHashTableIterator;
|
||||
class GenericHashTable {
|
||||
protected:
|
||||
GenericHashEntry **buckets; // Vector of hash buckets
|
||||
|
@ -89,21 +93,25 @@ namespace JavaScript {
|
|||
void maybeGrow() {if (nEntries > maxNEntries) rehash();}
|
||||
void maybeShrink() {if (nEntries < minNEntries) rehash();}
|
||||
|
||||
class Iterator {
|
||||
protected:
|
||||
GenericHashTable &ht; // Hash table being iterated
|
||||
GenericHashEntry *entry; // Current entry; nil if done
|
||||
GenericHashEntry **backpointer; // Pointer to pointer to current entry
|
||||
GenericHashEntry **nextBucket; // Next bucket; pointer past end of vector of hash buckets if done
|
||||
public:
|
||||
explicit Iterator(GenericHashTable &ht);
|
||||
~Iterator() {ht.maybeShrink(); DEBUG_ONLY(--ht.nReferences);}
|
||||
friend class GenericHashTableIterator;
|
||||
|
||||
operator bool() const {return entry;} // Return true if there are entries left.
|
||||
Iterator &operator++();
|
||||
};
|
||||
typedef GenericHashTableIterator Iterator;
|
||||
};
|
||||
|
||||
friend class Iterator;
|
||||
// This ought to be GenericHashTable::Iterator, but this doesn't work due to a
|
||||
// Microsoft VC6 bug.
|
||||
class GenericHashTableIterator {
|
||||
protected:
|
||||
GenericHashTable &ht; // Hash table being iterated
|
||||
GenericHashEntry *entry; // Current entry; nil if done
|
||||
GenericHashEntry **backpointer; // Pointer to pointer to current entry
|
||||
GenericHashEntry **nextBucket; // Next bucket; pointer past end of vector of hash buckets if done
|
||||
public:
|
||||
explicit GenericHashTableIterator(GenericHashTable &ht);
|
||||
~GenericHashTableIterator() {ht.maybeShrink(); DEBUG_ONLY(--ht.nReferences);}
|
||||
|
||||
operator bool() const {return entry != 0;} // Return true if there are entries left.
|
||||
GenericHashTableIterator &operator++();
|
||||
};
|
||||
|
||||
|
||||
|
@ -125,6 +133,9 @@ namespace JavaScript {
|
|||
|
||||
public:
|
||||
class Reference {
|
||||
#ifdef _WIN32 // Microsoft VC6 bug: friend declarations to inner classes don't work
|
||||
public:
|
||||
#endif
|
||||
Entry *entry; // Current entry; nil if done
|
||||
GenericHashEntry **backpointer; // Pointer to pointer to current entry
|
||||
const HashNumber keyHash; // This entry's key's hash value
|
||||
|
@ -133,7 +144,25 @@ namespace JavaScript {
|
|||
#endif
|
||||
|
||||
public:
|
||||
#ifndef _WIN32
|
||||
Reference(HashTable &ht, Key key); // Search for an entry with the given key.
|
||||
#else // Microsoft VC6 bug: VC6 doesn't allow this to be defined outside the class
|
||||
Reference(HashTable &ht, Key key): keyHash(ht.hasher(key)) {
|
||||
#ifdef DEBUG
|
||||
Reference::ht = &ht;
|
||||
++ht.nReferences;
|
||||
#endif
|
||||
HashNumber kh = keyHash;
|
||||
HashNumber h = kh*goldenRatio >> ht.shift;
|
||||
GenericHashEntry **bp = ht.buckets + h;
|
||||
Entry *e;
|
||||
|
||||
while ((e = static_cast<Entry *>(*bp)) != 0 && !(e->keyHash == kh && e->data == key))
|
||||
bp = &e->next;
|
||||
entry = e;
|
||||
backpointer = bp;
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
Reference(const Reference&); // No copy constructor
|
||||
void operator=(const Reference&); // No assignment operator
|
||||
|
@ -142,22 +171,22 @@ namespace JavaScript {
|
|||
~Reference() {if (ht) --ht->nReferences;}
|
||||
#endif
|
||||
|
||||
operator bool() const {return entry;} // Return true if an entry was found.
|
||||
operator bool() const {return entry != 0;} // Return true if an entry was found.
|
||||
Data &operator*() const {ASSERT(entry); return entry->data;} // Return the data of the entry that was found.
|
||||
|
||||
friend class HashTable;
|
||||
};
|
||||
|
||||
class Iterator: public GenericHashTable::Iterator {
|
||||
class Iterator: public GenericHashTableIterator {
|
||||
public:
|
||||
explicit Iterator(HashTable &ht): GenericHashTable::Iterator(ht) {}
|
||||
explicit Iterator(HashTable &ht): GenericHashTableIterator(ht) {}
|
||||
private:
|
||||
Iterator(const Iterator&); // No copy constructor
|
||||
void operator=(const Iterator&); // No assignment operator
|
||||
public:
|
||||
|
||||
// Go to next entry.
|
||||
Iterator &operator++() {return *static_cast<Iterator*>(&GenericHashTable::Iterator::operator++());}
|
||||
Iterator &operator++() {return *static_cast<Iterator*>(&GenericHashTableIterator::operator++());}
|
||||
Data &operator*() const {ASSERT(entry); return static_cast<Entry *>(entry)->data;} // Return current entry's data.
|
||||
void erase();
|
||||
};
|
||||
|
@ -167,7 +196,6 @@ namespace JavaScript {
|
|||
|
||||
template<class Value> Data &insert(Reference &r, Key key, Value value);
|
||||
Data &insert(Reference &r, Key key);
|
||||
template<class Value> Data &insert(Key key, Value value);
|
||||
Data &insert(Key key);
|
||||
void erase(Reference &r);
|
||||
void erase(Key key);
|
||||
|
@ -175,6 +203,18 @@ namespace JavaScript {
|
|||
|
||||
friend class Reference;
|
||||
friend class Iterator;
|
||||
|
||||
#ifndef _WIN32
|
||||
template<class Value> Data &insert(Key key, Value value);
|
||||
#else // Microsoft VC6 bug: VC6 doesn't allow this to be defined outside the class
|
||||
template<class Value> Data &insert(Key key, Value value) {
|
||||
Reference r(*this, key);
|
||||
if (r)
|
||||
return *r = value;
|
||||
else
|
||||
return insert(r, key, value);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -197,8 +237,7 @@ namespace JavaScript {
|
|||
}
|
||||
|
||||
|
||||
const HashNumber goldenRatio = 0x9E3779B9U;
|
||||
|
||||
#ifndef _WIN32
|
||||
template<class Data, class Key, class H>
|
||||
HashTable<Data, Key, H>::Reference::Reference(HashTable &ht, Key key):
|
||||
keyHash(ht.hasher(key))
|
||||
|
@ -237,6 +276,7 @@ namespace JavaScript {
|
|||
#endif
|
||||
return e->data;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Same as above but without a Value argument.
|
||||
template<class Data, class Key, class H>
|
||||
|
@ -259,6 +299,7 @@ namespace JavaScript {
|
|||
// Insert the given key/value pair into the hash table. If an entry with a
|
||||
// matching key already exists, replace that entry's value.
|
||||
// Return a reference to the new entry's value.
|
||||
#ifndef _WIN32 // Microsoft VC6 bug: VC6 doesn't allow this to be defined outside the class
|
||||
template<class Data, class Key, class H> template<class Value>
|
||||
Data &HashTable<Data, Key, H>::insert(Key key, Value value)
|
||||
{
|
||||
|
@ -268,6 +309,7 @@ namespace JavaScript {
|
|||
else
|
||||
return insert(r, key, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Same as above but without a Value argument.
|
||||
template<class Data, class Key, class H>
|
||||
|
|
|
@ -126,7 +126,7 @@ static void initConsole(StringPtr consoleName, const char* startupMessage, int &
|
|||
#endif /* XP_MAC */
|
||||
|
||||
|
||||
// Interactively read a line from inFile and put it into s.
|
||||
// Interactively read a line from the input stream in and put it into s.
|
||||
static bool promptLine(istream &in, string &s, const char *prompt)
|
||||
{
|
||||
std::cout << prompt;
|
||||
|
@ -134,7 +134,14 @@ static bool promptLine(istream &in, string &s, const char *prompt)
|
|||
/* Print a CR after the prompt because MPW grabs the entire line when entering an interactive command */
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
return getline(in, s);
|
||||
#ifndef _WIN32
|
||||
return std::getline(in, s) != 0;
|
||||
#else
|
||||
char buffer[256];
|
||||
bool result = fgets(buffer, sizeof(buffer), stdin) != 0;
|
||||
s = buffer;
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -166,7 +173,7 @@ static void readEvalPrint(istream &in, World &world)
|
|||
showString(std::cout, e.fullMessage());
|
||||
}
|
||||
std::cout << std::endl;
|
||||
buffer.clear();
|
||||
clear(buffer);
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
|
|
@ -360,7 +360,7 @@ void JS::BigInt::allocate(uint lgGrossSize)
|
|||
FREE_DTOA_LOCK(0);
|
||||
} else {
|
||||
FREE_DTOA_LOCK(0);
|
||||
w = static_cast<uint32 *>(std::malloc(min(grossSize*sizeof(uint32), sizeof(uint32 *))));
|
||||
w = static_cast<uint32 *>(STD::malloc(max(grossSize*sizeof(uint32), uint32(sizeof(uint32 *)))));
|
||||
if (!w) {
|
||||
std::bad_alloc outOfMemory;
|
||||
throw outOfMemory;
|
||||
|
@ -1123,14 +1123,14 @@ double JS::strToDouble(const char *str, const char *&numEnd)
|
|||
goto ret;
|
||||
break;
|
||||
case 'I':
|
||||
if (!std::strncmp(s+1, "nfinity", 7)) {
|
||||
if (!STD::strncmp(s+1, "nfinity", 7)) {
|
||||
rv = positiveInfinity;
|
||||
s += 8;
|
||||
goto ret;
|
||||
}
|
||||
break;
|
||||
case 'N':
|
||||
if (!haveSign && !std::strncmp(s+1, "aN", 2)) {
|
||||
if (!haveSign && !STD::strncmp(s+1, "aN", 2)) {
|
||||
rv = nan;
|
||||
s += 3;
|
||||
goto ret;
|
||||
|
@ -1768,6 +1768,7 @@ double JS::stringToInteger(const char16 *str, const char16 *strEnd, const char16
|
|||
|
||||
if (bit == 1) {
|
||||
// Gather the 53 significant bits (including the leading 1)
|
||||
int bit2;
|
||||
value = 1.0;
|
||||
for (int j = 52; j; --j) {
|
||||
bit = bdr.next();
|
||||
|
@ -1776,7 +1777,7 @@ double JS::stringToInteger(const char16 *str, const char16 *strEnd, const char16
|
|||
value = value*2 + bit;
|
||||
}
|
||||
// bit2 is the 54th bit (the first dropped from the mantissa)
|
||||
int bit2 = bdr.next();
|
||||
bit2 = bdr.next();
|
||||
if (bit2 >= 0) {
|
||||
double factor = 2.0;
|
||||
int sticky = 0; // sticky is 1 if any bit beyond the 54th is 1
|
||||
|
@ -1912,7 +1913,7 @@ static char *doubleToAscii(double d, int mode, bool biasUp, int ndigits,
|
|||
// Infinity or NaN
|
||||
*decpt = 9999;
|
||||
s = !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN";
|
||||
std::strcpy(buf, s);
|
||||
strcpy(buf, s);
|
||||
return buf[3] ? buf + 8 : buf + 3;
|
||||
}
|
||||
if (!d) {
|
||||
|
@ -2515,7 +2516,7 @@ char *JS::doubleToStr(char *buffer, size_t bufferSize, double value, DToStrMode
|
|||
numBegin[0] = numBegin[1];
|
||||
numBegin[1] = '.';
|
||||
}
|
||||
std::sprintf(numEnd, "e%+d", decPt-1);
|
||||
STD::sprintf(numEnd, "e%+d", decPt-1);
|
||||
} else if (decPt != nDigits) {
|
||||
// Some kind of a fraction in fixed notation
|
||||
ASSERT(decPt <= nDigits);
|
||||
|
@ -2590,8 +2591,8 @@ size_t JS::doubleToBaseStr(char *buffer, double value, uint base)
|
|||
|
||||
// Check for Infinity and NaN
|
||||
if ((word0(value) & Exp_mask) == Exp_mask) {
|
||||
std::strcpy(p, !word1(value) && !(word0(value) & Frac_mask) ? "Infinity" : "NaN");
|
||||
return std::strlen(buffer);
|
||||
strcpy(p, !word1(value) && !(word0(value) & Frac_mask) ? "Infinity" : "NaN");
|
||||
return strlen(buffer);
|
||||
}
|
||||
|
||||
// Output the integer part of value with the digits in reverse order.
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <cmath>
|
||||
// Use platform-defined floating-point routines. On platforms with faulty floating-point code
|
||||
// ifdef these out and replace by custom implementations.
|
||||
#ifndef _WIN32 // Microsoft VC6 bug: standard identifiers should be in std namespace
|
||||
using std::abs;
|
||||
using std::floor;
|
||||
using std::ceil;
|
||||
|
@ -34,6 +35,7 @@ using std::tan;
|
|||
using std::asin;
|
||||
using std::acos;
|
||||
using std::atan;
|
||||
#endif
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
|
@ -53,7 +55,7 @@ namespace JavaScript {
|
|||
int hi0bits(uint32 x);
|
||||
|
||||
class BigInt {
|
||||
static const int maxLgGrossSize = 15; // Maximum value of lg2(grossSize)
|
||||
enum {maxLgGrossSize = 15}; // Maximum value of lg2(grossSize)
|
||||
static uint32 *freeLists[maxLgGrossSize+1];
|
||||
|
||||
uint lgGrossSize; // lg2(grossSize)
|
||||
|
|
|
@ -151,7 +151,7 @@ JS::String JS::StringReader::sourceFile() const
|
|||
//
|
||||
|
||||
|
||||
static const char *const JS::Token::kindNames[] = {
|
||||
const char *const JS::Token::kindNames[] = {
|
||||
// Special
|
||||
"[End]", // Token::End
|
||||
"[Identifier]", // Token::Id
|
||||
|
@ -676,7 +676,7 @@ void JS::Lexer::lexRegExp()
|
|||
syntaxError("Unterminated regular expression literal");
|
||||
if (prevCh == '\\') {
|
||||
reader.recordChar(char16orEOFToChar16(ch));
|
||||
prevCh = 0; // Ignore slashes and backslashes immediately after a \
|
||||
prevCh = 0; // Ignore slashes and backslashes immediately after a backslash
|
||||
} else if (ch != '/') {
|
||||
reader.recordChar(char16orEOFToChar16(ch));
|
||||
prevCh = ch;
|
||||
|
|
|
@ -313,7 +313,7 @@ namespace JavaScript {
|
|||
|
||||
|
||||
class Lexer {
|
||||
static const int tokenBufferSize = 3; // Token lookahead buffer size
|
||||
enum {tokenBufferSize = 3}; // Token lookahead buffer size
|
||||
public:
|
||||
Reader &reader;
|
||||
World &world;
|
||||
|
|
|
@ -22,43 +22,33 @@
|
|||
|
||||
#include <cstddef>
|
||||
|
||||
#ifdef _WIN32
|
||||
// Turn off warnings about identifiers too long in browser information
|
||||
#pragma warning(disable: 4786)
|
||||
#endif
|
||||
|
||||
// Define int8, int16, int32, int64, uint8, uint16, uint32, uint64, and uint.
|
||||
#ifdef XP_BEOS
|
||||
#include <SupportDefs.h>
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef short int16;
|
||||
typedef unsigned short uint16;
|
||||
#if !defined(XP_MAC) && !defined(_WIN32)
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
#else
|
||||
#ifdef XP_UNIX
|
||||
#include <sys/types.h>
|
||||
#else
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
typedef long int32;
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2)
|
||||
typedef unsigned int uint32;
|
||||
#else
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned char uint8;
|
||||
#ifdef AIX4_3
|
||||
#include <sys/inttypes.h>
|
||||
#else
|
||||
typedef long long int64;
|
||||
#ifdef HPUX
|
||||
#include <model.h>
|
||||
#else
|
||||
#if !defined(WIN32) || !defined(_WINSOCK2API_) /* defines its own "int32" */
|
||||
#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2)
|
||||
typedef int int32;
|
||||
#else
|
||||
typedef long int32;
|
||||
#endif
|
||||
#endif
|
||||
typedef short int16;
|
||||
typedef signed char int8;
|
||||
#endif /* HPUX */
|
||||
#endif /* AIX4_3 */
|
||||
#endif /* XP_BEOS */
|
||||
#endif
|
||||
|
||||
// Define this if the machine natively supports 64-bit integers
|
||||
#define NATIVE_INT64
|
||||
|
@ -72,6 +62,13 @@ typedef float float32;
|
|||
// Note that in C++ wchar_t is a distinct type rather than a typedef for some integral type.
|
||||
// Like char, a char16 can be either signed or unsigned at the implementation's discretion.
|
||||
typedef wchar_t char16;
|
||||
typedef unsigned wchar_t uchar16;
|
||||
|
||||
#ifndef _WIN32 // Microsoft VC6 bug: wchar_t should be a built-in type, not a typedef
|
||||
typedef unsigned wchar_t uchar16;
|
||||
#else
|
||||
typedef wchar_t uchar16;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IS_LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -161,11 +161,33 @@ uint JS::floorLog2(uint32 n)
|
|||
//
|
||||
|
||||
|
||||
#ifdef _WIN32 // Microsoft VC6 bug: String constructor and append limited to char16 iterators
|
||||
// Return a String containing the characters of the null-terminated C string cstr
|
||||
// (without the trailing null).
|
||||
JS::String JS::widenCString(const char *cstr)
|
||||
{
|
||||
size_t len = strlen(cstr);
|
||||
String s(len, uni::null);
|
||||
std::transform(cstr, cstr+len, s.begin(), widen);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// Widen and append length characters starting at chars to the end of str.
|
||||
void JS::appendChars(String &str, const char *chars, size_t length)
|
||||
{
|
||||
String::size_type strLen = str.size();
|
||||
str.append(length, uni::null);
|
||||
std::transform(chars, chars+length, str.begin()+strLen, widen);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Widen and append the null-terminated string cstr to the end of str.
|
||||
// Return str.
|
||||
JS::String &JS::operator+=(String &str, const char *cstr)
|
||||
{
|
||||
appendChars(str, cstr, std::strlen(cstr));
|
||||
appendChars(str, cstr, strlen(cstr));
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -1581,6 +1603,7 @@ JS::String JS::Exception::fullMessage() const
|
|||
//
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
static void jsNewHandler()
|
||||
{
|
||||
std::bad_alloc outOfMemory;
|
||||
|
@ -1592,4 +1615,18 @@ struct InitUtilities
|
|||
{
|
||||
InitUtilities() {std::set_new_handler(&jsNewHandler);}
|
||||
};
|
||||
#else
|
||||
#include <new.h>
|
||||
static int jsNewHandler(size_t)
|
||||
{
|
||||
std::bad_alloc outOfMemory;
|
||||
throw outOfMemory;
|
||||
}
|
||||
|
||||
|
||||
struct InitUtilities
|
||||
{
|
||||
InitUtilities() {_set_new_handler(&jsNewHandler);}
|
||||
};
|
||||
#endif
|
||||
InitUtilities initUtilities;
|
||||
|
|
|
@ -20,13 +20,20 @@
|
|||
#ifndef utilities_h
|
||||
#define utilities_h
|
||||
|
||||
#include "systemtypes.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "systemtypes.h"
|
||||
|
||||
#ifndef _WIN32 // Microsoft VC6 bug: standard identifiers should be in std namespace
|
||||
using std::size_t;
|
||||
using std::ptrdiff_t;
|
||||
using std::strlen;
|
||||
using std::strcpy;
|
||||
#define STD std
|
||||
#else
|
||||
#define STD
|
||||
#endif
|
||||
using std::string;
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
|
@ -102,11 +109,12 @@ namespace JavaScript {
|
|||
|
||||
inline char16 widen(char ch) {return static_cast<char16>(static_cast<uchar>(ch));}
|
||||
|
||||
#ifndef _WIN32
|
||||
// Return a String containing the characters of the null-terminated C string cstr
|
||||
// (without the trailing null).
|
||||
inline String widenCString(const char *cstr)
|
||||
{
|
||||
size_t len = std::strlen(cstr);
|
||||
size_t len = strlen(cstr);
|
||||
const uchar *ucstr = reinterpret_cast<const uchar *>(cstr);
|
||||
return String(ucstr, ucstr+len);
|
||||
}
|
||||
|
@ -118,6 +126,10 @@ namespace JavaScript {
|
|||
const uchar *uchars = reinterpret_cast<const uchar *>(chars);
|
||||
str.append(uchars, uchars + length);
|
||||
}
|
||||
#else // Microsoft VC6 bug: String constructor and append limited to char16 iterators
|
||||
String widenCString(const char *cstr);
|
||||
void appendChars(String &str, const char *chars, size_t length);
|
||||
#endif
|
||||
|
||||
|
||||
String &operator+=(String &str, const char *cstr);
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
// Copyright (C) 1998 Netscape Communications Corporation. All
|
||||
// Rights Reserved.
|
||||
|
||||
#include <new>
|
||||
#include "hash.h"
|
||||
#include <new>
|
||||
namespace JS = JavaScript;
|
||||
|
||||
|
||||
|
|
|
@ -47,6 +47,9 @@ namespace JavaScript {
|
|||
}
|
||||
|
||||
|
||||
const HashNumber goldenRatio = 0x9E3779B9U;
|
||||
|
||||
|
||||
//
|
||||
// Private
|
||||
//
|
||||
|
@ -66,6 +69,7 @@ namespace JavaScript {
|
|||
|
||||
|
||||
// private
|
||||
class GenericHashTableIterator;
|
||||
class GenericHashTable {
|
||||
protected:
|
||||
GenericHashEntry **buckets; // Vector of hash buckets
|
||||
|
@ -89,21 +93,25 @@ namespace JavaScript {
|
|||
void maybeGrow() {if (nEntries > maxNEntries) rehash();}
|
||||
void maybeShrink() {if (nEntries < minNEntries) rehash();}
|
||||
|
||||
class Iterator {
|
||||
protected:
|
||||
GenericHashTable &ht; // Hash table being iterated
|
||||
GenericHashEntry *entry; // Current entry; nil if done
|
||||
GenericHashEntry **backpointer; // Pointer to pointer to current entry
|
||||
GenericHashEntry **nextBucket; // Next bucket; pointer past end of vector of hash buckets if done
|
||||
public:
|
||||
explicit Iterator(GenericHashTable &ht);
|
||||
~Iterator() {ht.maybeShrink(); DEBUG_ONLY(--ht.nReferences);}
|
||||
friend class GenericHashTableIterator;
|
||||
|
||||
operator bool() const {return entry;} // Return true if there are entries left.
|
||||
Iterator &operator++();
|
||||
};
|
||||
typedef GenericHashTableIterator Iterator;
|
||||
};
|
||||
|
||||
friend class Iterator;
|
||||
// This ought to be GenericHashTable::Iterator, but this doesn't work due to a
|
||||
// Microsoft VC6 bug.
|
||||
class GenericHashTableIterator {
|
||||
protected:
|
||||
GenericHashTable &ht; // Hash table being iterated
|
||||
GenericHashEntry *entry; // Current entry; nil if done
|
||||
GenericHashEntry **backpointer; // Pointer to pointer to current entry
|
||||
GenericHashEntry **nextBucket; // Next bucket; pointer past end of vector of hash buckets if done
|
||||
public:
|
||||
explicit GenericHashTableIterator(GenericHashTable &ht);
|
||||
~GenericHashTableIterator() {ht.maybeShrink(); DEBUG_ONLY(--ht.nReferences);}
|
||||
|
||||
operator bool() const {return entry != 0;} // Return true if there are entries left.
|
||||
GenericHashTableIterator &operator++();
|
||||
};
|
||||
|
||||
|
||||
|
@ -125,6 +133,9 @@ namespace JavaScript {
|
|||
|
||||
public:
|
||||
class Reference {
|
||||
#ifdef _WIN32 // Microsoft VC6 bug: friend declarations to inner classes don't work
|
||||
public:
|
||||
#endif
|
||||
Entry *entry; // Current entry; nil if done
|
||||
GenericHashEntry **backpointer; // Pointer to pointer to current entry
|
||||
const HashNumber keyHash; // This entry's key's hash value
|
||||
|
@ -133,7 +144,25 @@ namespace JavaScript {
|
|||
#endif
|
||||
|
||||
public:
|
||||
#ifndef _WIN32
|
||||
Reference(HashTable &ht, Key key); // Search for an entry with the given key.
|
||||
#else // Microsoft VC6 bug: VC6 doesn't allow this to be defined outside the class
|
||||
Reference(HashTable &ht, Key key): keyHash(ht.hasher(key)) {
|
||||
#ifdef DEBUG
|
||||
Reference::ht = &ht;
|
||||
++ht.nReferences;
|
||||
#endif
|
||||
HashNumber kh = keyHash;
|
||||
HashNumber h = kh*goldenRatio >> ht.shift;
|
||||
GenericHashEntry **bp = ht.buckets + h;
|
||||
Entry *e;
|
||||
|
||||
while ((e = static_cast<Entry *>(*bp)) != 0 && !(e->keyHash == kh && e->data == key))
|
||||
bp = &e->next;
|
||||
entry = e;
|
||||
backpointer = bp;
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
Reference(const Reference&); // No copy constructor
|
||||
void operator=(const Reference&); // No assignment operator
|
||||
|
@ -142,22 +171,22 @@ namespace JavaScript {
|
|||
~Reference() {if (ht) --ht->nReferences;}
|
||||
#endif
|
||||
|
||||
operator bool() const {return entry;} // Return true if an entry was found.
|
||||
operator bool() const {return entry != 0;} // Return true if an entry was found.
|
||||
Data &operator*() const {ASSERT(entry); return entry->data;} // Return the data of the entry that was found.
|
||||
|
||||
friend class HashTable;
|
||||
};
|
||||
|
||||
class Iterator: public GenericHashTable::Iterator {
|
||||
class Iterator: public GenericHashTableIterator {
|
||||
public:
|
||||
explicit Iterator(HashTable &ht): GenericHashTable::Iterator(ht) {}
|
||||
explicit Iterator(HashTable &ht): GenericHashTableIterator(ht) {}
|
||||
private:
|
||||
Iterator(const Iterator&); // No copy constructor
|
||||
void operator=(const Iterator&); // No assignment operator
|
||||
public:
|
||||
|
||||
// Go to next entry.
|
||||
Iterator &operator++() {return *static_cast<Iterator*>(&GenericHashTable::Iterator::operator++());}
|
||||
Iterator &operator++() {return *static_cast<Iterator*>(&GenericHashTableIterator::operator++());}
|
||||
Data &operator*() const {ASSERT(entry); return static_cast<Entry *>(entry)->data;} // Return current entry's data.
|
||||
void erase();
|
||||
};
|
||||
|
@ -167,7 +196,6 @@ namespace JavaScript {
|
|||
|
||||
template<class Value> Data &insert(Reference &r, Key key, Value value);
|
||||
Data &insert(Reference &r, Key key);
|
||||
template<class Value> Data &insert(Key key, Value value);
|
||||
Data &insert(Key key);
|
||||
void erase(Reference &r);
|
||||
void erase(Key key);
|
||||
|
@ -175,6 +203,18 @@ namespace JavaScript {
|
|||
|
||||
friend class Reference;
|
||||
friend class Iterator;
|
||||
|
||||
#ifndef _WIN32
|
||||
template<class Value> Data &insert(Key key, Value value);
|
||||
#else // Microsoft VC6 bug: VC6 doesn't allow this to be defined outside the class
|
||||
template<class Value> Data &insert(Key key, Value value) {
|
||||
Reference r(*this, key);
|
||||
if (r)
|
||||
return *r = value;
|
||||
else
|
||||
return insert(r, key, value);
|
||||
}
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
@ -197,8 +237,7 @@ namespace JavaScript {
|
|||
}
|
||||
|
||||
|
||||
const HashNumber goldenRatio = 0x9E3779B9U;
|
||||
|
||||
#ifndef _WIN32
|
||||
template<class Data, class Key, class H>
|
||||
HashTable<Data, Key, H>::Reference::Reference(HashTable &ht, Key key):
|
||||
keyHash(ht.hasher(key))
|
||||
|
@ -237,6 +276,7 @@ namespace JavaScript {
|
|||
#endif
|
||||
return e->data;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Same as above but without a Value argument.
|
||||
template<class Data, class Key, class H>
|
||||
|
@ -259,6 +299,7 @@ namespace JavaScript {
|
|||
// Insert the given key/value pair into the hash table. If an entry with a
|
||||
// matching key already exists, replace that entry's value.
|
||||
// Return a reference to the new entry's value.
|
||||
#ifndef _WIN32 // Microsoft VC6 bug: VC6 doesn't allow this to be defined outside the class
|
||||
template<class Data, class Key, class H> template<class Value>
|
||||
Data &HashTable<Data, Key, H>::insert(Key key, Value value)
|
||||
{
|
||||
|
@ -268,6 +309,7 @@ namespace JavaScript {
|
|||
else
|
||||
return insert(r, key, value);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Same as above but without a Value argument.
|
||||
template<class Data, class Key, class H>
|
||||
|
|
|
@ -360,7 +360,7 @@ void JS::BigInt::allocate(uint lgGrossSize)
|
|||
FREE_DTOA_LOCK(0);
|
||||
} else {
|
||||
FREE_DTOA_LOCK(0);
|
||||
w = static_cast<uint32 *>(std::malloc(min(grossSize*sizeof(uint32), sizeof(uint32 *))));
|
||||
w = static_cast<uint32 *>(STD::malloc(max(grossSize*sizeof(uint32), uint32(sizeof(uint32 *)))));
|
||||
if (!w) {
|
||||
std::bad_alloc outOfMemory;
|
||||
throw outOfMemory;
|
||||
|
@ -1123,14 +1123,14 @@ double JS::strToDouble(const char *str, const char *&numEnd)
|
|||
goto ret;
|
||||
break;
|
||||
case 'I':
|
||||
if (!std::strncmp(s+1, "nfinity", 7)) {
|
||||
if (!STD::strncmp(s+1, "nfinity", 7)) {
|
||||
rv = positiveInfinity;
|
||||
s += 8;
|
||||
goto ret;
|
||||
}
|
||||
break;
|
||||
case 'N':
|
||||
if (!haveSign && !std::strncmp(s+1, "aN", 2)) {
|
||||
if (!haveSign && !STD::strncmp(s+1, "aN", 2)) {
|
||||
rv = nan;
|
||||
s += 3;
|
||||
goto ret;
|
||||
|
@ -1768,6 +1768,7 @@ double JS::stringToInteger(const char16 *str, const char16 *strEnd, const char16
|
|||
|
||||
if (bit == 1) {
|
||||
// Gather the 53 significant bits (including the leading 1)
|
||||
int bit2;
|
||||
value = 1.0;
|
||||
for (int j = 52; j; --j) {
|
||||
bit = bdr.next();
|
||||
|
@ -1776,7 +1777,7 @@ double JS::stringToInteger(const char16 *str, const char16 *strEnd, const char16
|
|||
value = value*2 + bit;
|
||||
}
|
||||
// bit2 is the 54th bit (the first dropped from the mantissa)
|
||||
int bit2 = bdr.next();
|
||||
bit2 = bdr.next();
|
||||
if (bit2 >= 0) {
|
||||
double factor = 2.0;
|
||||
int sticky = 0; // sticky is 1 if any bit beyond the 54th is 1
|
||||
|
@ -1912,7 +1913,7 @@ static char *doubleToAscii(double d, int mode, bool biasUp, int ndigits,
|
|||
// Infinity or NaN
|
||||
*decpt = 9999;
|
||||
s = !word1(d) && !(word0(d) & Frac_mask) ? "Infinity" : "NaN";
|
||||
std::strcpy(buf, s);
|
||||
strcpy(buf, s);
|
||||
return buf[3] ? buf + 8 : buf + 3;
|
||||
}
|
||||
if (!d) {
|
||||
|
@ -2515,7 +2516,7 @@ char *JS::doubleToStr(char *buffer, size_t bufferSize, double value, DToStrMode
|
|||
numBegin[0] = numBegin[1];
|
||||
numBegin[1] = '.';
|
||||
}
|
||||
std::sprintf(numEnd, "e%+d", decPt-1);
|
||||
STD::sprintf(numEnd, "e%+d", decPt-1);
|
||||
} else if (decPt != nDigits) {
|
||||
// Some kind of a fraction in fixed notation
|
||||
ASSERT(decPt <= nDigits);
|
||||
|
@ -2590,8 +2591,8 @@ size_t JS::doubleToBaseStr(char *buffer, double value, uint base)
|
|||
|
||||
// Check for Infinity and NaN
|
||||
if ((word0(value) & Exp_mask) == Exp_mask) {
|
||||
std::strcpy(p, !word1(value) && !(word0(value) & Frac_mask) ? "Infinity" : "NaN");
|
||||
return std::strlen(buffer);
|
||||
strcpy(p, !word1(value) && !(word0(value) & Frac_mask) ? "Infinity" : "NaN");
|
||||
return strlen(buffer);
|
||||
}
|
||||
|
||||
// Output the integer part of value with the digits in reverse order.
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include <cmath>
|
||||
// Use platform-defined floating-point routines. On platforms with faulty floating-point code
|
||||
// ifdef these out and replace by custom implementations.
|
||||
#ifndef _WIN32 // Microsoft VC6 bug: standard identifiers should be in std namespace
|
||||
using std::abs;
|
||||
using std::floor;
|
||||
using std::ceil;
|
||||
|
@ -34,6 +35,7 @@ using std::tan;
|
|||
using std::asin;
|
||||
using std::acos;
|
||||
using std::atan;
|
||||
#endif
|
||||
|
||||
namespace JavaScript {
|
||||
|
||||
|
@ -53,7 +55,7 @@ namespace JavaScript {
|
|||
int hi0bits(uint32 x);
|
||||
|
||||
class BigInt {
|
||||
static const int maxLgGrossSize = 15; // Maximum value of lg2(grossSize)
|
||||
enum {maxLgGrossSize = 15}; // Maximum value of lg2(grossSize)
|
||||
static uint32 *freeLists[maxLgGrossSize+1];
|
||||
|
||||
uint lgGrossSize; // lg2(grossSize)
|
||||
|
|
|
@ -151,7 +151,7 @@ JS::String JS::StringReader::sourceFile() const
|
|||
//
|
||||
|
||||
|
||||
static const char *const JS::Token::kindNames[] = {
|
||||
const char *const JS::Token::kindNames[] = {
|
||||
// Special
|
||||
"[End]", // Token::End
|
||||
"[Identifier]", // Token::Id
|
||||
|
@ -676,7 +676,7 @@ void JS::Lexer::lexRegExp()
|
|||
syntaxError("Unterminated regular expression literal");
|
||||
if (prevCh == '\\') {
|
||||
reader.recordChar(char16orEOFToChar16(ch));
|
||||
prevCh = 0; // Ignore slashes and backslashes immediately after a \
|
||||
prevCh = 0; // Ignore slashes and backslashes immediately after a backslash
|
||||
} else if (ch != '/') {
|
||||
reader.recordChar(char16orEOFToChar16(ch));
|
||||
prevCh = ch;
|
||||
|
|
|
@ -313,7 +313,7 @@ namespace JavaScript {
|
|||
|
||||
|
||||
class Lexer {
|
||||
static const int tokenBufferSize = 3; // Token lookahead buffer size
|
||||
enum {tokenBufferSize = 3}; // Token lookahead buffer size
|
||||
public:
|
||||
Reader &reader;
|
||||
World &world;
|
||||
|
|
|
@ -22,43 +22,33 @@
|
|||
|
||||
#include <cstddef>
|
||||
|
||||
#ifdef _WIN32
|
||||
// Turn off warnings about identifiers too long in browser information
|
||||
#pragma warning(disable: 4786)
|
||||
#endif
|
||||
|
||||
// Define int8, int16, int32, int64, uint8, uint16, uint32, uint64, and uint.
|
||||
#ifdef XP_BEOS
|
||||
#include <SupportDefs.h>
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
|
||||
typedef signed char int8;
|
||||
typedef unsigned char uint8;
|
||||
typedef short int16;
|
||||
typedef unsigned short uint16;
|
||||
#if !defined(XP_MAC) && !defined(_WIN32)
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
#else
|
||||
#ifdef XP_UNIX
|
||||
#include <sys/types.h>
|
||||
#else
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
typedef long int32;
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
typedef long long int64;
|
||||
typedef unsigned long long uint64;
|
||||
#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2)
|
||||
typedef unsigned int uint32;
|
||||
#else
|
||||
typedef unsigned long uint32;
|
||||
#endif
|
||||
typedef unsigned short uint16;
|
||||
typedef unsigned char uint8;
|
||||
#ifdef AIX4_3
|
||||
#include <sys/inttypes.h>
|
||||
#else
|
||||
typedef long long int64;
|
||||
#ifdef HPUX
|
||||
#include <model.h>
|
||||
#else
|
||||
#if !defined(WIN32) || !defined(_WINSOCK2API_) /* defines its own "int32" */
|
||||
#if !defined(XP_MAC) && !defined(_WIN32) && !defined(XP_OS2)
|
||||
typedef int int32;
|
||||
#else
|
||||
typedef long int32;
|
||||
#endif
|
||||
#endif
|
||||
typedef short int16;
|
||||
typedef signed char int8;
|
||||
#endif /* HPUX */
|
||||
#endif /* AIX4_3 */
|
||||
#endif /* XP_BEOS */
|
||||
#endif
|
||||
|
||||
// Define this if the machine natively supports 64-bit integers
|
||||
#define NATIVE_INT64
|
||||
|
@ -72,6 +62,13 @@ typedef float float32;
|
|||
// Note that in C++ wchar_t is a distinct type rather than a typedef for some integral type.
|
||||
// Like char, a char16 can be either signed or unsigned at the implementation's discretion.
|
||||
typedef wchar_t char16;
|
||||
typedef unsigned wchar_t uchar16;
|
||||
|
||||
#ifndef _WIN32 // Microsoft VC6 bug: wchar_t should be a built-in type, not a typedef
|
||||
typedef unsigned wchar_t uchar16;
|
||||
#else
|
||||
typedef wchar_t uchar16;
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define IS_LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -161,11 +161,33 @@ uint JS::floorLog2(uint32 n)
|
|||
//
|
||||
|
||||
|
||||
#ifdef _WIN32 // Microsoft VC6 bug: String constructor and append limited to char16 iterators
|
||||
// Return a String containing the characters of the null-terminated C string cstr
|
||||
// (without the trailing null).
|
||||
JS::String JS::widenCString(const char *cstr)
|
||||
{
|
||||
size_t len = strlen(cstr);
|
||||
String s(len, uni::null);
|
||||
std::transform(cstr, cstr+len, s.begin(), widen);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
// Widen and append length characters starting at chars to the end of str.
|
||||
void JS::appendChars(String &str, const char *chars, size_t length)
|
||||
{
|
||||
String::size_type strLen = str.size();
|
||||
str.append(length, uni::null);
|
||||
std::transform(chars, chars+length, str.begin()+strLen, widen);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// Widen and append the null-terminated string cstr to the end of str.
|
||||
// Return str.
|
||||
JS::String &JS::operator+=(String &str, const char *cstr)
|
||||
{
|
||||
appendChars(str, cstr, std::strlen(cstr));
|
||||
appendChars(str, cstr, strlen(cstr));
|
||||
return str;
|
||||
}
|
||||
|
||||
|
@ -1581,6 +1603,7 @@ JS::String JS::Exception::fullMessage() const
|
|||
//
|
||||
|
||||
|
||||
#ifndef _WIN32
|
||||
static void jsNewHandler()
|
||||
{
|
||||
std::bad_alloc outOfMemory;
|
||||
|
@ -1592,4 +1615,18 @@ struct InitUtilities
|
|||
{
|
||||
InitUtilities() {std::set_new_handler(&jsNewHandler);}
|
||||
};
|
||||
#else
|
||||
#include <new.h>
|
||||
static int jsNewHandler(size_t)
|
||||
{
|
||||
std::bad_alloc outOfMemory;
|
||||
throw outOfMemory;
|
||||
}
|
||||
|
||||
|
||||
struct InitUtilities
|
||||
{
|
||||
InitUtilities() {_set_new_handler(&jsNewHandler);}
|
||||
};
|
||||
#endif
|
||||
InitUtilities initUtilities;
|
||||
|
|
|
@ -20,13 +20,20 @@
|
|||
#ifndef utilities_h
|
||||
#define utilities_h
|
||||
|
||||
#include "systemtypes.h"
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "systemtypes.h"
|
||||
|
||||
#ifndef _WIN32 // Microsoft VC6 bug: standard identifiers should be in std namespace
|
||||
using std::size_t;
|
||||
using std::ptrdiff_t;
|
||||
using std::strlen;
|
||||
using std::strcpy;
|
||||
#define STD std
|
||||
#else
|
||||
#define STD
|
||||
#endif
|
||||
using std::string;
|
||||
using std::istream;
|
||||
using std::ostream;
|
||||
|
@ -102,11 +109,12 @@ namespace JavaScript {
|
|||
|
||||
inline char16 widen(char ch) {return static_cast<char16>(static_cast<uchar>(ch));}
|
||||
|
||||
#ifndef _WIN32
|
||||
// Return a String containing the characters of the null-terminated C string cstr
|
||||
// (without the trailing null).
|
||||
inline String widenCString(const char *cstr)
|
||||
{
|
||||
size_t len = std::strlen(cstr);
|
||||
size_t len = strlen(cstr);
|
||||
const uchar *ucstr = reinterpret_cast<const uchar *>(cstr);
|
||||
return String(ucstr, ucstr+len);
|
||||
}
|
||||
|
@ -118,6 +126,10 @@ namespace JavaScript {
|
|||
const uchar *uchars = reinterpret_cast<const uchar *>(chars);
|
||||
str.append(uchars, uchars + length);
|
||||
}
|
||||
#else // Microsoft VC6 bug: String constructor and append limited to char16 iterators
|
||||
String widenCString(const char *cstr);
|
||||
void appendChars(String &str, const char *chars, size_t length);
|
||||
#endif
|
||||
|
||||
|
||||
String &operator+=(String &str, const char *cstr);
|
||||
|
|
|
@ -126,7 +126,7 @@ static void initConsole(StringPtr consoleName, const char* startupMessage, int &
|
|||
#endif /* XP_MAC */
|
||||
|
||||
|
||||
// Interactively read a line from inFile and put it into s.
|
||||
// Interactively read a line from the input stream in and put it into s.
|
||||
static bool promptLine(istream &in, string &s, const char *prompt)
|
||||
{
|
||||
std::cout << prompt;
|
||||
|
@ -134,7 +134,14 @@ static bool promptLine(istream &in, string &s, const char *prompt)
|
|||
/* Print a CR after the prompt because MPW grabs the entire line when entering an interactive command */
|
||||
std::cout << std::endl;
|
||||
#endif
|
||||
return getline(in, s);
|
||||
#ifndef _WIN32
|
||||
return std::getline(in, s) != 0;
|
||||
#else
|
||||
char buffer[256];
|
||||
bool result = fgets(buffer, sizeof(buffer), stdin) != 0;
|
||||
s = buffer;
|
||||
return result;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -166,7 +173,7 @@ static void readEvalPrint(istream &in, World &world)
|
|||
showString(std::cout, e.fullMessage());
|
||||
}
|
||||
std::cout << std::endl;
|
||||
buffer.clear();
|
||||
clear(buffer);
|
||||
}
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
|
Загрузка…
Ссылка в новой задаче