*** empty log message ***

This commit is contained in:
David Rose 2001-03-23 01:16:03 +00:00
parent c47d83286d
commit 121fb2faa3
9 changed files with 530 additions and 26 deletions

View File

@ -3,8 +3,8 @@
dclass Movable {
// 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
set_xyzhpr : set_xyz, set_hpr;
@ -14,7 +14,7 @@ dclass Movable {
dclass Attitude : Movable {
// 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.
set_xyzhprattitude : set_xyz, set_hpr, set_attitude;

View File

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

View File

@ -7,6 +7,7 @@
#include "hashGenerator.h"
#include "dcindent.h"
#include <math.h>
ostream &
operator << (ostream &out, const DCAtomicField::ElementType &et) {
@ -14,9 +15,281 @@ operator << (ostream &out, const DCAtomicField::ElementType &et) {
if (et._divisor != 1) {
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;
}
////////////////////////////////////////////////////////////////////
// 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
// Access: Public, Virtual
@ -51,6 +324,20 @@ get_element_type(int n) const {
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
// Access: Public
@ -66,6 +353,34 @@ get_element_divisor(int n) const {
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
// Access: Public

View File

@ -25,7 +25,10 @@ PUBLISHED:
int get_num_elements() const;
DCSubatomicType get_element_type(int n) const;
string get_element_name(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_broadcast() const;
@ -46,8 +49,23 @@ public:
// definition as read from the file.
class ElementType {
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;
string _name;
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;

View File

@ -188,6 +188,66 @@ scan_quoted_string() {
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 */
// encountered.
static void
@ -229,6 +289,7 @@ inline void accept() {
%}
INTEGERNUM ([+-]?([0-9]+))
HEXNUM 0x[0-9a-fA-F]*
REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
%%
@ -403,6 +464,14 @@ mol[0-9]+ {
return INTEGER;
}
{HEXNUM} {
// A hexadecimal integer number.
accept();
dcyylval.u.integer = strtoul(yytext+2, NULL, 16);
dcyylval.str = yytext;
return INTEGER;
}
{REALNUM} {
// A floating-point number.
accept();
@ -418,6 +487,13 @@ mol[0-9]+ {
return STRING;
}
[<] {
// Long hex string.
accept();
dcyylval.str = scan_hex_string();
return HEX_STRING;
}
[A-Za-z_][A-Za-z_0-9]* {
// Identifier.
accept();

View File

@ -23,6 +23,7 @@ static DCFile *dc_file = (DCFile *)NULL;
static DCClass *current_class = (DCClass *)NULL;
static DCAtomicField *current_atomic = (DCAtomicField *)NULL;
static DCMolecularField *current_molecular = (DCMolecularField *)NULL;
static DCAtomicField::ElementType atomic_element;
////////////////////////////////////////////////////////////////////
// Defining the interface to the parser.
@ -43,7 +44,7 @@ dc_cleanup_parser() {
%token <u.integer> INTEGER
%token <u.real> REAL
%token <str> STRING IDENTIFIER
%token <str> STRING HEX_STRING IDENTIFIER
%token KW_DCLASS
@ -171,27 +172,112 @@ 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:
KW_INT8
{

View File

@ -20,6 +20,7 @@
#include <directbase.h>
#include <notify.h>
#include <filename.h>
#include <numeric_types.h>
#else
@ -75,6 +76,14 @@ using namespace std;
// string instead.
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 // DCBASE_H

View File

@ -7,18 +7,15 @@
#include "primeNumberGenerator.h"
// 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
// 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 PrimeNumberGenerator primes;
////////////////////////////////////////////////////////////////////
// Function: HashGenerator::Constructor
@ -39,7 +36,7 @@ HashGenerator() {
void HashGenerator::
add_int(int num) {
nassertv(_index >= 0 && _index < max_prime_numbers);
_hash += (int)primes[_index] * num;
_hash += _primes[_index] * num;
_index = (_index + 1) % max_prime_numbers;
}

View File

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