Browse Source

begin work on xfile parser

David Rose 21 years ago
parent
commit
7d2b0346ac
51 changed files with 2691 additions and 31 deletions
  1. 1 1
      pandatool/src/ptloader/Sources.pp
  2. 28 28
      pandatool/src/xfile/Sources.pp
  3. 9 0
      pandatool/src/xfile/config_xfile.cxx
  4. 108 0
      pandatool/src/xfile/standardTemplates.x
  5. 122 0
      pandatool/src/xfile/windowsGuid.I
  6. 86 0
      pandatool/src/xfile/windowsGuid.cxx
  7. 66 0
      pandatool/src/xfile/windowsGuid.h
  8. 18 0
      pandatool/src/xfile/xFile.I
  9. 361 0
      pandatool/src/xfile/xFile.cxx
  10. 89 0
      pandatool/src/xfile/xFile.h
  11. 79 0
      pandatool/src/xfile/xFileArrayDef.I
  12. 34 0
      pandatool/src/xfile/xFileArrayDef.cxx
  13. 53 0
      pandatool/src/xfile/xFileArrayDef.h
  14. 32 0
      pandatool/src/xfile/xFileDataDef.I
  15. 126 0
      pandatool/src/xfile/xFileDataDef.cxx
  16. 90 0
      pandatool/src/xfile/xFileDataDef.h
  17. 18 0
      pandatool/src/xfile/xFileNode.I
  18. 96 0
      pandatool/src/xfile/xFileNode.cxx
  19. 78 0
      pandatool/src/xfile/xFileNode.h
  20. 18 0
      pandatool/src/xfile/xFileTemplate.I
  21. 53 0
      pandatool/src/xfile/xFileTemplate.cxx
  22. 65 0
      pandatool/src/xfile/xFileTemplate.h
  23. 107 0
      pandatool/src/xfile/xFileTrans.cxx
  24. 46 0
      pandatool/src/xfile/xFileTrans.h
  25. 540 0
      pandatool/src/xfile/xLexer.lxx
  26. 33 0
      pandatool/src/xfile/xLexerDefs.h
  27. 237 0
      pandatool/src/xfile/xParser.yxx
  28. 57 0
      pandatool/src/xfile/xParserDefs.h
  29. 34 0
      pandatool/src/xfileegg/Sources.pp
  30. 0 0
      pandatool/src/xfileegg/xFileAnimationSet.cxx
  31. 0 0
      pandatool/src/xfileegg/xFileAnimationSet.h
  32. 0 0
      pandatool/src/xfileegg/xFileFace.cxx
  33. 0 0
      pandatool/src/xfileegg/xFileFace.h
  34. 0 0
      pandatool/src/xfileegg/xFileMaker.cxx
  35. 0 0
      pandatool/src/xfileegg/xFileMaker.h
  36. 0 0
      pandatool/src/xfileegg/xFileMaterial.cxx
  37. 0 0
      pandatool/src/xfileegg/xFileMaterial.h
  38. 0 0
      pandatool/src/xfileegg/xFileMesh.cxx
  39. 0 0
      pandatool/src/xfileegg/xFileMesh.h
  40. 0 0
      pandatool/src/xfileegg/xFileNormal.cxx
  41. 0 0
      pandatool/src/xfileegg/xFileNormal.h
  42. 0 0
      pandatool/src/xfileegg/xFileTemplates.cxx
  43. 0 0
      pandatool/src/xfileegg/xFileTemplates.h
  44. 0 0
      pandatool/src/xfileegg/xFileToEggConverter.cxx
  45. 0 0
      pandatool/src/xfileegg/xFileToEggConverter.h
  46. 0 0
      pandatool/src/xfileegg/xFileVertex.cxx
  47. 0 0
      pandatool/src/xfileegg/xFileVertex.h
  48. 0 0
      pandatool/src/xfileegg/xFileVertexPool.h
  49. 0 0
      pandatool/src/xfileegg/xfileegg_composite1.cxx
  50. 2 2
      pandatool/src/xfileprogs/Sources.pp
  51. 5 0
      pandatool/src/xfileprogs/xFileToEgg.cxx

+ 1 - 1
pandatool/src/ptloader/Sources.pp

@@ -2,7 +2,7 @@
   #define TARGET ptloader
   #define TARGET ptloader
   #define BUILDING_DLL BUILDING_PTLOADER
   #define BUILDING_DLL BUILDING_PTLOADER
   #define LOCAL_LIBS \
   #define LOCAL_LIBS \
-    fltegg flt lwoegg lwo dxfegg dxf vrmlegg pvrml xfile \
+    fltegg flt lwoegg lwo dxfegg dxf vrmlegg pvrml xfileegg xfile \
     converter pandatoolbase
     converter pandatoolbase
   #define OTHER_LIBS \
   #define OTHER_LIBS \
     egg2pg:c builder:c egg:c pandaegg:m \
     egg2pg:c builder:c egg:c pandaegg:m \

+ 28 - 28
pandatool/src/xfile/Sources.pp

@@ -1,36 +1,36 @@
-
-// The .x converter takes advantage of the DirectX API's; therefore,
-// it can only be built if we have DX available (and therefore it only
-// builds on Windows--sorry).
-#define BUILD_DIRECTORY $[HAVE_DX]
-#define USE_PACKAGES dx
+#define YACC_PREFIX xyy
+#define LFLAGS -i
 
 
 #begin ss_lib_target
 #begin ss_lib_target
   #define TARGET xfile
   #define TARGET xfile
-  #define LOCAL_LIBS eggbase progbase pandatoolbase
+  #define LOCAL_LIBS pandatoolbase
   #define OTHER_LIBS \
   #define OTHER_LIBS \
-    egg:c pandaegg:m \
-    mathutil:c linmath:c putil:c panda:m \
-    express:c pandaexpress:m \
-    dtoolconfig dtool pystub \
-
-  #define WIN_SYS_LIBS \
-    d3dxof.lib dxguid.lib d3d8.lib d3dx8.lib dxerr8.lib
-    
-  #define COMBINED_SOURCES $[TARGET]_composite1.cxx     
+    mathutil:c linmath:c panda:m \
+    dtoolbase:c dtool:m
     
     
   #define SOURCES \
   #define SOURCES \
-     config_xfile.h \
-     xFileAnimationSet.h \
-     xFileFace.h xFileMaker.h xFileMaterial.h \
-     xFileMesh.h xFileNormal.h xFileTemplates.h \
-     xFileToEggConverter.h xFileVertex.h 
-
-  #define INCLUDED_SOURCES \
-     config_xfile.cxx \
-     xFileAnimationSet.cxx \
-     xFileFace.cxx xFileMaker.cxx xFileMaterial.cxx \
-     xFileMesh.cxx xFileNormal.cxx xFileTemplates.cxx \
-     xFileToEggConverter.cxx xFileVertex.cxx 
+     config_xfile.h config_xfile.cxx \
+     windowsGuid.cxx windowsGuid.h \
+     xLexer.lxx xLexerDefs.h \
+     xParser.yxx xParserDefs.h \
+     xFile.cxx xFile.I xFile.h \
+     xFileArrayDef.cxx xFileArrayDef.I xFileArrayDef.h \
+     xFileDataDef.cxx xFileDataDef.I xFileDataDef.h \
+     xFileNode.cxx xFileNode.I xFileNode.h \
+     xFileTemplate.cxx xFileTemplate.I xFileTemplate.h
 
 
 #end ss_lib_target
 #end ss_lib_target
+
+#begin test_bin_target
+  #define TARGET x-trans
+  #define LOCAL_LIBS \
+    progbase xfile
+  #define OTHER_LIBS \
+    linmath:c panda:m \
+    express:c pandaexpress:m \
+    dtoolutil:c dtoolbase:c dconfig:c dtoolconfig:m dtool:m pystub
+
+  #define SOURCES \
+    xFileTrans.cxx xFileTrans.h
+
+#end test_bin_target

+ 9 - 0
pandatool/src/xfile/config_xfile.cxx

@@ -17,6 +17,10 @@
 ////////////////////////////////////////////////////////////////////
 ////////////////////////////////////////////////////////////////////
 
 
 #include "config_xfile.h"
 #include "config_xfile.h"
+#include "xFile.h"
+#include "xFileDataDef.h"
+#include "xFileNode.h"
+#include "xFileTemplate.h"
 
 
 #include "dconfig.h"
 #include "dconfig.h"
 
 
@@ -48,5 +52,10 @@ init_libxfile() {
     return;
     return;
   }
   }
   initialized = true;
   initialized = true;
+
+  XFile::init_type();
+  XFileDataDef::init_type();
+  XFileNode::init_type();
+  XFileTemplate::init_type();
 }
 }
 
 

+ 108 - 0
pandatool/src/xfile/standardTemplates.x

