Переглянути джерело

*** empty log message ***

David Rose 25 роки тому
батько
коміт
121fb2faa3

+ 3 - 3
direct/src/dcparse/test.dc

@@ -3,8 +3,8 @@
 dclass Movable {
 dclass Movable {
 
 
   // Declare a few atomic fields
   // Declare a few atomic fields
-  set_xyz(int16 / 1000, int16 / 1000, int16 / 1000) required broadcast ram;
-  set_hpr(int16, int16, int16) required broadcast ram;
+  set_xyz(int16 x = 1024 / 1000, int16 y / 1000 = 1.024, int16 z / 1000 = 0.512) required broadcast ram;
+  set_hpr(int16 h, int16 p , int16 r = 0) required broadcast ram;
 
 
   // And a molecular field
   // And a molecular field
   set_xyzhpr : set_xyz, set_hpr;
   set_xyzhpr : set_xyz, set_hpr;
@@ -14,7 +14,7 @@ dclass Movable {
 dclass Attitude : Movable {
 dclass Attitude : Movable {
   // methods are inherited from parent class.
   // methods are inherited from parent class.
 
 
-  set_attitude(int8) required broadcast ram;
+  set_attitude(int16array attitude = { 1 * 3 }) required broadcast ram;
 
 
   // This molecular field uses some inherited atomic fields.
   // This molecular field uses some inherited atomic fields.
   set_xyzhprattitude : set_xyz, set_hpr, set_attitude;
   set_xyzhprattitude : set_xyz, set_hpr, set_attitude;

+ 1 - 0
direct/src/dcparser/Sources.pp

@@ -6,6 +6,7 @@
     directbase
     directbase
 #define YACC_PREFIX dcyy
 #define YACC_PREFIX dcyy
 #define C++FLAGS -DWITHIN_PANDA
 #define C++FLAGS -DWITHIN_PANDA
+#define UNIX_SYS_LIBS m
 
 
 #begin lib_target
 #begin lib_target
   #define TARGET dcparser
   #define TARGET dcparser

+ 315 - 0
direct/src/dcparser/dcAtomicField.cxx

@@ -7,6 +7,7 @@
 #include "hashGenerator.h"
 #include "hashGenerator.h"
 #include "dcindent.h"
 #include "dcindent.h"
 
 
+#include <math.h>
 
 
 ostream &
 ostream &
 operator << (ostream &out, const DCAtomicField::ElementType &et) {
 operator << (ostream &out, const DCAtomicField::ElementType &et) {
@@ -14,9 +15,281 @@ operator << (ostream &out, const DCAtomicField::ElementType &et) {
   if (et._divisor != 1) {
   if (et._divisor != 1) {
     out << " / " << et._divisor;
     out << " / " << et._divisor;
   }
   }
+  if (!et._name.empty()) {
+    out << " " << et._name;
+  }
+  if (et._has_default_value) {
+    out << " = <" << hex;
+    string::const_iterator si;
+    for (si = et._default_value.begin(); si != et._default_value.end(); ++si) {
+      out << setw(2) << setfill('0') << (int)(unsigned char)(*si);
+    }
+    out << dec << ">";
+  }
   return out;
   return out;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::ElementType::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+DCAtomicField::ElementType::
+ElementType() {
+  _type = ST_invalid;
+  _divisor = 1;
+  _has_default_value = false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::ElementType::set_default_value
+//       Access: Public
+//  Description: Stores the indicated value as the default value for
+//               this element.
+//
+//               Returns true if the element type reasonably accepts a
+//               default value of numeric type, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCAtomicField::ElementType::
+set_default_value(double num) {
+  switch (_type) {
+  case ST_int16array:
+  case ST_uint16array:
+  case ST_int32array:
+  case ST_uint32array:
+  case ST_blob:
+    // These array types don't take numbers.
+    return false;
+  default:
+    break;
+  }
+
+  string formatted;
+  if (!format_default_value(num, formatted)) {
+    return false;
+  }
+
+  _default_value = formatted;
+  _has_default_value = true;
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::ElementType::set_default_value
+//       Access: Public
+//  Description: Stores the indicated value as the default value for
+//               this element.
+//
+//               Returns true if the element type reasonably accepts a
+//               default value of string type, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCAtomicField::ElementType::
+set_default_value(const string &str) {
+  switch (_type) {
+  case ST_int16array:
+  case ST_uint16array:
+  case ST_int32array:
+  case ST_uint32array:
+    // These array types don't take strings.
+    return false;
+  default:
+    break;
+  }
+
+  string formatted;
+  if (!format_default_value(str, formatted)) {
+    return false;
+  }
+
+  _default_value = formatted;
+  _has_default_value = true;
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::ElementType::set_default_value_literal
+//       Access: Public
+//  Description: Explicitly sets the default value to the given
+//               pre-formatted string.
+////////////////////////////////////////////////////////////////////
+void DCAtomicField::ElementType::
+set_default_value_literal(const string &str) {
+  _default_value = str;
+  _has_default_value = true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::ElementType::add_default_value
+//       Access: Public
+//  Description: Appends the indicated value as the next array element
+//               value for the default value for this type.
+//
+//               Returns true if the element type reasonably accepts a
+//               default value of numeric type, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCAtomicField::ElementType::
+add_default_value(double num) {
+  string formatted;
+  if (!format_default_value(num, formatted)) {
+    return false;
+  }
+
+  _default_value += formatted;
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::ElementType::end_array
+//       Access: Public
+//  Description: Called by the parser after a number of calls to
+//               add_default_value(), to indicate the array has been
+//               completed.
+////////////////////////////////////////////////////////////////////
+bool DCAtomicField::ElementType::
+end_array() {
+  switch (_type) {
+  case ST_int16array:
+  case ST_uint16array:
+  case ST_int32array:
+  case ST_uint32array:
+  case ST_blob:
+    {
+      // We've accumulated all the elements of the array; now we must
+      // prepend the array length.
+      int length = _default_value.length();
+      _default_value = 
+	string(1, (char)(length & 0xff)) +
+	string(1, (char)((length >> 8) & 0xff)) +
+	_default_value;
+    }
+    return true;
+    
+  default:
+    return false;
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::ElementType::format_default_value
+//       Access: Private
+//  Description: Formats the indicated default value to a sequence of
+//               bytes, according to the element type.  Returns true
+//               if the element type reasonably accepts a number,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCAtomicField::ElementType::
+format_default_value(double num, string &formatted) const {
+  double real_value = num * _divisor;
+  int int_value = (int)floor(real_value + 0.5);
+
+  switch (_type) {
+  case ST_int8:
+  case ST_uint8:
+  case ST_blob:
+    formatted = string(1, (char)(int_value & 0xff));
+    break;
+
+  case ST_int16:
+  case ST_uint16:
+  case ST_int16array:
+  case ST_uint16array:
+    formatted = 
+      string(1, (char)(int_value & 0xff)) +
+      string(1, (char)((int_value >> 8) & 0xff));
+    break;
+
+  case ST_int32:
+  case ST_uint32:
+  case ST_int32array:
+  case ST_uint32array:
+    formatted = 
+      string(1, (char)(int_value & 0xff)) +
+      string(1, (char)((int_value >> 8) & 0xff)) +
+      string(1, (char)((int_value >> 16) & 0xff)) +
+      string(1, (char)((int_value >> 24) & 0xff));
+    break;
+
+  case ST_int64:
+    // We don't fully support default values for int64.  The
+    // high-order 32 bits cannot be specified.
+    formatted = 
+      string(1, (char)(int_value & 0xff)) +
+      string(1, (char)((int_value >> 8) & 0xff)) +
+      string(1, (char)((int_value >> 16) & 0xff)) +
+      string(1, (char)((int_value >> 24) & 0xff)) +
+      ((int_value & 0x80000000) != 0 ? string(4, '\xff') : string(4, '\0'));
+    break;
+
+  case ST_uint64:
+    // We don't fully support default values for int64.  The
+    // high-order 32 bits cannot be specified.
+    formatted = 
+      string(1, (char)(int_value & 0xff)) +
+      string(1, (char)((int_value >> 8) & 0xff)) +
+      string(1, (char)((int_value >> 16) & 0xff)) +
+      string(1, (char)((int_value >> 24) & 0xff)) +
+      string(4, '\0');
+    break;
+
+  case ST_float64:
+    // This may not be fully portable.
+    formatted = string((char *)&real_value, 8);
+#ifdef IS_BIG_ENDIAN
+    {
+      // Reverse the byte ordering for big-endian machines.
+      string str;
+      str = reserve(8);
+
+      for (size_t i = 0; i < 8; i++) {
+	str += formatted[length - 1 - i];
+      }
+      formatted = str;
+    }
+#endif
+    break;
+
+  case ST_string:
+    // It doesn't make sense to assign a numeric default value to a
+    // string.
+    return false;
+
+  case ST_invalid:
+    break;
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::ElementType::format_default_value
+//       Access: Private
+//  Description: Formats the indicated default value to a sequence of
+//               bytes, according to the element type.  Returns true
+//               if the element type reasonably accepts a string,
+//               false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCAtomicField::ElementType::
+format_default_value(const string &str, string &formatted) const {
+  switch (_type) {
+  case ST_string:
+  case ST_blob:
+    {
+      int length = str.length();
+      formatted = 
+	string(1, (char)(length & 0xff)) +
+	string(1, (char)((length >> 8) & 0xff)) +
+	str;
+    }
+    break;
+
+  default:
+    // It doesn't make sense to assign a string default to a number.
+    return false;
+  }
+
+  return true;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCAtomicField::as_atomic_field
 //     Function: DCAtomicField::as_atomic_field
 //       Access: Public, Virtual
 //       Access: Public, Virtual
@@ -51,6 +324,20 @@ get_element_type(int n) const {
   return _elements[n]._type;
   return _elements[n]._type;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::get_element_name
+//       Access: Public
+//  Description: Returns the name of the nth element of the field.
+//               This name is strictly for documentary purposes; it
+//               does not generally affect operation.  If a name is
+//               not specified, this will be the empty string.
+////////////////////////////////////////////////////////////////////
+string DCAtomicField::
+get_element_name(int n) const {
+  nassertr(n >= 0 && n < (int)_elements.size(), string());
+  return _elements[n]._name;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCAtomicField::get_element_divisor
 //     Function: DCAtomicField::get_element_divisor
 //       Access: Public
 //       Access: Public
@@ -66,6 +353,34 @@ get_element_divisor(int n) const {
   return _elements[n]._divisor;
   return _elements[n]._divisor;
 }
 }
 
 
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::get_element_default
+//       Access: Public
+//  Description: Returns the pre-formatted default value associated
+//               with the nth element of the field.  This is only
+//               valid if has_element_default() returns true, in which
+//               case this string represents the bytes that should be
+//               assigned to the field as a default value.
+////////////////////////////////////////////////////////////////////
+string DCAtomicField::
+get_element_default(int n) const {
+  nassertr(has_element_default(n), string());
+  nassertr(n >= 0 && n < (int)_elements.size(), string());
+  return _elements[n]._default_value;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: DCAtomicField::has_element_default
+//       Access: Public
+//  Description: Returns true if the nth element of the field has a
+//               default value specified, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool DCAtomicField::
+has_element_default(int n) const {
+  nassertr(n >= 0 && n < (int)_elements.size(), false);
+  return _elements[n]._has_default_value;
+}
+
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: DCAtomicField::is_required
 //     Function: DCAtomicField::is_required
 //       Access: Public
 //       Access: Public

+ 18 - 0
direct/src/dcparser/dcAtomicField.h

@@ -25,7 +25,10 @@ PUBLISHED:
 
 
   int get_num_elements() const;
   int get_num_elements() const;
   DCSubatomicType get_element_type(int n) const;
   DCSubatomicType get_element_type(int n) const;
+  string get_element_name(int n) const;
   int get_element_divisor(int n) const;
   int get_element_divisor(int n) const;
+  string get_element_default(int n) const;
+  bool has_element_default(int n) const;
 
 
   bool is_required() const;
   bool is_required() const;
   bool is_broadcast() const;
   bool is_broadcast() const;
@@ -46,8 +49,23 @@ public:
   // definition as read from the file.
   // definition as read from the file.
   class ElementType {
   class ElementType {
   public:
   public:
+    ElementType();
+    bool set_default_value(double num);
+    bool set_default_value(const string &str);
+    void set_default_value_literal(const string &str);
+
+    bool add_default_value(double num);
+    bool end_array();
+
     DCSubatomicType _type;
     DCSubatomicType _type;
+    string _name;
     int _divisor;
     int _divisor;
+    string _default_value;
+    bool _has_default_value;
+
+  private:
+    bool format_default_value(double num, string &formatted) const;
+    bool format_default_value(const string &str, string &formatted) const;
   };
   };
 
 
   typedef vector<ElementType> Elements;
   typedef vector<ElementType> Elements;

+ 76 - 0
direct/src/dcparser/dcLexer.lxx

@@ -188,6 +188,66 @@ scan_quoted_string() {
   return result;
   return result;
 }
 }
 
 
+// scan_hex_string reads a string of hexadecimal digits delimited by
+// angle brackets and returns the representative string.
+static string
+scan_hex_string() {
+  string result;
+
+  // We don't touch the current line number and column number during
+  // scanning, so that if we detect an error while scanning the string
+  // (e.g. an unterminated string), we'll report the error as
+  // occurring at the start of the string, not at the end--somewhat
+  // more convenient for the user.
+
+  // Instead of adjusting the global line_number and col_number
+  // variables, we'll operate on our own local variables for the
+  // interim.
+  int line = line_number;
+  int col = col_number;
+
+  bool odd = false;
+  int last = 0;
+  int c;
+  c = read_char(line, col);
+  while (c != '>' && c != EOF) {
+    int value;
+    if (c >= '0' && c <= '9') {
+      value = c - '0';
+    } else if (c >= 'a' && c <= 'f') {
+      value = c - 'a' + 10;
+    } else if (c >= 'A' && c <= 'F') {
+      value = c - 'A' + 10;
+    } else {
+      line_number = line;
+      col_number = col;
+      dcyyerror("Invalid hex digit.");
+      return string();
+    }
+
+    odd = !odd;
+    if (odd) {
+      last = value;
+    } else {
+      result += (char)((last << 4) | value);
+    }
+    c = read_char(line, col);
+  }
+
+  if (c == EOF) {
+    dcyyerror("This hex string is unterminated.");
+    return string();
+  } else if (odd) {
+    dcyyerror("Odd number of hex digits.");
+    return string();
+  }
+
+  line_number = line;
+  col_number = col;
+
+  return result;
+}
+
 // eat_c_comment scans past all characters up until the first */
 // eat_c_comment scans past all characters up until the first */
 // encountered.
 // encountered.
 static void
 static void
@@ -229,6 +289,7 @@ inline void accept() {
 %}
 %}
 
 
 INTEGERNUM       ([+-]?([0-9]+))
 INTEGERNUM       ([+-]?([0-9]+))
+HEXNUM           0x[0-9a-fA-F]*
 REALNUM          ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
 REALNUM          ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
 
 
 %%
 %%
@@ -403,6 +464,14 @@ mol[0-9]+ {
   return INTEGER; 
   return INTEGER; 
 }
 }
 
 
+{HEXNUM} {
+  // A hexadecimal integer number.
+  accept(); 
+  dcyylval.u.integer = strtoul(yytext+2, NULL, 16);
+  dcyylval.str = yytext;
+  return INTEGER; 
+}
+
 {REALNUM} { 
 {REALNUM} { 
   // A floating-point number.
   // A floating-point number.
   accept(); 
   accept(); 
@@ -418,6 +487,13 @@ mol[0-9]+ {
   return STRING;
   return STRING;
 }
 }
 
 
+[<] {
+  // Long hex string.
+  accept();
+  dcyylval.str = scan_hex_string();
+  return HEX_STRING;
+}
+
 [A-Za-z_][A-Za-z_0-9]* { 
 [A-Za-z_][A-Za-z_0-9]* { 
   // Identifier.
   // Identifier.
   accept();
   accept();

+ 100 - 14
direct/src/dcparser/dcParser.yxx

@@ -23,6 +23,7 @@ static DCFile *dc_file = (DCFile *)NULL;
 static DCClass *current_class = (DCClass *)NULL;
 static DCClass *current_class = (DCClass *)NULL;
 static DCAtomicField *current_atomic = (DCAtomicField *)NULL;
 static DCAtomicField *current_atomic = (DCAtomicField *)NULL;
 static DCMolecularField *current_molecular = (DCMolecularField *)NULL;
 static DCMolecularField *current_molecular = (DCMolecularField *)NULL;
+static DCAtomicField::ElementType atomic_element;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // Defining the interface to the parser.
 // Defining the interface to the parser.
@@ -43,7 +44,7 @@ dc_cleanup_parser() {
 
 
 %token <u.integer> INTEGER
 %token <u.integer> INTEGER
 %token <u.real> REAL
 %token <u.real> REAL
-%token <str> STRING IDENTIFIER
+%token <str> STRING HEX_STRING IDENTIFIER
 
 
 %token KW_DCLASS 
 %token KW_DCLASS 
 
 
@@ -171,27 +172,112 @@ parameter_list:
 	;
 	;
 
 
 nonempty_parameter_list:
 nonempty_parameter_list:
-	subatomic_type
-	| nonempty_parameter_list ',' subatomic_type
+	atomic_element
+	| nonempty_parameter_list ',' atomic_element
 	;
 	;
 
 
-subatomic_type:
-	type_token
+atomic_element:
+	type_token 
 {
 {
-  DCAtomicField::ElementType et;
-  et._type = $1;
-  et._divisor = 1;
-  current_atomic->_elements.push_back(et);
+  atomic_element = DCAtomicField::ElementType();
+  atomic_element._type = $1;
 }
 }
-	| type_token '/' INTEGER
+	atomic_element_definition
 {
 {
-  DCAtomicField::ElementType et;
-  et._type = $1;
-  et._divisor = $3;
-  current_atomic->_elements.push_back(et);
+  current_atomic->_elements.push_back(atomic_element)
 }
 }
 	;
 	;
 
 
+atomic_element_definition:
+	empty
+	| atomic_element_definition '/' INTEGER
+{
+  atomic_element._divisor = $3;
+}
+	| atomic_element_definition IDENTIFIER
+{
+  atomic_element._name = $2;
+}
+	| atomic_element_definition '=' INTEGER
+{
+  if (!atomic_element.set_default_value($3)) {
+    yyerror("Invalid default value: " + $<str>3);
+  }
+}
+	| atomic_element_definition '=' REAL
+{
+  if (!atomic_element.set_default_value($3)) {
+    yyerror("Invalid default value: " + $<str>3);
+  }
+}
+	| atomic_element_definition '=' STRING
+{
+  if (!atomic_element.set_default_value($3)) {
+    yyerror("Invalid default value: \"" + $3 + "\"");
+  }
+}
+	| atomic_element_definition '=' HEX_STRING
+{
+  atomic_element.set_default_value($3);
+}
+	| atomic_element_definition '=' '{' default_array '}'
+{
+  if (!atomic_element.end_array()) {
+    yyerror("Array default value inappropriate");
+  } else {
+    atomic_element._has_default_value = true;
+  }
+}
+	;
+
+default_array:
+	empty
+	| default_array_def maybe_comma
+	;
+
+maybe_comma:
+	empty
+	| ','
+	;
+
+default_array_def:
+	default_array_element
+	| default_array_def ',' default_array_element
+	;
+
+default_array_element:
+	INTEGER
+{
+  if (!atomic_element.add_default_value($1)) {
+    yyerror("Invalid default value: " + $<str>1);
+  }
+}
+	| REAL
+{
+  if (!atomic_element.add_default_value($1)) {
+    yyerror("Invalid default value: " + $<str>1);
+  }
+}
+	| INTEGER '*' INTEGER
+{
+  for (int i = 0; i < $3; i++) {
+    if (!atomic_element.add_default_value($1)) {
+      yyerror("Invalid default value: " + $<str>1);
+      break;
+    }
+  }
+}
+	| REAL '*' INTEGER
+{
+  for (int i = 0; i < $3; i++) {
+    if (!atomic_element.add_default_value($1)) {
+      yyerror("Invalid default value: " + $<str>1);
+      break;
+    }
+  }
+}
+	;  
+
 type_token:
 type_token:
 	KW_INT8
 	KW_INT8
 {
 {

+ 9 - 0
direct/src/dcparser/dcbase.h

@@ -20,6 +20,7 @@
 #include <directbase.h>
 #include <directbase.h>
 #include <notify.h>
 #include <notify.h>
 #include <filename.h>
 #include <filename.h>
+#include <numeric_types.h>
 
 
 #else
 #else
 
 
@@ -75,6 +76,14 @@ using namespace std;
 // string instead.
 // string instead.
 typedef string Filename;
 typedef string Filename;
 
 
+// Panda defines IS_BIG_ENDIAN or IS_LITTLE_ENDIAN as appropriate.
+// Outside of panda, you'll have to do it yourself.  If neither is
+// defined, we'll assume IS_LITTLE_ENDIAN.
+#if !defined(IS_BIG_ENDIAN) && !defined(IS_LITTLE_ENDIAN)
+#define IS_LITTLE_ENDIAN
+#endif
+
+
 #endif  // WITHIN_PANDA
 #endif  // WITHIN_PANDA
 
 
 #endif  // DCBASE_H
 #endif  // DCBASE_H

+ 6 - 9
direct/src/dcparser/hashGenerator.cxx

@@ -7,18 +7,15 @@
 #include "primeNumberGenerator.h"
 #include "primeNumberGenerator.h"
 
 
 // We multiply each consecutive integer by the next prime number and
 // We multiply each consecutive integer by the next prime number and
-// add it to the total, so in theory we will truly generate a unique
-// hash number for each unique sequence of ints, as long as the number
-// of ints does not exceed the number of prime numbers we have, and we
-// do not overflow the limits of a 32-bit integer.
+// add it to the total.  This will generate pretty evenly-distributed
+// hash numbers for an arbitrary sequence of ints.
 
 
 // We do recycle the prime number table at some point, just to keep it
 // We do recycle the prime number table at some point, just to keep it
-// from growing insanely large, however, and we also truncate
-// everything to the low-order 32 bits, so we introduce ambiguity in
-// this way.
+// from growing insanely large, however (and to avoid wasting time
+// computing large prime numbers unnecessarily), and we also truncate
+// the result to the low-order 32 bits.
 
 
 static const int max_prime_numbers = 10000;
 static const int max_prime_numbers = 10000;
-static PrimeNumberGenerator primes;
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 //     Function: HashGenerator::Constructor
 //     Function: HashGenerator::Constructor
@@ -39,7 +36,7 @@ HashGenerator() {
 void HashGenerator::
 void HashGenerator::
 add_int(int num) {
 add_int(int num) {
   nassertv(_index >= 0 && _index < max_prime_numbers);
   nassertv(_index >= 0 && _index < max_prime_numbers);
-  _hash += (int)primes[_index] * num;
+  _hash += _primes[_index] * num;
   _index = (_index + 1) % max_prime_numbers;
   _index = (_index + 1) % max_prime_numbers;
 }
 }
 
 

+ 2 - 0
direct/src/dcparser/hashGenerator.h

@@ -7,6 +7,7 @@
 #define DCHASHGENERATOR_H
 #define DCHASHGENERATOR_H
 
 
 #include "dcbase.h"
 #include "dcbase.h"
+#include "primeNumberGenerator.h"
 
 
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 // 	 Class : HashGenerator
 // 	 Class : HashGenerator
@@ -25,6 +26,7 @@ public:
 private:
 private:
   long _hash;
   long _hash;
   int _index;
   int _index;
+  PrimeNumberGenerator _primes;
 };
 };
 
 
 #endif
 #endif