@@ -0,0 +1,108 @@
+xof 0303txt 0032
+
+template Header {
+ <3d82ab43-62da-11cf-ab39-0020af71e433>
+ WORD major;
+ WORD minor;
+ DWORD flags;
+}
+
+template Coords2d {
+ <f6f23f44-7686-11cf-8f52-0040333594a3>
+ FLOAT u;
+ FLOAT v;
+}
+
+template Vector {
+ <3d82ab5e-62da-11cf-ab39-0020af71e433>
+ FLOAT x;
+ FLOAT y;
+ FLOAT z;
+}
+
+template ColorRGBA {
+ <35ff44e0-6c7c-11cf-8f52-0040333594a3>
+ FLOAT red;
+ FLOAT green;
+ FLOAT blue;
+ FLOAT alpha;
+}
+
+template ColorRGB {
+ <d3e16e81-7835-11cf-8f52-0040333594a3>
+ FLOAT red;
+ FLOAT green;
+ FLOAT blue;
+}
+
+template IndexedColor {
+ <1630b820-7842-11cf-8f52-0040333594a3>
+ DWORD index;
+ ColorRGBA indexColor;
+}
+
+template TextureFilename {
+ <a42790e1-7810-11cf-8f52-0040333594a3>
+ STRING filename;
+}
+
+template Matrix4x4 {
+ <f6f23f45-7686-11cf-8f52-0040333594a3>
+ array FLOAT matrix[16];
+}
+
+template Material {
+ <3d82ab4d-62da-11cf-ab39-0020af71e433>
+ ColorRGBA faceColor;
+ FLOAT power;
+ ColorRGB specularColor;
+ ColorRGB emissiveColor;
+ [...]
+}
+
+template MeshFace {
+ <3d82ab5f-62da-11cf-ab39-0020af71e433>
+ DWORD nFaceVertexIndices;
+ array DWORD faceVertexIndices[nFaceVertexIndices];
+}
+
+template Mesh {
+ <3d82ab44-62da-11cf-ab39-0020af71e433>
+ DWORD nVertices;
+ array Vector vertices[nVertices];
+ DWORD nFaces;
+ array MeshFace faces[nFaces];
+ [...]
+}
+
+template MeshNormals {
+ <f6f23f43-7686-11cf-8f52-0040333594a3>
+ DWORD nNormals;
+ array Vector normals[nNormals];
+ DWORD nFaceNormals;
+ array MeshFace faceNormals[nFaceNormals];
+}
+
+template MeshTextureCoords {
+ <f6f23f40-7686-11cf-8f52-0040333594a3>
+ DWORD nTextureCoords;
+ array Coords2d textureCoords[nTextureCoords];
+}
+
+template MeshMaterialList {
+ <f6f23f42-7686-11cf-8f52-0040333594a3>
+ DWORD nMaterials;
+ DWORD nFaceIndexes;
+ array DWORD faceIndexes[nFaceIndexes];
+ [Material <3d82ab4d-62da-11cf-ab39-0020af71e433>]
+}
+
+template FrameTransformMatrix {
+ <f6f23f41-7686-11cf-8f52-0040333594a3>
+ Matrix4x4 frameMatrix;
+}
+
+template Frame {
+ <3d82ab46-62da-11cf-ab39-0020af71e433>
+ [...]
+}

+ 122 - 0
pandatool/src/xfile/windowsGuid.I

@@ -0,0 +1,122 @@
+// Filename: windowsGuid.I
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE WindowsGuid::
+WindowsGuid() {
+  memset(this, 0, sizeof(WindowsGuid));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE WindowsGuid::
+WindowsGuid(unsigned long data1, 
+            unsigned short data2, unsigned short data3,
+            unsigned char b1, unsigned char b2, unsigned char b3, 
+            unsigned char b4, unsigned char b5, unsigned char b6, 
+            unsigned char b7, unsigned char b8) :
+  _data1(data1),
+  _data2(data2),
+  _data3(data3),
+  _b1(b1),
+  _b2(b2),
+  _b3(b3),
+  _b4(b4),
+  _b5(b5),
+  _b6(b6),
+  _b7(b7),
+  _b8(b8)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::Copy Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE WindowsGuid::
+WindowsGuid(const WindowsGuid &copy) {
+  (*this) = copy;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::Copy Assignment Operator
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE void WindowsGuid::
+operator = (const WindowsGuid &copy) {
+  memcpy(this, &copy, sizeof(WindowsGuid));
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::operator ==
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool WindowsGuid::
+operator == (const WindowsGuid &other) const {
+  return compare_to(other) == 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::operator !=
+//       Access: Published
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE bool WindowsGuid::
+operator != (const WindowsGuid &other) const {
+  return compare_to(other) != 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::operator <
+//       Access: Published
+//  Description: 
+////////////////////////////////////////////////////////////////////
+INLINE bool WindowsGuid::
+operator < (const WindowsGuid &other) const {
+  return compare_to(other) < 0;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::compare_to
+//       Access: Published
+//  Description: Returns a number less than zero if this WindowsGuid
+//               sorts before the other one, greater than zero if it
+//               sorts after, or zero if they are equivalent.
+////////////////////////////////////////////////////////////////////
+INLINE int WindowsGuid::
+compare_to(const WindowsGuid &other) const {
+  return memcmp(this, &other, sizeof(WindowsGuid));
+}
+
+INLINE ostream &
+operator << (ostream &out, const WindowsGuid &guid) {
+  guid.output(out);
+  return out;
+}
+

+ 86 - 0
pandatool/src/xfile/windowsGuid.cxx

@@ -0,0 +1,86 @@
+// Filename: windowsGuid.cxx
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "windowsGuid.h"
+#include "notify.h"
+
+#include <stdio.h>  // for sscanf, sprintf
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::parse_string
+//       Access: Public
+//  Description: Parses the hex representation in the indicated string
+//               and stores it in the WindowsGuid object.  Returns
+//               true if successful, false if the string
+//               representation is malformed.
+////////////////////////////////////////////////////////////////////
+bool WindowsGuid::
+parse_string(const string &str) {
+  long data1;
+  short data2, data3;
+  short b1, b2, b3, b4, b5, b6, b7, b8;
+  int result = sscanf(str.c_str(),
+                      "%08lx-%04hx-%04hx-%02x%02x-%02x%02x%02x%02x%02x%02x",
+                      &data1, &data2, &data3,
+                      &b1, &b2, &b3, &b4, &b5, &b6, &b7, &b8);
+  if (result != 11) {
+    return false;
+  }
+
+  _data1 = data1;
+  _data2 = data2;
+  _data3 = data3;
+  _b1 = b1;
+  _b2 = b2;
+  _b3 = b3;
+  _b4 = b4;
+  _b5 = b5;
+  _b6 = b6;
+  _b7 = b7;
+  _b8 = b8;
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::format_string
+//       Access: Public
+//  Description: Returns a hex representation of the GUID.
+////////////////////////////////////////////////////////////////////
+string WindowsGuid::
+format_string() const {
+  static const int buf_length = 128;  // Actually, we only need 36 + 1 == 37.
+  char buffer[buf_length];
+  sprintf(buffer, 
+          "%08lx-%04hx-%04hx-%02x%02x-%02x%02x%02x%02x%02x%02x",
+          _data1, _data2, _data3,
+          _b1, _b2, _b3, _b4, _b5, _b6, _b7, _b8);
+  nassertr(strlen(buffer) < buf_length, string());
+
+  return string(buffer);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: WindowsGuid::output
+//       Access: Public
+//  Description: Outputs a hex representation of the GUID.
+////////////////////////////////////////////////////////////////////
+void WindowsGuid::
+output(ostream &out) const {
+  out << format_string();
+}

+ 66 - 0
pandatool/src/xfile/windowsGuid.h

@@ -0,0 +1,66 @@
+// Filename: windowsGuid.h
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef WINDOWS_GUID_H
+#define WINDOWS_GUID_H
+
+#include "pandatoolbase.h"
+
+#include <string.h>  // For memcpy, memcmp
+
+////////////////////////////////////////////////////////////////////
+//       Class : WindowsGuid
+// Description : This is an implementation of the Windows GUID object,
+//               used everywhere as a world-unique identifier for
+//               anything and everything.  In particular, it's used in
+//               the X file format to identify standard templates.
+////////////////////////////////////////////////////////////////////
+class WindowsGuid {
+public:
+  INLINE WindowsGuid();
+  INLINE WindowsGuid(unsigned long data1, 
+                     unsigned short data2, unsigned short data3,
+                     unsigned char b1, unsigned char b2, unsigned char b3, 
+                     unsigned char b4, unsigned char b5, unsigned char b6, 
+                     unsigned char b7, unsigned char b8);
+  INLINE WindowsGuid(const WindowsGuid &copy);
+  INLINE void operator = (const WindowsGuid &copy);
+
+  INLINE bool operator == (const WindowsGuid &other) const;
+  INLINE bool operator != (const WindowsGuid &other) const;
+  INLINE bool operator < (const WindowsGuid &other) const;
+  INLINE int compare_to(const WindowsGuid &other) const;
+
+  bool parse_string(const string &str);
+  string format_string() const;
+
+  void output(ostream &out) const;
+
+private:
+  unsigned long _data1;
+  unsigned short _data2;
+  unsigned short _data3;
+  unsigned char _b1, _b2, _b3, _b4, _b5, _b6, _b7, _b8;
+};
+
+INLINE ostream &operator << (ostream &out, const WindowsGuid &guid);
+
+#include "windowsGuid.I"
+
+#endif
+

+ 18 - 0
pandatool/src/xfile/xFile.I

@@ -0,0 +1,18 @@
+// Filename: xFile.I
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+

+ 361 - 0
pandatool/src/xfile/xFile.cxx

@@ -0,0 +1,361 @@
+// Filename: xFile.cxx
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "xFile.h"
+#include "xParserDefs.h"
+#include "xLexerDefs.h"
+#include "config_xfile.h"
+#include "config_express.h"
+#include "virtualFileSystem.h"
+
+TypeHandle XFile::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+XFile::
+XFile() : XFileNode("xfile") {
+  _major_version = 1;
+  _minor_version = 1;
+  _format_type = FT_text;
+  _float_size = FS_64;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::Destructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+XFile::
+~XFile() {
+  clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::add_child
+//       Access: Public, Virtual
+//  Description: Adds the indicated node as a child of this node.
+////////////////////////////////////////////////////////////////////
+void XFile::
+add_child(XFileNode *node) {
+  XFileNode::add_child(node);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::clear
+//       Access: Public, Virtual
+//  Description: Removes all of the classes defined within the XFile
+//               and prepares it for reading a new file.
+////////////////////////////////////////////////////////////////////
+void XFile::
+clear() {
+  XFileNode::clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::read
+//       Access: Public
+//  Description: Opens and reads the indicated .x file by name.  The
+//               nodes and templates defined in the file will be
+//               appended to the set of nodes already recorded, if
+//               any.
+//
+//               Returns true if the file is successfully read, false
+//               if there was an error (in which case the file might
+//               have been partially read).
+////////////////////////////////////////////////////////////////////
+bool XFile::
+read(Filename filename) {
+  ifstream in;
+
+  filename.set_text();
+  if (use_vfs) {
+    VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
+    istream *in = vfs->open_read_file(filename);
+    if (in == (istream *)NULL) {
+      xfile_cat.error()
+        << "Cannot open " << filename << " for reading.\n";
+      return false;
+    }
+    bool okflag = read(*in, filename);
+    delete in;
+    return okflag;
+
+  } else {
+    filename.open_read(in);
+
+    if (!in) {
+      xfile_cat.error()
+        << "Cannot open " << filename << " for reading.\n";
+      return false;
+    }
+    
+    return read(in, filename);
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::read
+//       Access: Public
+//  Description: Parses the already-opened input stream for
+//               distributed class descriptions.  The filename
+//               parameter is optional and is only used when reporting
+//               errors.
+//
+//               The distributed classes defined in the file will be
+//               appended to the set of distributed classes already
+//               recorded, if any.
+//
+//               Returns true if the file is successfully read, false
+//               if there was an error (in which case the file might
+//               have been partially read).
+////////////////////////////////////////////////////////////////////
+bool XFile::
+read(istream &in, const string &filename) {
+  if (!read_header(in)) {
+    return false;
+  }
+
+  if (_format_type != FT_text) {
+    // Does anyone actually use the binary format?  It wouldn't be too
+    // hard to support it if there were any reason at all to do so.
+    xfile_cat.error()
+      << "Cannot read binary .x files at this time.\n";
+    return false;
+  }
+
+  x_init_parser(in, filename, *this);
+  xyyparse();
+  x_cleanup_parser();
+
+  return (x_error_count() == 0);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::write
+//       Access: Public
+//  Description: Opens the indicated filename for output and writes a
+//               parseable description of all the known distributed
+//               classes to the file.
+//
+//               Returns true if the description is successfully
+//               written, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool XFile::
+write(Filename filename) const {
+  ofstream out;
+
+  // We actually open the file to write in binary mode, to avoid the
+  // MS-DOS newline characters (since Windows seems to do this too).
+  filename.set_binary();
+  filename.open_write(out);
+
+  if (!out) {
+    xfile_cat.error()
+      << "Can't open " << filename << " for output.\n";
+    return false;
+  }
+
+  return write(out);
+}
+
+////////////////////////////////////////////////////////////////////
+//     function: XFile::write
+//       Access: Public
+//  Description: Writes a parseable description of all the known
+//               nodes and templates to the stream.
+//
+//               Returns true if the description is successfully
+//               written, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool XFile::
+write(ostream &out) const {
+  if (!write_header(out)) {
+    return false;
+  }
+
+  write_text(out, 0);
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::write_text
+//       Access: Public, Virtual
+//  Description: Writes a suitable representation of this node to an
+//               .x file in text mode.
+////////////////////////////////////////////////////////////////////
+void XFile::
+write_text(ostream &out, int indent_level) const {
+  Children::const_iterator ci;
+  for (ci = _children.begin(); ci != _children.end(); ++ci) {
+    (*ci)->write_text(out, indent_level);
+    out << "\n";
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::read_header
+//       Access: Private
+//  Description: Reads the header and magic number associated with the
+//               file.  Returns true on success, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool XFile::
+read_header(istream &in) {
+  char magic[4];
+  if (!in.read(magic, 4)) {
+    xfile_cat.error()
+      << "Empty file.\n";
+    return false;
+  }
+
+  if (memcmp(magic, "xof ", 4) != 0) {
+    xfile_cat.error()
+      << "Not a DirectX file.\n";
+    return false;
+  }
+
+  char version[4];
+  if (!in.read(version, 4)) {
+    xfile_cat.error()
+      << "Truncated file.\n";
+    return false;
+  }
+  _major_version = (version[0] - '0') * 10 + (version[1] - '0');
+  _minor_version = (version[2] - '0') * 10 + (version[3] - '0');
+
+  char format[4];
+  if (!in.read(format, 4)) {
+    xfile_cat.error()
+      << "Truncated file.\n";
+    return false;
+  }
+
+  if (memcmp(format, "txt ", 4) == 0) {
+    _format_type = FT_text;
+
+  } else if (memcmp(format, "bin ", 4) == 0) {
+    _format_type = FT_binary;
+
+  } else if (memcmp(format, "com ", 4) == 0) {
+    _format_type = FT_compressed;
+
+  } else {
+    xfile_cat.error()
+      << "Unknown format type: " << string(format, 4) << "\n";
+    return false;
+  }
+
+  if (_format_type == FT_compressed) {
+    // Read and ignore the compression type, since we don't support
+    // compression anyway.
+    char compression_type[4];
+    in.read(compression_type, 4);
+  }
+
+  char float_size[4];
+  if (!in.read(float_size, 4)) {
+    xfile_cat.error()
+      << "Truncated file.\n";
+    return false;
+  }
+
+  if (memcmp(float_size, "0032", 4) == 0) {
+    _float_size = FS_32;
+
+  } else if (memcmp(float_size, "0064", 4) == 0) {
+    _float_size = FS_64;
+
+  } else {
+    xfile_cat.error()
+      << "Unknown float size: " << string(float_size, 4) << "\n";
+    return false;
+  }
+
+  return true;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFile::write_header
+//       Access: Private
+//  Description: Writes the header and magic number associated with the
+//               file.  Returns true on success, false otherwise.
+////////////////////////////////////////////////////////////////////
+bool XFile::
+write_header(ostream &out) const {
+  out.write("xof ", 4);
+
+  char buffer[128];
+  sprintf(buffer, "%02d%02d", _major_version, _minor_version);
+  if (strlen(buffer) != 4) {
+    xfile_cat.error()
+      << "Invalid version: " << _major_version << "." << _minor_version
+      << "\n";
+    return false;
+  }
+
+  out.write(buffer, 4);
+
+  switch (_format_type) {
+  case FT_text:
+    out.write("txt ", 4);
+    break;
+ 
+  case FT_binary:
+    out.write("bin ", 4);
+    break;
+  
+  case FT_compressed:
+    out.write("cmp ", 4);
+    break;
+
+  default:
+    xfile_cat.error()
+      << "Invalid format type: " << _format_type << "\n";
+    return false;
+  }
+
+  if (_format_type == FT_compressed) {
+    // Write a bogus compression type, just so we have a valid header.
+    out.write("xxx ", 4);
+  }
+
+  switch (_float_size) {
+  case FS_32:
+    out.write("0032", 4);
+    break;
+ 
+  case FS_64:
+    out.write("0064", 4);
+    break;
+
+  default:
+    xfile_cat.error()
+      << "Invalid float size: " << _float_size << "\n";
+    return false;
+  }
+
+  if (_format_type == FT_text) {
+    // If it's a text format, we can now write a newline.
+    out << "\n";
+  }
+
+  return true;
+}

+ 89 - 0
pandatool/src/xfile/xFile.h

@@ -0,0 +1,89 @@
+// Filename: xFile.h
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef XFILE_H
+#define XFILE_H
+
+#include "pandatoolbase.h"
+#include "xFileNode.h"
+
+#include "filename.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : XFile
+// Description : This represents the complete contents of an X file
+//               (file.x) in memory.  It may be read or written from
+//               or to a disk file.
+////////////////////////////////////////////////////////////////////
+class XFile : public XFileNode {
+public:
+  XFile();
+  ~XFile();
+
+  virtual void add_child(XFileNode *node);
+  virtual void clear();
+
+  bool read(Filename filename);
+  bool read(istream &in, const string &filename = string());
+
+  bool write(Filename filename) const;
+  bool write(ostream &out) const;
+
+  virtual void write_text(ostream &out, int indent_level) const;
+
+  enum FormatType {
+    FT_text,
+    FT_binary,
+    FT_compressed,
+  };
+  enum FloatSize {
+    FS_32,
+    FS_64,
+  };
+
+private:
+  bool read_header(istream &in);
+  bool write_header(ostream &out) const;
+
+  int _major_version, _minor_version;
+  FormatType _format_type;
+  FloatSize _float_size;
+  
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    XFileNode::init_type();
+    register_type(_type_handle, "XFile",
+                  XFileNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "xFile.I"
+
+#endif
+
+

+ 79 - 0
pandatool/src/xfile/xFileArrayDef.I

@@ -0,0 +1,79 @@
+// Filename: xFileArrayDef.I
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileArrayDef::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE XFileArrayDef::
+XFileArrayDef(int fixed_size) :
+  _fixed_size(fixed_size),
+  _dynamic_size(NULL)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileArrayDef::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE XFileArrayDef::
+XFileArrayDef(XFileDataDef *dynamic_size) :
+  _fixed_size(0),
+  _dynamic_size(dynamic_size)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileArrayDef::is_fixed_size
+//       Access: Public
+//  Description: Returns true if this array definition specifies a
+//               const-size array, false if it is a dynamic-size
+//               array.
+////////////////////////////////////////////////////////////////////
+INLINE bool XFileArrayDef::
+is_fixed_size() const {
+  return (_dynamic_size == (XFileDataDef *)NULL);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileArrayDef::get_fixed_size
+//       Access: Public
+//  Description: Returns the const size of the array, if
+//               is_fixed_size() returned true.
+////////////////////////////////////////////////////////////////////
+INLINE int XFileArrayDef::
+get_fixed_size() const {
+  nassertr(is_fixed_size(), 0);
+  return _fixed_size;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileArrayDef::get_dynamic_size
+//       Access: Public
+//  Description: Returns the data element that names the dynamic size
+//               of the array, if is_fixed_size() returned false.
+////////////////////////////////////////////////////////////////////
+INLINE XFileDataDef *XFileArrayDef::
+get_dynamic_size() const {
+  nassertr(!is_fixed_size(), NULL);
+  return _dynamic_size;
+}
+

+ 34 - 0
pandatool/src/xfile/xFileArrayDef.cxx

@@ -0,0 +1,34 @@
+// Filename: xFileArrayDef.cxx
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "xFileArrayDef.h"
+#include "xFileDataDef.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileArrayDef::output
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void XFileArrayDef::
+output(ostream &out) const {
+  if (is_fixed_size()) {
+    out << "[" << _fixed_size << "]";
+  } else {
+    out << "[" << _dynamic_size->get_name() << "]";
+  }
+}

+ 53 - 0
pandatool/src/xfile/xFileArrayDef.h

@@ -0,0 +1,53 @@
+// Filename: xFileArrayDef.h
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef XFILEARRAYDEF_H
+#define XFILEARRAYDEF_H
+
+#include "pandatoolbase.h"
+#include "notify.h"
+
+class XFileDataDef;
+
+////////////////////////////////////////////////////////////////////
+//       Class : XFileArrayDef
+// Description : Defines one level of array bounds for an associated
+//               XFileDataDef element.
+////////////////////////////////////////////////////////////////////
+class XFileArrayDef {
+public:
+  INLINE XFileArrayDef(int fixed_size);
+  INLINE XFileArrayDef(XFileDataDef *dynamic_size);
+
+  INLINE bool is_fixed_size() const;
+  INLINE int get_fixed_size() const;
+  INLINE XFileDataDef *get_dynamic_size() const;
+
+  void output(ostream &out) const;
+
+private:
+  int _fixed_size;
+  XFileDataDef *_dynamic_size;
+};
+
+#include "xFileArrayDef.I"
+
+#endif
+  
+
+

+ 32 - 0
pandatool/src/xfile/xFileDataDef.I

@@ -0,0 +1,32 @@
+// Filename: xFileDataDef.I
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileDataDef::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+INLINE XFileDataDef::
+XFileDataDef(XFileDataDef::Type type, const string &name, 
+             XFileTemplate *xtemplate) :
+  XFileNode(name),
+  _type(type),
+  _template(xtemplate)
+{
+}

+ 126 - 0
pandatool/src/xfile/xFileDataDef.cxx

@@ -0,0 +1,126 @@
+// Filename: xFileDataDef.cxx
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "xFileDataDef.h"
+#include "indent.h"
+
+TypeHandle XFileDataDef::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileDataDef::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+XFileDataDef::
+~XFileDataDef() {
+  clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileDataDef::clear
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void XFileDataDef::
+clear() {
+  XFileNode::clear();
+  _array_def.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileDataDef::add_array_def
+//       Access: Public
+//  Description: Adds an additional array dimension to the data
+//               description.
+////////////////////////////////////////////////////////////////////
+void XFileDataDef::
+add_array_def(const XFileArrayDef &array_def) {
+  _array_def.push_back(array_def);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileDataDef::write_text
+//       Access: Public, Virtual
+//  Description: Writes a suitable representation of this node to an
+//               .x file in text mode.
+////////////////////////////////////////////////////////////////////
+void XFileDataDef::
+write_text(ostream &out, int indent_level) const {
+  indent(out, indent_level);
+
+  if (!_array_def.empty()) {
+    out << "array ";
+  }
+
+  switch (_type) {
+  case T_word:
+    out << "WORD";
+    break;
+
+  case T_dword:
+    out << "DWORD";
+    break;
+
+  case T_float:
+    out << "FLOAT";
+    break;
+
+  case T_double:
+    out << "DOUBLE";
+    break;
+
+  case T_char:
+    out << "CHAR";
+    break;
+
+  case T_uchar:
+    out << "UCHAR";
+    break;
+
+  case T_byte:
+    out << "BYTE";
+    break;
+
+  case T_string:
+    out << "STRING";
+    break;
+
+  case T_cstring:
+    out << "CSTRING";
+    break;
+
+  case T_unicode:
+    out << "UNICODE";
+    break;
+
+  case T_template:
+    out << _template->get_name();
+    break;
+  }
+
+  if (has_name()) {
+    out << " " << get_name();
+  }
+
+  ArrayDef::const_iterator ai;
+  for (ai = _array_def.begin(); ai != _array_def.end(); ++ai) {
+    (*ai).output(out);
+  }
+
+  out << ";\n";
+}

+ 90 - 0
pandatool/src/xfile/xFileDataDef.h

@@ -0,0 +1,90 @@
+// Filename: xFileDataDef.h
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef XFILEDATADEF_H
+#define XFILEDATADEF_H
+
+#include "pandatoolbase.h"
+#include "namable.h"
+#include "xFileNode.h"
+#include "xFileArrayDef.h"
+#include "xFileTemplate.h"
+#include "pvector.h"
+#include "pointerTo.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : XFileDataDef
+// Description : A definition of a single data element appearing
+//               within a template record.
+////////////////////////////////////////////////////////////////////
+class XFileDataDef : public XFileNode {
+public:
+  enum Type {
+    T_word,
+    T_dword,
+    T_float,
+    T_double,
+    T_char,
+    T_uchar,
+    T_byte,
+    T_string,
+    T_cstring,
+    T_unicode,
+    T_template,
+  };
+
+  INLINE XFileDataDef(Type type, const string &name, 
+                      XFileTemplate *xtemplate = NULL);
+  virtual ~XFileDataDef();
+
+  virtual void clear();
+  void add_array_def(const XFileArrayDef &array_def);
+
+  virtual void write_text(ostream &out, int indent_level) const;
+
+private:
+  Type _type;
+  PT(XFileTemplate) _template;
+  
+  typedef pvector<XFileArrayDef> ArrayDef;
+  ArrayDef _array_def;
+  
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    XFileNode::init_type();
+    register_type(_type_handle, "XFileDataDef",
+                  XFileNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "xFileDataDef.I"
+
+#endif
+  
+
+

+ 18 - 0
pandatool/src/xfile/xFileNode.I

@@ -0,0 +1,18 @@
+// Filename: xFileNode.I
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+

+ 96 - 0
pandatool/src/xfile/xFileNode.cxx

@@ -0,0 +1,96 @@
+// Filename: xFileNode.cxx
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "xFileNode.h"
+
+TypeHandle XFileNode::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileNode::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+XFileNode::
+XFileNode(const string &name) : Namable(name)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileNode::Destructor
+//       Access: Public, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+XFileNode::
+~XFileNode() {
+  clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileNode::find_child
+//       Access: Public
+//  Description: Returns the child with the indicated name, if any, or
+//               NULL if none.
+////////////////////////////////////////////////////////////////////
+XFileNode *XFileNode::
+find_child(const string &name) const {
+  ChildrenByName::const_iterator ni;
+  ni = _children_by_name.find(name);
+  if (ni != _children_by_name.end()) {
+    return (*ni).second;
+  }
+
+  return NULL;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileNode::add_child
+//       Access: Public, Virtual
+//  Description: Adds the indicated node as a child of this node.
+////////////////////////////////////////////////////////////////////
+void XFileNode::
+add_child(XFileNode *node) {
+  _children.push_back(node);
+  if (node->has_name()) {
+    _children_by_name.insert(ChildrenByName::value_type(node->get_name(), node));
+  }
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileNode::clear
+//       Access: Public, Virtual
+//  Description: Removes all children from the node, and otherwise
+//               resets it to its initial state.
+////////////////////////////////////////////////////////////////////
+void XFileNode::
+clear() {
+  _children.clear();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileNode::write_text
+//       Access: Public, Virtual
+//  Description: Writes a suitable representation of this node to an
+//               .x file in text mode.
+////////////////////////////////////////////////////////////////////
+void XFileNode::
+write_text(ostream &out, int indent_level) const {
+  Children::const_iterator ci;
+  for (ci = _children.begin(); ci != _children.end(); ++ci) {
+    (*ci)->write_text(out, indent_level);
+  }
+}

+ 78 - 0
pandatool/src/xfile/xFileNode.h

@@ -0,0 +1,78 @@
+// Filename: xFileNode.h
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef XFILENODE_H
+#define XFILENODE_H
+
+#include "pandatoolbase.h"
+#include "typedReferenceCount.h"
+#include "pointerTo.h"
+#include "namable.h"
+#include "pvector.h"
+#include "pmap.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : XFileNode
+// Description : A single node of an X file.  This may be either a
+//               template or a data node.
+////////////////////////////////////////////////////////////////////
+class XFileNode : public TypedReferenceCount, public Namable {
+public:
+  XFileNode(const string &name);
+  virtual ~XFileNode();
+
+  INLINE int get_num_children() const;
+  INLINE XFileNode *get_child(int n) const;
+  XFileNode *find_child(const string &name) const;
+
+  virtual void add_child(XFileNode *node);
+  virtual void clear();
+
+  virtual void write_text(ostream &out, int indent_level) const;
+
+protected:
+  typedef pvector< PT(XFileNode) > Children;
+  Children _children;
+
+  typedef pmap<string, XFileNode *> ChildrenByName;
+  ChildrenByName _children_by_name;
+  
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    TypedReferenceCount::init_type();
+    register_type(_type_handle, "XFileNode",
+                  TypedReferenceCount::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "xFileNode.I"
+
+#endif
+  
+
+

+ 18 - 0
pandatool/src/xfile/xFileTemplate.I

@@ -0,0 +1,18 @@
+// Filename: xFileTemplate.I
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+

+ 53 - 0
pandatool/src/xfile/xFileTemplate.cxx

@@ -0,0 +1,53 @@
+// Filename: xFileTemplate.cxx
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "xFileTemplate.h"
+#include "indent.h"
+
+TypeHandle XFileTemplate::_type_handle;
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileTemplate::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+XFileTemplate::
+XFileTemplate(const string &name, const WindowsGuid &guid) : 
+  XFileNode(name),
+  _guid(guid)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileTemplate::write_text
+//       Access: Public, Virtual
+//  Description: Writes a suitable representation of this node to an
+//               .x file in text mode.
+////////////////////////////////////////////////////////////////////
+void XFileTemplate::
+write_text(ostream &out, int indent_level) const {
+  indent(out, indent_level)
+    << "template " << get_name() << " {\n";
+  indent(out, indent_level + 2)
+    << "<" << _guid << ">\n";
+
+  XFileNode::write_text(out, indent_level + 2);
+
+  indent(out, indent_level)
+    << "}\n";
+}

+ 65 - 0
pandatool/src/xfile/xFileTemplate.h

@@ -0,0 +1,65 @@
+// Filename: xFileTemplate.h
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef XFILETEMPLATE_H
+#define XFILETEMPLATE_H
+
+#include "pandatoolbase.h"
+#include "xFileNode.h"
+#include "windowsGuid.h"
+
+class XFileDataDef;
+
+////////////////////////////////////////////////////////////////////
+//       Class : XFileTemplate
+// Description : A template definition in the X file.  This defines
+//               the data structures that may be subsequently read.
+////////////////////////////////////////////////////////////////////
+class XFileTemplate : public XFileNode {
+public:
+  XFileTemplate(const string &name, const WindowsGuid &guid);
+
+  virtual void write_text(ostream &out, int indent_level) const;
+
+private:
+  WindowsGuid _guid;
+  
+public:
+  static TypeHandle get_class_type() {
+    return _type_handle;
+  }
+  static void init_type() {
+    XFileNode::init_type();
+    register_type(_type_handle, "XFileTemplate",
+                  XFileNode::get_class_type());
+  }
+  virtual TypeHandle get_type() const {
+    return get_class_type();
+  }
+  virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
+
+private:
+  static TypeHandle _type_handle;
+};
+
+#include "xFileTemplate.I"
+
+#endif
+  
+
+

+ 107 - 0
pandatool/src/xfile/xFileTrans.cxx

@@ -0,0 +1,107 @@
+// Filename: xFileTrans.cxx
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#include "xFileTrans.h"
+#include "xFile.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileTrans::Constructor
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+XFileTrans::
+XFileTrans() :
+  WithOutputFile(true, true, false)
+{
+  // Indicate the extension name we expect the user to supply for
+  // output files.
+  _preferred_extension = ".x";
+
+  set_program_description
+    ("This program reads a DirectX retained-mode file (.x) and writes an "
+     "essentially equivalent .x file.  It is primarily useful for "
+     "debugging the X file parser that is part of the Pandatool library.");
+
+  clear_runlines();
+  add_runline("[opts] input.x > output.x");
+  add_runline("[opts] input.x output.x");
+  add_runline("[opts] -o output.x input.x");
+
+  add_option
+    ("o", "filename", 0,
+     "Specify the filename to which the resulting .x file will be written.  "
+     "If this option is omitted, the last parameter name is taken to be the "
+     "name of the output file.",
+     &XFileTrans::dispatch_filename, &_got_output_filename, &_output_filename);
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileTrans::run
+//       Access: Public
+//  Description:
+////////////////////////////////////////////////////////////////////
+void XFileTrans::
+run() {
+  nout << "Reading " << _input_filename << "\n";
+
+  XFile file;
+  if (!file.read(_input_filename)) {
+    nout << "Unable to read.\n";
+    exit(1);
+  }
+
+  if (!file.write(get_output())) {
+    nout << "Unable to write.\n";
+    exit(1);
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: XFileTrans::handle_args
+//       Access: Protected, Virtual
+//  Description:
+////////////////////////////////////////////////////////////////////
+bool XFileTrans::
+handle_args(ProgramBase::Args &args) {
+  if (!check_last_arg(args, 1)) {
+    return false;
+  }
+
+  if (args.empty()) {
+    nout << "You must specify the .x file to read on the command line.\n";
+    return false;
+
+  } else if (args.size() != 1) {
+    nout << "You must specify only one .x file to read on the command line.\n";
+    return false;
+  }
+
+  _input_filename = args[0];
+
+  return true;
+}
+
+
+int main(int argc, char *argv[]) {
+  XFileTrans prog;
+  prog.parse_command_line(argc, argv);
+  prog.run();
+  return 0;
+}

+ 46 - 0
pandatool/src/xfile/xFileTrans.h

@@ -0,0 +1,46 @@
+// Filename: xFileTrans.h
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef XFILETRANS_H
+#define XFILETRANS_H
+
+#include "pandatoolbase.h"
+
+#include "programBase.h"
+#include "withOutputFile.h"
+
+////////////////////////////////////////////////////////////////////
+//       Class : XFileTrans
+// Description : A program to read a X file and output an
+//               essentially similar X file.  This is mainly useful
+//               to test the X file parser used in Panda.
+////////////////////////////////////////////////////////////////////
+class XFileTrans : public ProgramBase, public WithOutputFile {
+public:
+  XFileTrans();
+
+  void run();
+
+protected:
+  virtual bool handle_args(Args &args);
+
+  Filename _input_filename;
+};
+
+#endif
+

+ 540 - 0
pandatool/src/xfile/xLexer.lxx

@@ -0,0 +1,540 @@
+/*
+// Filename: xLexer.lxx
+// Created by:  drose (03Oct04)
+// 
+////////////////////////////////////////////////////////////////////
+*/
+
+%{
+#include "xLexerDefs.h"
+#include "xParserDefs.h"
+#include "xParser.h"
+#include "indent.h"
+#include "notify.h"
+
+static int yyinput(void);        // declared by flex.
+extern "C" int xyywrap();
+
+////////////////////////////////////////////////////////////////////
+// Static variables
+////////////////////////////////////////////////////////////////////
+
+// We'll increment line_number and col_number as we parse the file, so
+// that we can report the position of an error.
+static int line_number = 0;
+static int col_number = 0;
+
+// current_line holds as much of the current line as will fit.  Its
+// only purpose is for printing it out to report an error to the user.
+static const int max_error_width = 1024;
+static char current_line[max_error_width + 1];
+
+static int error_count = 0;
+static int warning_count = 0;
+
+// This is the pointer to the current input stream.
+static istream *inp = NULL;
+
+// This is the name of the x file we're parsing.  We keep it so we
+// can print it out for error messages.
+static string x_filename;
+
+
+////////////////////////////////////////////////////////////////////
+// Defining the interface to the lexer.
+////////////////////////////////////////////////////////////////////
+
+void
+x_init_lexer(istream &in, const string &filename) {
+  inp = &in;
+  x_filename = filename;
+  line_number = 0;
+  col_number = 0;
+  error_count = 0;
+  warning_count = 0;
+}
+
+int
+x_error_count() {
+  return error_count;
+}
+
+int
+x_warning_count() {
+  return warning_count;
+}
+
+
+////////////////////////////////////////////////////////////////////
+// Internal support functions.
+////////////////////////////////////////////////////////////////////
+
+int
+xyywrap(void) {
+  return 1;
+}
+
+void
+xyyerror(const string &msg) {
+  cerr << "\nError";
+  if (!x_filename.empty()) {
+    cerr << " in " << x_filename;
+  }
+  cerr 
+    << " at line " << line_number << ", column " << col_number << ":\n"
+    << current_line << "\n";
+  indent(cerr, col_number-1) 
+    << "^\n" << msg << "\n\n";
+  
+  error_count++;
+}
+
+void
+xyywarning(const string &msg) {
+  cerr << "\nWarning";
+  if (!x_filename.empty()) {
+    cerr << " in " << x_filename;
+  }
+  cerr 
+    << " at line " << line_number << ", column " << col_number << ":\n"
+    << current_line << "\n";
+  indent(cerr, col_number-1) 
+    << "^\n" << msg << "\n\n";
+
+  warning_count++;
+}
+
+// Now define a function to take input from an istream instead of a
+// stdio FILE pointer.  This is flex-specific.
+static void
+input_chars(char *buffer, int &result, int max_size) {
+  nassertv(inp != NULL);
+  if (*inp) {
+    inp->read(buffer, max_size);
+    result = inp->gcount();
+    if (result >= 0 && result < max_size) {
+      // Truncate at the end of the read.
+      buffer[result] = '\0';
+    }
+
+    if (line_number == 0) {
+      // This is a special case.  If we are reading the very first bit
+      // from the stream, copy it into the current_line array.  This
+      // is because the \n.* rule below, which fills current_line
+      // normally, doesn't catch the first line.
+      strncpy(current_line, xyytext, max_error_width);
+      current_line[max_error_width] = '\0';
+      line_number++;
+      col_number = 0;
+
+      // Truncate it at the newline.
+      char *end = strchr(current_line, '\n');
+      if (end != NULL) {
+        *end = '\0';
+      }
+    }
+
+  } else {
+    // End of file or I/O error.
+    result = 0;
+  }
+}
+#undef YY_INPUT
+#define YY_INPUT(buffer, result, max_size) input_chars(buffer, result, max_size)
+
+// read_char reads and returns a single character, incrementing the
+// supplied line and column numbers as appropriate.  A convenience
+// function for the scanning functions below.
+static int
+read_char(int &line, int &col) {
+  int c = yyinput();
+  if (c == '\n') {
+    line++;
+    col = 0;
+  } else {
+    col++;
+  }
+  return c;
+}
+
+// scan_quoted_string reads a string delimited by quotation marks and
+// returns it.
+static string
+scan_quoted_string(char quote_mark) {
+  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;
+
+  int c;
+  c = read_char(line, col);
+  while (c != quote_mark && c != EOF) {
+    // A newline is not allowed within a string unless it is escaped.
+    if (c == '\n') {
+      c = EOF;
+      break;
+
+    } else if (c == '\\') {
+      // Backslash escapes the following character.  We also respect
+      // some C conventions.
+      c = read_char(line, col);
+      switch (c) {
+      case 'a':
+        result += '\a';
+        c = read_char(line, col);
+        break;
+
+      case 'n':
+        result += '\n';
+        c = read_char(line, col);
+        break;
+
+      case 'r':
+        result += '\r';
+        c = read_char(line, col);
+        break;
+
+      case 't':
+        result += '\t';
+        c = read_char(line, col);
+        break;
+
+      case 'x':
+        {
+          int hex = 0;
+          c = read_char(line, col);
+          for (int i = 0; i < 2 && isxdigit(c); i++) {
+            hex = hex * 16 + (isdigit(c) ? c - '0' : tolower(c) - 'a' + 10);
+            c = read_char(line, col);
+          }
+
+          result += hex;
+        }
+        break;
+
+      case '0':
+        {
+          int oct = 0;
+          c = read_char(line, col);
+          for (int i = 0; i < 3 && (c >= '0' && c < '7'); i++) {
+            oct = oct * 8 + (c - '0');
+            c = read_char(line, col);
+          }
+
+          result += oct;
+        }
+        break;
+
+      case '1':
+      case '2':
+      case '3':
+      case '4':
+      case '5':
+      case '6':
+      case '7':
+      case '8':
+      case '9':
+        {
+          int dec = 0;
+          c = read_char(line, col);
+          for (int i = 0; i < 3 && isdigit(c); i++) {
+            dec = dec * 10 + (c - '0');
+            c = read_char(line, col);
+          }
+
+          result += dec;
+        }
+        break;
+
+      case EOF:
+        break;
+
+      default:
+        result += c;
+        c = read_char(line, col);
+      }
+
+    } else {
+      result += c;
+      c = read_char(line, col);
+    }
+  }
+
+  if (c == EOF) {
+    xyyerror("This quotation mark is unterminated.");
+  }
+
+  line_number = line;
+  col_number = col;
+
+  return result;
+}
+
+// scan_guid_string reads a string of hexadecimal digits delimited by
+// angle brackets and returns the corresponding string.
+static string
+scan_guid_string() {
+  // 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;
+
+  int num_digits = 0;
+  int num_hyphens = 0;
+
+  string result;
+
+  int c;
+  c = read_char(line, col);
+  while (c != '>' && c != EOF) {
+    if (isxdigit(c)) {
+      num_digits++;
+
+    } else if (c == '-') {
+      num_hyphens++;
+
+    } else {
+      line_number = line;
+      col_number = col;
+      xyyerror("Invalid character in GUID.");
+      return string();
+    }
+
+    result += c;
+
+    c = read_char(line, col);
+  }
+
+  if (c == EOF) {
+    xyyerror("This GUID string is unterminated.");
+    return string();
+
+  } else if (num_digits != 32) {
+    xyyerror("Incorrect number of hex digits in GUID.");
+    return string();
+
+  } else if (num_hyphens != 4) {
+    xyyerror("Incorrect number of hyphens in GUID.");
+    return string();
+  }
+
+  line_number = line;
+  col_number = col;
+
+  return result;
+}
+
+
+
+// accept() is called below as each piece is pulled off and
+// accepted by the lexer; it increments the current column number.
+inline void accept() {
+  col_number += yyleng;
+}
+
+%}
+
+INTEGERNUM           ([+-]?([0-9]+))
+UNSIGNED_HEXNUM      (0x[0-9a-fA-F]*)
+REALNUM              ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
+
+%%
+
+%{
+%}
+
+\n.* {
+  // New line.  Save a copy of the line so we can print it out for the
+  // benefit of the user in case we get an error.
+
+  strncpy(current_line, xyytext+1, max_error_width);
+  current_line[max_error_width] = '\0';
+  line_number++;
+  col_number=0;
+
+  // Return the whole line to the lexer, except the newline character,
+  // which we eat.
+  yyless(1);
+}
+
+[ \t\r] { 
+  // Eat whitespace.
+  accept();
+}
+
+"//".* { 
+  // Eat C++-style comments.
+  accept();
+}
+
+"#".* { 
+  // Eat sh-style comments.
+  accept();
+}
+
+
+"array" {
+  accept();
+  return KW_ARRAY;
+}
+
+"byte" {
+  accept();
+  return KW_BYTE;
+}
+
+"char" {
+  accept();
+  return KW_CHAR;
+}
+
+"cstring" {
+  accept();
+  return KW_CSTRING;
+}
+
+"double" {
+  accept();
+  return KW_DOUBLE;
+}
+
+"dword" {
+  accept();
+  return KW_DWORD;
+}
+
+"float" {
+  accept();
+  return KW_FLOAT;
+}
+
+"string" {
+  accept();
+  return KW_STRING;
+}
+
+"template" {
+  accept();
+  return KW_TEMPLATE;
+}
+
+"uchar" {
+  accept();
+  return KW_UCHAR;
+}
+
+"unicode" {
+  accept();
+  return KW_UNICODE;
+}
+
+"word" {
+  accept();
+  return KW_WORD;
+}
+
+[.][.][.] {
+  accept();
+  return ELLIPSIS;
+}
+
+{INTEGERNUM} { 
+  // A signed or unsigned integer number.
+  accept();
+  xyylval.u.s_int = atol(xyytext); 
+  xyylval.str = yytext;
+
+  return INTEGER;
+}
+
+{UNSIGNED_HEXNUM} {
+  // A hexadecimal integer number.
+  accept(); 
+
+  // As above, we'll decode the hex string by hand.
+  xyylval.str = xyytext;
+  xyylval.u.s_int = 0;
+  const char *p = xyytext + 2;
+  while (*p != '\0') {
+    int next_value = xyylval.u.s_int * 16;
+    if (next_value < xyylval.u.s_int) {
+      xyyerror("Number out of range.");
+      xyylval.u.s_int = 1;
+      return INTEGER;
+    }
+
+    if (isalpha(*p)) {
+      xyylval.u.s_int = next_value + (tolower(*p) - 'a' + 10);
+    } else {
+      xyylval.u.s_int = next_value + (*p - '0');
+    }
+    ++p;
+  }
+
+  return INTEGER; 
+}
+
+{REALNUM} { 
+  // A floating-point number.
+  accept(); 
+  xyylval.u.real = atof(xyytext); 
+  xyylval.str = xyytext;
+  return REAL; 
+}
+
+["] {
+  // Quoted string.
+  accept();
+  xyylval.str = scan_quoted_string('"');
+  return STRING;
+}
+
+['] {
+  // Single-quoted string.
+  accept();
+  xyylval.str = scan_quoted_string('\'');
+  return STRING;
+}
+
+[<] {
+  // Long GUID string.
+  accept();
+  xyylval.str = scan_guid_string();
+
+  if (!xyylval.guid.parse_string(xyylval.str)) {
+    xyyerror("Malformed GUID.");
+  }
+
+  return WINDOWS_GUID;
+}
+
+[A-Za-z_-][A-Za-z_0-9-]* { 
+  // Identifier.
+  accept();
+  xyylval.str = xyytext;
+  return IDENTIFIER;
+}
+
+
+. {
+  // Send any other printable character as itself.
+  accept(); 
+  return xyytext[0];
+}
+  

+ 33 - 0
pandatool/src/xfile/xLexerDefs.h

@@ -0,0 +1,33 @@
+// Filename: xLexerDefs.h
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef XLEXERDEFS_H
+#define XLEXERDEFS_H
+
+#include "pandatoolbase.h"
+
+void x_init_lexer(istream &in, const string &filename);
+int x_error_count();
+int x_warning_count();
+
+void xyyerror(const string &msg);
+void xyywarning(const string &msg);
+
+int xyylex();
+
+#endif

+ 237 - 0
pandatool/src/xfile/xParser.yxx

@@ -0,0 +1,237 @@
+// Filename: xParser.yxx
+// Created by:  drose (03Oct04)
+// 
+////////////////////////////////////////////////////////////////////
+
+%{
+#include "xLexerDefs.h"
+#include "xParserDefs.h"
+#include "xFile.h"
+#include "xFileTemplate.h"
+#include "xFileDataDef.h"
+#include "xFileArrayDef.h"
+#include "dcast.h"
+
+// Because our token type contains objects of type string, which
+// require correct copy construction (and not simply memcpying), we
+// cannot use bison's built-in auto-stack-grow feature.  As an easy
+// solution, we ensure here that we have enough yacc stack to start
+// with, and that it doesn't ever try to grow.
+#define YYINITDEPTH 1000
+#define YYMAXDEPTH 1000
+
+static XFile *x_file = (XFile *)NULL;
+static XFileNode *current_node = (XFileNode *)NULL;
+static XFileDataDef *current_data_def = (XFileDataDef *)NULL;
+
+////////////////////////////////////////////////////////////////////
+// Defining the interface to the parser.
+////////////////////////////////////////////////////////////////////
+
+void
+x_init_parser(istream &in, const string &filename, XFile &file) {
+  x_file = &file;
+  current_node = &file;
+  x_init_lexer(in, filename);
+}
+
+void
+x_cleanup_parser() {
+  x_file = (XFile *)NULL;
+  current_node = (XFileNode *)NULL;
+}
+
+%}
+
+%token <u.s_int> INTEGER
+%token <u.real> REAL
+%token <str> STRING IDENTIFIER
+%token <guid> WINDOWS_GUID
+
+%token KW_ARRAY 
+%token KW_BYTE
+%token KW_CHAR
+%token KW_CSTRING
+%token KW_DOUBLE
+%token KW_DWORD
+%token KW_FLOAT
+%token KW_STRING
+%token KW_TEMPLATE
+%token KW_UCHAR
+%token KW_UNICODE
+%token KW_WORD
+%token ELLIPSIS
+
+%type <u.node> xtemplate
+%type <u.data_def> data_def
+%type <str> optional_identifier
+%type <guid> optional_guid
+
+%%
+
+xfile:
+        empty
+        | xfile xtemplate
+        | xfile data_object
+        ;
+
+xtemplate:
+	KW_TEMPLATE IDENTIFIER '{' WINDOWS_GUID
+{
+  $$ = current_node;
+  XFileTemplate *templ = new XFileTemplate($2, $4);
+  current_node->add_child(templ);
+  current_node = templ;
+}
+	template_members template_restrictions '}'
+{
+  $$ = current_node;
+  current_node = $<u.node>5;
+}
+	;
+
+template_members:
+	empty
+	| template_members template_member ';'
+	;
+
+template_member:
+        data_def
+{
+  current_node->add_child($1);
+}
+        | KW_ARRAY data_def
+{
+  current_node->add_child($2);
+  current_data_def = $2;
+}
+	array_dimensions
+	;
+
+data_def:
+        KW_WORD optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_word, $2);
+}
+	| KW_DWORD optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_dword, $2);
+}
+	| KW_FLOAT optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_float, $2);
+}
+	| KW_DOUBLE optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_double, $2);
+}
+	| KW_CHAR optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_char, $2);
+}
+	| KW_UCHAR optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_uchar, $2);
+}
+	| KW_BYTE optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_byte, $2);
+}
+	| KW_STRING optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_string, $2);
+}
+	| KW_CSTRING optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_cstring, $2);
+}
+	| KW_UNICODE optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_unicode, $2);
+}
+	| IDENTIFIER optional_identifier
+{
+  $$ = new XFileDataDef(XFileDataDef::T_word, $2);
+}
+	;
+
+array_dimensions:
+	array_level
+	| array_dimensions array_level
+	;
+
+array_level:
+	'[' INTEGER ']'
+{
+  current_data_def->add_array_def(XFileArrayDef($2));
+}
+	| '[' IDENTIFIER ']'
+{
+  XFileNode *data_def = current_node->find_child($2);
+  if (data_def == (XFileNode *)NULL) {
+    yyerror("Unknown identifier: " + $2);
+  } else {
+    current_data_def->add_array_def(XFileArrayDef(DCAST(XFileDataDef, data_def)));
+  }
+}
+	;
+
+template_restrictions:
+	empty
+	| '[' ELLIPSIS ']'
+        | '[' template_list ']'
+	;
+
+template_list:
+        IDENTIFIER optional_guid
+	| template_list ',' IDENTIFIER optional_guid
+	;
+
+data_object:
+	IDENTIFIER optional_identifier '{'
+{
+}
+	data_object_members '}'
+{
+}
+	;
+
+
+data_object_members:
+	empty
+	| data_object_members data_object_member
+	;
+
+data_object_member:
+	data_object
+        | data_reference
+	| INTEGER
+	| REAL
+        | STRING
+        | ';'
+        | ','
+	;
+
+data_reference:
+	'{' IDENTIFIER '}'
+	;
+
+optional_identifier:
+	empty
+{
+  $$ = string();
+}
+	| IDENTIFIER
+	;
+
+optional_guid:
+	empty
+{
+  $$ = WindowsGuid();
+}
+	| WINDOWS_GUID
+	;
+
+empty:
+        ;
+

+ 57 - 0
pandatool/src/xfile/xParserDefs.h

@@ -0,0 +1,57 @@
+// Filename: xParserDefs.h
+// Created by:  drose (03Oct04)
+//
+////////////////////////////////////////////////////////////////////
+//
+// PANDA 3D SOFTWARE
+// Copyright (c) 2001 - 2004, Disney Enterprises, Inc.  All rights reserved
+//
+// All use of this software is subject to the terms of the Panda 3d
+// Software license.  You should have received a copy of this license
+// along with this source code; you will also find a current copy of
+// the license at http://etc.cmu.edu/panda3d/docs/license/ .
+//
+// To contact the maintainers of this program write to
+// [email protected] .
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef XPARSERDEFS_H
+#define XPARSERDEFS_H
+
+#include "pandatoolbase.h"
+
+#include "windowsGuid.h"
+
+class XFile;
+class XFileNode;
+class XFileDataDef;
+
+void x_init_parser(istream &in, const string &filename, XFile &file);
+void x_cleanup_parser();
+int xyyparse();
+
+// This structure holds the return value for each token.
+// Traditionally, this is a union, and is declared with the %union
+// declaration in the parser.y file, but unions are pretty worthless
+// in C++ (you can't include an object that has member functions in a
+// union), so we'll use a class instead.  That means we need to
+// declare it externally, here.
+
+class XTokenType {
+public:
+  union U {
+    int s_int;
+    double real;
+    XFileNode *node;
+    XFileDataDef *data_def;
+  } u;
+  string str;
+  WindowsGuid guid;
+};
+
+// The yacc-generated code expects to use the symbol 'YYSTYPE' to
+// refer to the above class.
+#define YYSTYPE XTokenType
+
+#endif

+ 34 - 0
pandatool/src/xfileegg/Sources.pp

@@ -0,0 +1,34 @@
+
+// The .x converter takes advantage of the DirectX API's; therefore,
+// it can only be built if we have DX available (and therefore it only
+// builds on Windows--sorry).
+#define BUILD_DIRECTORY $[HAVE_DX]
+#define USE_PACKAGES dx
+
+#begin ss_lib_target
+  #define TARGET xfileegg
+  #define LOCAL_LIBS xfile eggbase progbase pandatoolbase
+  #define OTHER_LIBS \
+    egg:c pandaegg:m \
+    mathutil:c linmath:c putil:c panda:m \
+    express:c pandaexpress:m \
+    dtoolconfig dtool pystub \
+
+  #define WIN_SYS_LIBS \
+    d3dxof.lib dxguid.lib d3d8.lib d3dx8.lib dxerr8.lib
+    
+  #define COMBINED_SOURCES $[TARGET]_composite1.cxx     
+    
+  #define SOURCES \
+     xFileAnimationSet.h \
+     xFileFace.h xFileMaker.h xFileMaterial.h \
+     xFileMesh.h xFileNormal.h xFileTemplates.h \
+     xFileToEggConverter.h xFileVertex.h 
+
+  #define INCLUDED_SOURCES \
+     xFileAnimationSet.cxx \
+     xFileFace.cxx xFileMaker.cxx xFileMaterial.cxx \
+     xFileMesh.cxx xFileNormal.cxx xFileTemplates.cxx \
+     xFileToEggConverter.cxx xFileVertex.cxx 
+
+#end ss_lib_target

+ 0 - 0
pandatool/src/xfile/xFileAnimationSet.cxx → pandatool/src/xfileegg/xFileAnimationSet.cxx


+ 0 - 0
pandatool/src/xfile/xFileAnimationSet.h → pandatool/src/xfileegg/xFileAnimationSet.h


+ 0 - 0
pandatool/src/xfile/xFileFace.cxx → pandatool/src/xfileegg/xFileFace.cxx


+ 0 - 0
pandatool/src/xfile/xFileFace.h → pandatool/src/xfileegg/xFileFace.h


+ 0 - 0
pandatool/src/xfile/xFileMaker.cxx → pandatool/src/xfileegg/xFileMaker.cxx


+ 0 - 0
pandatool/src/xfile/xFileMaker.h → pandatool/src/xfileegg/xFileMaker.h


+ 0 - 0
pandatool/src/xfile/xFileMaterial.cxx → pandatool/src/xfileegg/xFileMaterial.cxx


+ 0 - 0
pandatool/src/xfile/xFileMaterial.h → pandatool/src/xfileegg/xFileMaterial.h


+ 0 - 0
pandatool/src/xfile/xFileMesh.cxx → pandatool/src/xfileegg/xFileMesh.cxx


+ 0 - 0
pandatool/src/xfile/xFileMesh.h → pandatool/src/xfileegg/xFileMesh.h


+ 0 - 0
pandatool/src/xfile/xFileNormal.cxx → pandatool/src/xfileegg/xFileNormal.cxx


+ 0 - 0
pandatool/src/xfile/xFileNormal.h → pandatool/src/xfileegg/xFileNormal.h


+ 0 - 0
pandatool/src/xfile/xFileTemplates.cxx → pandatool/src/xfileegg/xFileTemplates.cxx


+ 0 - 0
pandatool/src/xfile/xFileTemplates.h → pandatool/src/xfileegg/xFileTemplates.h


+ 0 - 0
pandatool/src/xfile/xFileToEggConverter.cxx → pandatool/src/xfileegg/xFileToEggConverter.cxx


+ 0 - 0
pandatool/src/xfile/xFileToEggConverter.h → pandatool/src/xfileegg/xFileToEggConverter.h


+ 0 - 0
pandatool/src/xfile/xFileVertex.cxx → pandatool/src/xfileegg/xFileVertex.cxx


+ 0 - 0
pandatool/src/xfile/xFileVertex.h → pandatool/src/xfileegg/xFileVertex.h


+ 0 - 0
pandatool/src/xfile/xFileVertexPool.h → pandatool/src/xfileegg/xFileVertexPool.h


+ 0 - 0
pandatool/src/xfile/xfile_composite1.cxx → pandatool/src/xfileegg/xfileegg_composite1.cxx


+ 2 - 2
pandatool/src/xfileprogs/Sources.pp

@@ -7,7 +7,7 @@
 
 
 #begin bin_target
 #begin bin_target
   #define TARGET egg2x
   #define TARGET egg2x
-  #define LOCAL_LIBS xfile eggbase progbase pandatoolbase
+  #define LOCAL_LIBS xfileegg xfile eggbase progbase pandatoolbase
   #define OTHER_LIBS \
   #define OTHER_LIBS \
     egg:c pandaegg:m \
     egg:c pandaegg:m \
     mathutil:c linmath:c putil:c panda:m \
     mathutil:c linmath:c putil:c panda:m \
@@ -24,7 +24,7 @@
 
 
 #begin bin_target
 #begin bin_target
   #define TARGET x2egg
   #define TARGET x2egg
-  #define LOCAL_LIBS xfile converter eggbase progbase pandatoolbase
+  #define LOCAL_LIBS xfileegg xfile converter eggbase progbase pandatoolbase
   #define OTHER_LIBS \
   #define OTHER_LIBS \
     egg:c pandaegg:m \
     egg:c pandaegg:m \
     mathutil:c linmath:c putil:c panda:m \
     mathutil:c linmath:c putil:c panda:m \

+ 5 - 0
pandatool/src/xfileprogs/xFileToEgg.cxx

@@ -44,10 +44,15 @@ XFileToEgg() :
 
 
   add_option
   add_option
     ("a", "name", 0,
     ("a", "name", 0,
+     "Convert as an animatable model, converting Frames into Joints.  "
+     "Note that animation support in x2egg is currently experimental and "
+     "likely to be broken.",
+  /*
      "Convert as an animatable model, converting Frames into Joints.  This "
      "Convert as an animatable model, converting Frames into Joints.  This "
      "should be specified for a model which is intended to be animated.  The "
      "should be specified for a model which is intended to be animated.  The "
      "default is to convert the model as a normal static model, which is "
      "default is to convert the model as a normal static model, which is "
      "usually more optimal if animation is not required.",
      "usually more optimal if animation is not required.",
+  */
      &XFileToEgg::dispatch_string, &_make_char, &_char_name);
      &XFileToEgg::dispatch_string, &_make_char, &_char_name);
 
 
   redescribe_option
   redescribe_option