Browse Source

Initial revision

David Rose 25 years ago
commit
7a78284129
100 changed files with 17323 additions and 0 deletions
  1. 49 0
      dtool/Config.Irix.pp
  2. 49 0
      dtool/Config.Linux.pp
  3. 49 0
      dtool/Config.Win32.pp
  4. 167 0
      dtool/Config.pp
  5. 211 0
      dtool/LocalSetup.pp
  6. 11 0
      dtool/Package.pp
  7. 10 0
      dtool/Sources.pp
  8. 68 0
      dtool/acconfig.h
  9. 933 0
      dtool/acinclude.m4
  10. 96 0
      dtool/dtool_config.h
  11. 7 0
      dtool/metalibs/Sources.pp
  12. 17 0
      dtool/metalibs/dtool/Sources.pp
  13. 11 0
      dtool/metalibs/dtool/dtool.cxx
  14. 1680 0
      dtool/metalibs/dtool/pydtool.cxx
  15. 4 0
      dtool/src/Sources.pp
  16. 13 0
      dtool/src/attach/Sources.pp
  17. 33 0
      dtool/src/attach/ctallihave
  18. 149 0
      dtool/src/attach/ctattach.drv
  19. 86 0
      dtool/src/attach/ctattachcc
  20. 474 0
      dtool/src/attach/ctattch.pl
  21. 953 0
      dtool/src/attach/ctattch.pl.rnd
  22. 439 0
      dtool/src/attach/ctccase.pl
  23. 55 0
      dtool/src/attach/ctci
  24. 580 0
      dtool/src/attach/ctcm.pl
  25. 55 0
      dtool/src/attach/ctco
  26. 408 0
      dtool/src/attach/ctcvs.pl
  27. 32 0
      dtool/src/attach/ctdelta
  28. 232 0
      dtool/src/attach/ctdelta.pl
  29. 232 0
      dtool/src/attach/ctdelta.pl.rnd
  30. 33 0
      dtool/src/attach/ctihave
  31. 23 0
      dtool/src/attach/ctmake
  32. 55 0
      dtool/src/attach/ctmkdir
  33. 78 0
      dtool/src/attach/ctmkelem
  34. 35 0
      dtool/src/attach/ctmv
  35. 258 0
      dtool/src/attach/ctntool.pl
  36. 42 0
      dtool/src/attach/ctquery
  37. 37 0
      dtool/src/attach/ctquery.pl
  38. 31 0
      dtool/src/attach/ctrm
  39. 43 0
      dtool/src/attach/ctsanity
  40. 43 0
      dtool/src/attach/cttimewarp
  41. 48 0
      dtool/src/attach/ctunattach.drv
  42. 250 0
      dtool/src/attach/ctunattach.pl
  43. 31 0
      dtool/src/attach/ctunco
  44. 359 0
      dtool/src/attach/ctvspec.pl
  45. 36 0
      dtool/src/attach/dtool.alias
  46. 46 0
      dtool/src/attach/dtool.alias-sh
  47. 85 0
      dtool/src/attach/dtool.cshrc
  48. 286 0
      dtool/src/attach/dtool.emacs
  49. 10 0
      dtool/src/attach/dtool.init
  50. 79 0
      dtool/src/attach/dtool.sh
  51. 104 0
      dtool/src/attach/get-cttree
  52. 481 0
      dtool/src/attach/get-delta
  53. 1055 0
      dtool/src/attach/neartool
  54. 31 0
      dtool/src/attach/unco.pl
  55. 189 0
      dtool/src/attach/update-cttree
  56. 50 0
      dtool/src/build/Makefile.a.rules
  57. 23 0
      dtool/src/build/Makefile.a.template
  58. 69 0
      dtool/src/build/Makefile.bin.rules
  59. 23 0
      dtool/src/build/Makefile.bin.template
  60. 121 0
      dtool/src/build/Makefile.bin.vars
  61. 74 0
      dtool/src/build/Makefile.foreign.rules
  62. 28 0
      dtool/src/build/Makefile.foreign.template
  63. 19 0
      dtool/src/build/Makefile.foreign.vars
  64. 891 0
      dtool/src/build/Makefile.install.rules
  65. 61 0
      dtool/src/build/Makefile.install.template
  66. 25 0
      dtool/src/build/Makefile.install.vars
  67. 103 0
      dtool/src/build/Makefile.meta.rules
  68. 16 0
      dtool/src/build/Makefile.meta.template
  69. 43 0
      dtool/src/build/Makefile.o.include
  70. 358 0
      dtool/src/build/Makefile.o.rules
  71. 11 0
      dtool/src/build/Makefile.o.template
  72. 354 0
      dtool/src/build/Makefile.o.vars
  73. 57 0
      dtool/src/build/Makefile.penv.vars
  74. 18 0
      dtool/src/build/Makefile.project.template
  75. 68 0
      dtool/src/build/Makefile.project.vars
  76. 158 0
      dtool/src/build/Makefile.so.rules
  77. 22 0
      dtool/src/build/Makefile.so.template
  78. 55 0
      dtool/src/build/Makefile.ss.rules
  79. 21 0
      dtool/src/build/Makefile.ss.template
  80. 28 0
      dtool/src/build/Makefile.ss.vars
  81. 20 0
      dtool/src/build/Makefile.uxb.rules
  82. 7 0
      dtool/src/build/Makefile.uxb.template
  83. 20 0
      dtool/src/build/Sources.pp
  84. 92 0
      dtool/src/build/ctaddpkg
  85. 91 0
      dtool/src/build/ctaddtgt
  86. 128 0
      dtool/src/build/ctinitproj
  87. 54 0
      dtool/src/build/ctinstmake.pl
  88. 74 0
      dtool/src/build/ctpathadjust
  89. 35 0
      dtool/src/build/ctproj
  90. 60 0
      dtool/src/build/ctproj.pl
  91. 47 0
      dtool/src/build/ctutils.pl
  92. 21 0
      dtool/src/build/initialize
  93. 46 0
      dtool/src/cppparser/Sources.pp
  94. 227 0
      dtool/src/cppparser/cppArrayType.cxx
  95. 52 0
      dtool/src/cppparser/cppArrayType.h
  96. 2527 0
      dtool/src/cppparser/cppBison.yxx
  97. 96 0
      dtool/src/cppparser/cppBisonDefs.h
  98. 112 0
      dtool/src/cppparser/cppClassTemplateParameter.cxx
  99. 40 0
      dtool/src/cppparser/cppClassTemplateParameter.h
  100. 7 0
      dtool/src/cppparser/cppCommentBlock.cxx

+ 49 - 0
dtool/Config.Irix.pp

@@ -0,0 +1,49 @@
+//
+// Config.Irix.pp
+//
+// This file defines some custom config variables for the SGI/Irix
+// platform.  It makes some initial guesses about compiler features,
+// etc.
+//
+
+// Is the platform big-endian (like an SGI workstation) or
+// little-endian (like a PC)?  Define this to the empty string to
+// indicate little-endian, or nonempty to indicate big-endian.
+#define WORDS_BIGENDIAN 1
+
+// Does the C++ compiler support namespaces?
+#define HAVE_NAMESPACE 1
+
+// Does the C++ compiler support ios::binary?
+#define HAVE_IOS_BINARY
+
+// Do we have a gettimeofday() function?
+#define HAVE_GETTIMEOFDAY 1
+
+// Does gettimeofday() take only one parameter?
+#define GETTIMEOFDAY_ONE_PARAM
+
+// Do we have getopt() and/or getopt_long_only() built into the
+// system?
+#define HAVE_GETOPT 1
+#define HAVE_GETOPT_LONG_ONLY
+
+// Should we include <iostream> or <iostream.h>?  Define HAVE_IOSTREAM
+// to nonempty if we should use <iostream>, or empty if we should use
+// <iostream.h>.
+#define HAVE_IOSTREAM
+
+// Do we have a true stringstream class defined in <sstream>?
+#define HAVE_SSTREAM
+
+// Do we have <malloc.h>?
+#define HAVE_MALLOC_H 1
+
+// Do we have <alloca.h>?
+#define HAVE_ALLOCA_H 1
+
+// Do we have <sys/types.h>?
+#define HAVE_SYS_TYPES_H 1
+
+// Do we have <unistd.h>?
+#define HAVE_UNISTD_H 1

+ 49 - 0
dtool/Config.Linux.pp

@@ -0,0 +1,49 @@
+//
+// Config.Linux.pp
+//
+// This file defines some custom config variables for the Linux
+// platform.  It makes some initial guesses about compiler features,
+// etc.
+//
+
+// Is the platform big-endian (like an SGI workstation) or
+// little-endian (like a PC)?  Define this to the empty string to
+// indicate little-endian, or nonempty to indicate big-endian.
+#define WORDS_BIGENDIAN
+
+// Does the C++ compiler support namespaces?
+#define HAVE_NAMESPACE 1
+
+// Does the C++ compiler support ios::binary?
+#define HAVE_IOS_BINARY 1
+
+// Do we have a gettimeofday() function?
+#define HAVE_GETTIMEOFDAY 1
+
+// Does gettimeofday() take only one parameter?
+#define GETTIMEOFDAY_ONE_PARAM
+
+// Do we have getopt() and/or getopt_long_only() built into the
+// system?
+#define HAVE_GETOPT 1
+#define HAVE_GETOPT_LONG_ONLY 1
+
+// Should we include <iostream> or <iostream.h>?  Define HAVE_IOSTREAM
+// to nonempty if we should use <iostream>, or empty if we should use
+// <iostream.h>.
+#define HAVE_IOSTREAM
+
+// Do we have a true stringstream class defined in <sstream>?
+#define HAVE_SSTREAM
+
+// Do we have <malloc.h>?
+#define HAVE_MALLOC_H 1
+
+// Do we have <alloca.h>?
+#define HAVE_ALLOCA_H 1
+
+// Do we have <sys/types.h>?
+#define HAVE_SYS_TYPES_H 1
+
+// Do we have <unistd.h>?
+#define HAVE_UNISTD_H 1

+ 49 - 0
dtool/Config.Win32.pp

@@ -0,0 +1,49 @@
+//
+// Config.Win32.pp
+//
+// This file defines some custom config variables for the Windows
+// platform.  It makes some initial guesses about compiler features,
+// etc.
+//
+
+// Is the platform big-endian (like an SGI workstation) or
+// little-endian (like a PC)?  Define this to the empty string to
+// indicate little-endian, or nonempty to indicate big-endian.
+#define WORDS_BIGENDIAN
+
+// Does the C++ compiler support namespaces?
+#define HAVE_NAMESPACE 1
+
+// Does the C++ compiler support ios::binary?
+#define HAVE_IOS_BINARY 1
+
+// Do we have a gettimeofday() function?
+#define HAVE_GETTIMEOFDAY
+
+// Does gettimeofday() take only one parameter?
+#define GETTIMEOFDAY_ONE_PARAM
+
+// Do we have getopt() and/or getopt_long_only() built into the
+// system?
+#define HAVE_GETOPT
+#define HAVE_GETOPT_LONG_ONLY
+
+// Should we include <iostream> or <iostream.h>?  Define HAVE_IOSTREAM
+// to nonempty if we should use <iostream>, or empty if we should use
+// <iostream.h>.
+#define HAVE_IOSTREAM 1
+
+// Do we have a true stringstream class defined in <sstream>?
+#define HAVE_SSTREAM 1
+
+// Do we have <malloc.h>?
+#define HAVE_MALLOC_H 1
+
+// Do we have <alloca.h>?
+#define HAVE_ALLOCA_H
+
+// Do we have <sys/types.h>?
+#define HAVE_SYS_TYPES_H 1
+
+// Do we have <unistd.h>?
+#define HAVE_UNISTD_H

+ 167 - 0
dtool/Config.pp

@@ -0,0 +1,167 @@
+//
+// Config.pp
+//
+// This file defines certain configuration variables that are written
+// into the various make scripts.  It is processed by ppremake (along
+// with the Sources.pp files in each of the various directories) to
+// generate build scripts appropriate to each environment.
+//
+// ppremake is capable of generating generic Unix autoconf/automake
+// style build scripts, as well as makefiles customized for SGI's
+// MipsPRO compiler or for Microsoft's Visual C++.  It can also
+// generate Microsoft Developer's Studio project files directly.  In
+// principle, it can be extended to generate suitable build script
+// files for any number of different build environments.
+//
+// All of these build scripts can be tuned for a particular
+// environment via this file.  This is the place for the user to
+// specify which external packages are installed and where, or to
+// enable or disable certain optional features.  However, it is
+// suggested that rather than modify this file directly, you create a
+// custom file in your home directory and there redefine whatever
+// variables are appropriate, and set the environment variable
+// PPREMAKE_CONFIG to refer to it.  In this way, you can easily get an
+// updated source tree (including a new Config.pp) without risking
+// accidentally losing your customizations.  This also avoids having
+// to redefine the same variables in different packages (for instance,
+// in dtool and in panda).
+//
+// If you *do* decide to make changes directly to this file, you
+// should also comment out the line near the bottom that includes the
+// file $[TOPDIRPREFIX]Config.$[PLATFORM].pp, to avoid stomping on the
+// changes you make.
+//
+// The syntax in this file resembles some hybrid between C++
+// preprocessor declarations and GNU make variables.  This is the same
+// syntax used in the various ppremake system configure files; it's
+// designed to be easy to use as a macro language to generate
+// makefiles and their ilk.
+// 
+
+// What kind of build scripts are we generating?  This selects a
+// suitable template file from the ppremake system files.  The
+// allowable choices, at present, are:
+//
+//  autoconf  - Generate configure.in and a series of Makefile.am files,
+//              suitable for using with autoconf/automake.  Not quite
+//              there yet.
+//  stopgap   - Generate original Cary-style Makefile/Makefile.install/etc.
+//              files, to ease transition to the new system.
+//
+#define BUILD_TYPE stopgap
+
+// Define the directory in which the system ppremake files are
+// installed.
+#define PPREMAKE_DIR /usr/local/panda/share
+
+
+// In which directory should this package be installed when you type
+// "make install"?  This has no meaning when BUILD_TYPE is "stopgap".
+#define INSTALL_DIR /usr/local/panda
+
+
+// What level of compiler optimization/debug symbols should we build?
+// The various optimize levels are defined as follows:
+//
+//   1 - No compiler optimizations, full debug symbols
+//   2 - Full compiler optimizations, full debug symbols
+//         (if the compiler supports this)
+//   3 - Full compiler optimizations, no debug symbols
+//   4 - Full optimizations, no debug symbols, and asserts removed
+//
+// Setting this has no effect when BUILD_TYPE is "stopgap".  In this
+// case, the compiler optimizations are selected by setting the
+// environment variable OPTIMIZE accordingly at compile time.
+#define OPTIMIZE 1
+
+
+
+////////////////////////////////////////////////////////////////////
+// The remaining variables are considered only if BUILD_TYPE is not
+// "autoconf".  (Autoconf can determine these directly.)
+////////////////////////////////////////////////////////////////////
+
+// NOTE: In the following, to indicate "yes" to a yes/no question,
+// define the variable to be a nonempty string.  To indicate "no",
+// define the variable to be an empty string.
+
+// Is Python installed, and should Python interfaces be generated?  If
+// Python is installed, which directory is it in?  (If the directory
+// is someplace standard like /usr/include, you may leave it blank.)
+#define HAVE_PYTHON 1
+#define PYTHON_INCLUDE /usr/local/include/python1.6
+#define PYTHON_LIB
+
+// Is NSPR installed, and where?
+#define HAVE_NSPR 1
+#define NSPR_INCLUDE /usr/local/mozilla/dist/*/include
+#define NSPR_LIB
+
+// Is VRPN installed, and where?
+#define HAVE_VRPN
+#define VRPN_INCLUDE
+#define VRPN_LIB
+
+// Is ZLIB installed, and where?
+#define HAVE_ZLIB 1
+#define ZLIB_INCLUDE
+#define ZLIB_LIB
+
+// Is OpenGL installed, and where?
+#define HAVE_GL 1
+#define GL_INCLUDE
+#define GL_LIB
+#define GLU_INCLUDE
+#define GLU_LIB
+
+// How about GLX?
+#define HAVE_GLX 1
+#define GLX_INCLUDE
+#define GLX_LIB
+
+// Glut?
+#define HAVE_GLUT
+#define GLUT_INCLUDE
+#define GLUT_LIB
+
+// Should we try to build the WGL interface?
+#define HAVE_WGL
+
+// Should we try to build the DirectX interface?
+#define HAVE_DX
+
+// Do you want to build the Renderman interface?
+#define HAVE_RIB
+
+// Is Mikmod installed?
+#define HAVE_MIKMOD
+#define MIKMOD_CFLAGS
+#define MIKMOD_INCLUDE
+#define MIKMOD_LIB
+
+
+//////////////////////////////////////////////////////////////////////
+// There are also some additional variables that control specific
+// compiler/platform features or characteristics, defined in the
+// platform specific file Config.platform.pp.  Be sure to inspect
+// these variables for correctness too.  As above, these are
+// unnecessary when BUILD_TYPE is "autoconf".
+//////////////////////////////////////////////////////////////////////
+#include $[TOPDIRPREFIX]Config.$[PLATFORM].pp
+
+
+// Also pull in whatever package-specific variables there may be.
+#include $[TOPDIRPREFIX]Package.pp
+
+
+// If the environment variable PPREMAKE_CONFIG is set, it points to a
+// user-customized Config.pp file, for instance in the user's home
+// directory.  This file might redefine any of the variables defined
+// above.
+#if $[ne $[PPREMAKE_CONFIG],]
+  #include $[PPREMAKE_CONFIG]
+#endif
+
+
+// Finally, include the system configure file.
+#include $[PPREMAKE_DIR]/System.pp

+ 211 - 0
dtool/LocalSetup.pp

@@ -0,0 +1,211 @@
+//
+// LocalSetup.pp
+//
+// This file contains further instructions to set up the DTOOL package
+// when using ppremake.  In particular, it creates the dtool_config.h
+// file based on the user's selected configure variables.  This script
+// need not execute when BUILD_TYPE is "autoconf"; in this case, the
+// dtool_config.h file will automatically be correctly generated by
+// configure.
+//
+
+#if $[ne $[BUILD_TYPE],autoconf]
+
+// A couple of variables to output the C #define and #undef
+// directives, since we can't type them literally.
+#define define #define
+#define undef #undef
+
+#output dtool_config.h
+#format straight
+/* dtool_config.h.  Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE]. */
+
+/* Define if you have the ANSI C header files.  */
+$[define] STDC_HEADERS 1
+
+/* Define if your processor stores words with the most significant
+   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
+#if $[WORDS_BIGENDIAN]
+$[define] WORDS_BIGENDIAN 1
+#else
+$[undef] WORDS_BIGENDIAN
+#endif
+
+/* Define if the X Window System is missing or not being used.  */
+$[undef] X_DISPLAY_MISSING
+
+/* Define if lex declares yytext as a char * by default, not a char[].  */
+$[undef] YYTEXT_POINTER
+
+/* Define if the C++ compiler uses namespaces.  */
+#if $[HAVE_NAMESPACE]
+$[define] HAVE_NAMESPACE 1
+#else
+$[undef] HAVE_NAMESPACE
+#endif
+
+/* Define if the C++ iostream library supports ios::binary.  */
+#if $[HAVE_IOS_BINARY]
+$[define] HAVE_IOS_BINARY 1
+#else
+$[undef] HAVE_IOS_BINARY
+#endif
+
+/* Define if we have Python installed.  */
+#if $[HAVE_PYTHON]
+$[define] HAVE_PYTHON 1
+#else
+$[undef] HAVE_PYTHON
+#endif
+
+/* Define if we have NSPR installed.  */
+#if $[HAVE_NSPR]
+$[define] HAVE_NSPR 1
+#else
+$[undef] HAVE_NSPR
+#endif
+
+/* Define if we have VRPN installed.  */
+#if $[HAVE_VRPN]
+$[define] HAVE_VRPN 1
+#else
+$[undef] HAVE_VRPN
+#endif
+
+/* Define if we have zlib installed.  */
+#if $[HAVE_ZLIB]
+$[define] HAVE_ZLIB 1
+#else
+$[undef] HAVE_ZLIB
+#endif
+
+/* Define if we have OpenGL installed and want to build for GL.  */
+#if $[HAVE_GL]
+$[define] HAVE_GL 1
+#else
+$[undef] HAVE_GL
+#endif
+
+/* Define if we have GLU installed.  */
+#if $[HAVE_GLU]
+$[define] HAVE_GLU 1
+#else
+$[undef] HAVE_GLU
+#endif
+
+/* Define if we have GLX installed and want to build for GLX.  */
+#if $[HAVE_GLX]
+$[define] HAVE_GLX 1
+#else
+$[undef] HAVE_GLX
+#endif
+
+/* Define if we have Glut installed and want to build for Glut.  */
+#if $[HAVE_GLUT]
+$[define] HAVE_GLUT 1
+#else
+$[undef] HAVE_GLUT
+#endif
+
+/* Define if we want to build the Renderman interface.  */
+#if $[HAVE_RIB]
+$[define] HAVE_RIB 1
+#else
+$[undef] HAVE_RIB
+#endif
+
+/* Define if we want to use mikmod for audio.  */
+#if $[HAVE_MIKMOD]
+$[define] HAVE_MIKMOD 1
+#else
+$[undef] HAVE_MIKMOD
+#endif
+
+/* Define if we have a gettimeofday() function. */
+#if $[HAVE_GETTIMEOFDAY]
+$[define] HAVE_GETTIMEOFDAY 1
+#else
+$[undef] HAVE_GETTIMEOFDAY
+#endif
+
+/* Define if gettimeofday() takes only one parameter. */
+#if $[GETTIMEOFDAY_ONE_PARAM]
+$[define] GETTIMEOFDAY_ONE_PARAM 1
+#else
+$[undef] GETTIMEOFDAY_ONE_PARAM
+#endif
+
+/* Define if you have the getopt function.  */
+#if $[HAVE_GETOPT]
+$[define] HAVE_GETOPT 1
+#else
+$[undef] HAVE_GETOPT
+#endif
+
+/* Define if you have the getopt_long_only function.  */
+#if $[HAVE_GETOPT_LONG_ONLY]
+$[define] HAVE_GETOPT_LONG_ONLY 1
+#else
+$[undef] HAVE_GETOPT_LONG_ONLY
+#endif
+
+/* Define if you have the <alloca.h> header file.  */
+$[define] HAVE_ALLOCA_H 1
+
+/* Define if you have the <io.h> header file.  */
+$[undef] HAVE_IO_H
+
+/* Define if you have the <iostream> header file.  */
+#if $[HAVE_IOSTREAM]
+$[define] HAVE_IOSTREAM 1
+#else
+$[undef] HAVE_IOSTREAM
+#endif
+
+/* Define if you have the <malloc.h> header file.  */
+#if $[HAVE_MALLOC_H]
+$[define] HAVE_MALLOC_H 1
+#else
+$[undef] HAVE_MALLOC_H
+#endif
+
+/* Define if you have the <alloca.h> header file.  */
+#if $[HAVE_ALLOCA_H]
+$[define] HAVE_ALLOCA_H 1
+#else
+$[undef] HAVE_ALLOCA_H
+#endif
+
+/* Define if you have the <minmax.h> header file.  */
+$[undef] HAVE_MINMAX_H
+
+/* Define if you have the <sstream> header file.  */
+#if $[HAVE_SSTREAM]
+$[define] HAVE_SSTREAM 1
+#else
+$[undef] HAVE_SSTREAM
+#endif
+
+/* Define if you have the <sys/types.h> header file.  */
+#if $[HAVE_SYS_TYPES]
+$[define] HAVE_SYS_TYPES 1
+#else
+$[undef] HAVE_SYS_TYPES
+#endif
+
+/* Define if you have the <unistd.h> header file.  */
+#if $[HAVE_UNISTD_H]
+$[define] HAVE_UNISTD_H 1
+#else
+$[undef] HAVE_UNISTD_H
+#endif
+
+/* Name of package */
+$[define] PACKAGE $[PACKAGE]
+
+/* Version number of package */
+$[define] VERSION $[VERSION]
+
+#end dtool_config.h
+
+#endif   // BUILD_TYPE

+ 11 - 0
dtool/Package.pp

@@ -0,0 +1,11 @@
+//
+// Package.pp
+//
+// This file defines a few more configuration variables that are
+// inconvenient to store in Config.pp, simply because they are more
+// specific to a particular package and not likely to be edited by a
+// configuring user.
+
+// What is the name and version of this source tree?
+#define PACKAGE dtool
+#define VERSION 0.80

+ 10 - 0
dtool/Sources.pp

@@ -0,0 +1,10 @@
+// This is the toplevel directory.  It contains configure.in and other
+// stuff.
+
+#define DIR_TYPE toplevel
+
+#define CONFIG_HEADER dtool_config.h
+#define SAMPLE_SOURCE_FILE src/dtoolbase/dtoolbase.cxx
+
+#define EXTRA_DIST \
+    Config.Irix.pp Config.Linux.pp Config.Win32.pp LocalSetup.pp Package.pp

+ 68 - 0
dtool/acconfig.h

@@ -0,0 +1,68 @@
+/* acconfig.h
+   This file is in the public domain.
+
+   Descriptive text for the C preprocessor macros that
+   the distributed Autoconf macros can define.
+   No software package will use all of them; autoheader copies the ones
+   your configure.in uses into your configuration header file templates.
+
+   The entries are in sort -df order: alphabetical, case insensitive,
+   ignoring punctuation (such as underscores).  Although this order
+   can split up related entries, it makes it easier to check whether
+   a given entry is in the file.
+
+   Leave the following blank line there!!  Autoheader needs it.  */
+
+
+/* Define if the C++ compiler uses namespaces.  */
+#undef HAVE_NAMESPACE
+
+/* Define if the C++ iostream library supports ios::binary.  */
+#undef HAVE_IOS_BINARY
+
+/* The current version number. */
+#define VERSION 0.0
+
+/* Define if we have Python installed.  */
+#undef HAVE_PYTHON
+
+/* Define if we have NSPR installed.  */
+#undef HAVE_NSPR
+
+/* Define if we have zlib installed.  */
+#undef HAVE_ZLIB
+
+/* Define if we have OpenGL installed and want to build for GL.  */
+#undef HAVE_GL
+
+/* Define if we have GLU installed.  */
+#undef HAVE_GLU
+
+/* Define if we have GLX installed and want to build for GLX.  */
+#undef HAVE_GLX
+
+/* Define if we have Glut installed and want to build for Glut.  */
+#undef HAVE_GLUT
+
+/* Define if we have DirectX installed and want to build for DirectX.  */
+#undef HAVE_DX
+
+/* Define if we want to build the Renderman interface.  */
+#undef HAVE_RIB
+
+/* Define if we want to use mikmod for audio.  */
+#undef HAVE_MIKMOD
+
+/* Define if we have a gettimeofday() function. */
+#undef HAVE_GETTIMEOFDAY
+
+/* Define if gettimeofday() takes only one parameter. */
+#undef GETTIMEOFDAY_ONE_PARAM
+
+
+/* Leave that blank line there!!  Autoheader needs it.
+   If you're adding to this file, keep in mind:
+   The entries are in sort -df order: alphabetical, case insensitive,
+   ignoring punctuation (such as underscores).  */
+
+

+ 933 - 0
dtool/acinclude.m4

@@ -0,0 +1,933 @@
+AC_DEFUN(AC_GETTIMEOFDAY,
+[AC_CACHE_CHECK([for gettimeofday()],
+  ac_cv_gettimeofday,
+[
+  AC_TRY_COMPILE([
+#include <sys/time.h>
+  ],[
+    gettimeofday((struct timeval *)NULL, (struct timezone *)NULL);
+  ], ac_cv_gettimeofday="2 params", ac_cv_gettimeofday=no)
+  if test "$ac_cv_gettimeofday" = no; then
+    AC_TRY_COMPILE([
+#include <sys/time.h>
+    ],[
+      gettimeofday((struct timeval *)NULL, (struct timezone *)NULL);
+    ], ac_cv_gettimeofday="1 param", ac_cv_gettimeofday=no)
+  fi
+])
+if test "$ac_cv_gettimeofday" = "1 param"; then
+  AC_DEFINE(GETTIMEOFDAY_ONE_PARAM)
+  AC_DEFINE(HAVE_GETTIMEOFDAY)
+elif test "$ac_cv_gettimeofday" = "2 params"; then
+  AC_DEFINE(HAVE_GETTIMEOFDAY)
+fi
+])
+
+
+AC_DEFUN(AC_HEADER_IOSTREAM,
+[AC_CHECK_HEADERS(iostream,[have_iostream=yes],[have_iostream=no])])
+
+AC_DEFUN(AC_IOS_BINARY,
+[AC_CACHE_CHECK([for ios::binary],
+  ac_cv_ios_binary,
+[
+if test $have_iostream = yes; then
+  AC_TRY_COMPILE([
+#include <iostream>
+  ],[
+  int x; x = ios::binary;
+  ], ac_cv_ios_binary=yes, ac_cv_ios_binary=no)
+else
+  AC_TRY_COMPILE([
+#include <iostream.h>
+  ],[
+  int x; x = ios::binary;
+  ], ac_cv_ios_binary=yes, ac_cv_ios_binary=no)
+fi
+
+])
+if test $ac_cv_ios_binary = yes; then
+  AC_DEFINE(HAVE_IOS_BINARY)
+fi
+])
+
+
+AC_DEFUN(AC_NAMESPACE,
+[AC_CACHE_CHECK([for compiler namespace support],
+  ac_cv_namespace,
+[AC_TRY_COMPILE(
+[namespace std { };
+using namespace std;],
+[],
+  ac_cv_namespace=yes, ac_cv_namespace=no)])
+if test $ac_cv_namespace = yes; then
+  AC_DEFINE(HAVE_NAMESPACE)
+fi
+])
+
+
+dnl A handy function to see if a library is in a particular directory.
+dnl AC_CHECK_LIB_LOC(directory, library, function, action-if-found, action-if-not-found, other-libraries)
+dnl
+AC_DEFUN(AC_CHECK_LIB_LOC,
+[AC_MSG_CHECKING([for lib$2 in $1])
+ac_lib_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
+AC_CACHE_VAL(ac_cv_lib_loc_$ac_lib_var,
+[ac_save_LIBS="$LIBS"
+LIBS="-L$1 -l$2 $6 $LIBS"
+AC_TRY_LINK(dnl
+ifelse(AC_LANG, CPLUSPLUS, [#ifdef __cplusplus
+extern "C"
+#endif
+])dnl
+[/* We use char because int might match the return type of a gcc2
+    builtin and then its argument prototype would still apply.  */
+char $3();
+],
+            [$3()],
+            eval "ac_cv_lib_loc_$ac_lib_var=yes",
+            eval "ac_cv_lib_loc_$ac_lib_var=no")
+LIBS="$ac_save_LIBS"
+])dnl
+if eval "test \"`echo '$ac_cv_lib_loc_'$ac_lib_var`\" = yes"; then
+  AC_MSG_RESULT(yes)
+  ifelse([$4], ,
+[LIBS="-L$1 -l$2 $LIBS"
+], [$4])
+else
+  AC_MSG_RESULT(no)
+ifelse([$5], , , [$5
+])dnl
+fi
+])
+
+dnl A handy function to search a number of possible locations for a library.
+dnl AC_SEARCH_LIB(search-dirs, library, function, package, other-libraries)
+dnl 
+dnl Sets $package_LIB to the directory containing the library, or to the
+dnl string "no" if the library cannot be found.
+AC_DEFUN(AC_SEARCH_LIB, [
+ac_found_lib="no"
+if test "$1" = ""; then
+  AC_CHECK_LIB($2, $3, [ ac_found_lib=""; ],, $5)
+else
+  for ac_check_dir in $1; do
+    if test "$ac_found_lib" = "no"; then
+      AC_CHECK_LIB_LOC($ac_check_dir, $2, $3, [ ac_found_lib="$ac_check_dir"; ],, $5)
+    fi
+  done
+fi
+$4_LIB="$ac_found_lib"
+])
+
+dnl A handy function to see if a header file is in a particular directory.
+dnl AC_CHECK_HEADER_LOC(directory, header, action-if-found, action-if-not-found)
+dnl
+AC_DEFUN(AC_CHECK_HEADER_LOC, [
+  AC_MSG_CHECKING([for $2 in $1])
+  ac_include_var=`echo $1['_']$2 | sed 'y%./+-%__p_%'`
+  AC_CACHE_VAL(ac_cv_include_loc_$ac_include_var, [
+    ac_save_CPPFLAGS="$CPPFLAGS"
+    CPPFLAGS="-I$1 $CPPFLAGS"
+    AC_TRY_CPP([#include <$2>], ac_ch_found_it="yes", ac_ch_found_it="no")
+    if test "$ac_ch_found_it" = "yes"; then
+      AC_MSG_RESULT(yes)
+      ifelse([$3], , :, [$3])
+    else
+      AC_MSG_RESULT(no)
+      ifelse([$4], , , [$4])
+    fi
+    CPPFLAGS="$ac_save_CPPFLAGS"
+  ])
+])
+
+
+dnl A handy function to search a number of possible locations for a header
+dnl file.
+dnl
+dnl AC_SEARCH_HEADER(search-dirs, header, package)
+dnl
+dnl Sets $package_INCLUDE to the directory containing the header, or to
+dnl the string "no" if the header cannot be found.
+AC_DEFUN(AC_SEARCH_HEADER, [
+ac_found_header="no"
+if test "$1" = ""; then
+  AC_CHECK_HEADER($2, [ ac_found_header="";])
+else
+  for ac_check_dir in $1; do
+    if test "$ac_found_header" = "no"; then
+      AC_CHECK_HEADER_LOC($ac_check_dir, $2, [ ac_found_header="$ac_check_dir";])
+    fi
+  done
+fi
+$3_INCLUDE="$ac_found_header"
+])
+
+
+dnl A handy function to scan for a third-party package, consisting of at
+dnl least a library and an include file.  A few assumptions are made about
+dnl the relationships between lib and include directories.
+dnl
+dnl AC_SEARCH_PACKAGE(search-dirs, package-names, header, library, function, package, other-libraries)
+dnl
+dnl search-dirs is the whitespace-separated list of directory prefixes to
+dnl   check.
+dnl package-names is a whitespace-separated list of possible names the
+dnl   package may have been installed under.
+dnl
+dnl For each combination of ${search-dir} and ${package-name}, the following
+dnl directories are searched:
+dnl
+dnl   ${search-dir}
+dnl   ${search-dir}/lib
+dnl   ${search-dir}/${package-name}
+dnl   ${search-dir}/${package-name}/lib
+dnl   ${search-dir}/lib/${package-name}
+dnl
+dnl And similarly for include.
+dnl
+dnl Sets the variables $package_INCLUDE and $package_LIB to the directories
+dnl containing the header file and library, respectively.  If both pieces
+dnl are located, also sets the variable $package_PKG to "yes"; otherwise,
+dnl sets the variable $package_PKG to "no".
+dnl
+AC_DEFUN(AC_SEARCH_PACKAGE, [
+$6_LIB="no"
+$6_INCLUDE="no"
+$6_PKG="no"
+
+dnl Look for the library.
+AC_SEARCH_LIB("", $4, $5, $6, $7)
+for ac_sp_dir in $1; do
+  if test "[$]$6_LIB" = "no"; then
+    AC_SEARCH_LIB("$ac_sp_dir" "$ac_sp_dir/lib", $4, $5, $6, $7)
+    for ac_sp_pkg in $2; do
+      if test "[$]$6_LIB" = "no"; then
+        AC_SEARCH_LIB("$ac_sp_dir/$ac_sp_pkg" "$ac_sp_dir/$ac_sp_pkg/lib" \
+                      "$ac_sp_dir/lib/$ac_sp_pkg", $4, $5, $6, $7)
+      fi
+    done
+  fi
+done
+
+dnl Now look for the header file.  Don't bother looking if the library
+dnl wasn't found.
+if test "[$]$6_LIB" != "no"; then
+  dnl First look in the obvious directory corresponding to the lib dir.
+  ac_sp_testinc=`echo [$]$6_LIB | sed 's:/lib:/include:'`
+  AC_SEARCH_HEADER("$ac_sp_testinc", $3, $6)
+
+  dnl If it wasn't found there, cast about.
+  if test "[$]$6_INCLUDE" = "no"; then
+    for ac_sp_dir in $1; do
+      if test "[$]$6_INCLUDE" = "no"; then
+        AC_SEARCH_HEADER("$ac_sp_dir" "$ac_sp_dir/include", $3, $6)
+        for ac_sp_pkg in $2; do
+          if test "[$]$6_INCLUDE" = "no"; then
+            AC_SEARCH_HEADER("$ac_sp_dir/$ac_sp_pkg" \
+                             "$ac_sp_dir/$ac_sp_pkg/include" \
+                             "$ac_sp_dir/include/$ac_sp_pkg", $3, $6)
+          fi
+        done
+      fi
+    done
+  fi
+
+  dnl If we got both a header and a library, set the PKG variable.
+  if test "[$]$6_INCLUDE" != "no"; then
+    $6_PKG="yes"
+  fi
+fi
+])  
+
+dnl A handy function, similar to AC_SEARCH_PACKAGE, above, that looks for a
+dnl package that only consists of header files, no libraries.
+dnl
+dnl AC_SEARCH_HPACKAGE(search-dirs, package-names, header, package)
+dnl
+dnl search-dirs is the whitespace-separated list of directory prefixes to
+dnl   check.
+dnl package-names is a whitespace-separated list of possible names the
+dnl   package may have been installed under.
+dnl
+dnl For each combination of ${search-dir} and ${package-name}, the following
+dnl directories are searched:
+dnl
+dnl   ${search-dir}
+dnl   ${search-dir}/include
+dnl   ${search-dir}/${package-name}
+dnl   ${search-dir}/${package-name}/include
+dnl   ${search-dir}/include/${package-name}
+dnl
+dnl Sets the variable $package_INCLUDE to the directory containing the
+dnl header file, and sets the variable $package_PKG to "yes"; if the
+dnl directory is not found, sets the variable $package_PKG to "no".
+dnl
+AC_DEFUN(AC_SEARCH_HPACKAGE, [
+$4_INCLUDE="no"
+$4_PKG="no"
+
+dnl Look for the header.
+AC_SEARCH_HEADER("", $3, $4)
+for ac_sp_dir in $1; do
+  if test "[$]$4_INCLUDE" = "no"; then
+    AC_SEARCH_HEADER("$ac_sp_dir" "$ac_sp_dir/include", $3, $4)
+    for ac_sp_pkg in $2; do
+      if test "[$]$4_INCLUDE" = "no"; then
+        AC_SEARCH_HEADER("$ac_sp_dir/$ac_sp_pkg" \
+                         "$ac_sp_dir/$ac_sp_pkg/include" \
+                         "$ac_sp_dir/include/$ac_sp_pkg", $3, $4)
+      fi
+    done
+  fi
+done
+
+dnl If we got both a header file, set the PKG variable.
+if test "[$]$4_INCLUDE" != "no"; then
+  $4_PKG="yes"
+fi
+])  
+
+# Define a conditional.
+
+AC_DEFUN(AM_CONDITIONAL,
+[AC_SUBST($1_TRUE)
+AC_SUBST($1_FALSE)
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi])
+
+
+
+
+# Configure paths for GTK--
+# Erik Andersen	30 May 1998
+# Modified by Tero Pulkkinen (added the compiler checks... I hope they work..)
+
+dnl Test for GTKMM, and define GTKMM_CFLAGS and GTKMM_LIBS
+dnl   to be used as follows:
+dnl AM_PATH_GTKMM([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl
+AC_DEFUN(AM_PATH_GTKMM,
+[dnl 
+dnl Get the cflags and libraries from the gtkmm-config script
+dnl
+AC_ARG_WITH(gtkmm-prefix,[  --with-gtkmm-prefix=PREFIX
+                          Prefix where GTK-- is installed (optional)],
+            gtkmm_config_prefix="$withval", gtkmm_config_prefix="")
+AC_ARG_WITH(gtkmm-exec-prefix,[  --with-gtkmm-exec-prefix=PREFIX
+                          Exec prefix where GTK-- is installed (optional)],
+            gtkmm_config_exec_prefix="$withval", gtkmm_config_exec_prefix="")
+AC_ARG_ENABLE(gtkmmtest, [  --disable-gtkmmtest     Do not try to compile and run a test GTK-- program],
+		    , enable_gtkmmtest=yes)
+
+  if test x$gtkmm_config_exec_prefix != x ; then
+     gtkmm_config_args="$gtkmm_config_args --exec-prefix=$gtkmm_config_exec_prefix"
+     if test x${GTKMM_CONFIG+set} != xset ; then
+        GTKMM_CONFIG=$gtkmm_config_exec_prefix/bin/gtkmm-config
+     fi
+  fi
+  if test x$gtkmm_config_prefix != x ; then
+     gtkmm_config_args="$gtkmm_config_args --prefix=$gtkmm_config_prefix"
+     if test x${GTKMM_CONFIG+set} != xset ; then
+        GTKMM_CONFIG=$gtkmm_config_prefix/bin/gtkmm-config
+     fi
+  fi
+
+  AC_PATH_PROG(GTKMM_CONFIG, gtkmm-config, no)
+  min_gtkmm_version=ifelse([$1], ,0.10.0,$1)
+
+  AC_MSG_CHECKING(for GTK-- - version >= $min_gtkmm_version)
+  no_gtkmm=""
+  if test "$GTKMM_CONFIG" = "no" ; then
+    no_gtkmm=yes
+  else
+    AC_LANG_SAVE
+    AC_LANG_CPLUSPLUS
+
+    GTKMM_CFLAGS=`$GTKMM_CONFIG $gtkmm_config_args --cflags`
+    GTKMM_LIBS=`$GTKMM_CONFIG $gtkmm_config_args --libs`
+    gtkmm_config_major_version=`$GTKMM_CONFIG $gtkmm_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    gtkmm_config_minor_version=`$GTKMM_CONFIG $gtkmm_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    gtkmm_config_micro_version=`$GTKMM_CONFIG $gtkmm_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_gtkmmtest" = "xyes" ; then
+      ac_save_CXXFLAGS="$CXXFLAGS"
+      ac_save_LIBS="$LIBS"
+      CXXFLAGS="$CXXFLAGS $GTKMM_CFLAGS"
+      LIBS="$LIBS $GTKMM_LIBS"
+dnl
+dnl Now check if the installed GTK-- is sufficiently new. (Also sanity
+dnl checks the results of gtkmm-config to some extent
+dnl
+      rm -f conf.gtkmmtest
+      AC_TRY_RUN([
+#include <gtk--.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int 
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gtkmmtest");
+
+  /* HP/UX 0 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_gtkmm_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_gtkmm_version");
+     exit(1);
+   }
+
+  if ((gtkmm_major_version != $gtkmm_config_major_version) ||
+      (gtkmm_minor_version != $gtkmm_config_minor_version) ||
+      (gtkmm_micro_version != $gtkmm_config_micro_version))
+    {
+      printf("\n*** 'gtkmm-config --version' returned %d.%d.%d, but GTK-- (%d.%d.%d)\n", 
+             $gtkmm_config_major_version, $gtkmm_config_minor_version, $gtkmm_config_micro_version,
+             gtkmm_major_version, gtkmm_minor_version, gtkmm_micro_version);
+      printf ("*** was found! If gtkmm-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GTK--. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If gtkmm-config was wrong, set the environment variable GTKMM_CONFIG\n");
+      printf("*** to point to the correct copy of gtkmm-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    } 
+/* GTK-- does not have the GTKMM_*_VERSION constants */
+/* 
+  else if ((gtkmm_major_version != GTKMM_MAJOR_VERSION) ||
+	   (gtkmm_minor_version != GTKMM_MINOR_VERSION) ||
+           (gtkmm_micro_version != GTKMM_MICRO_VERSION))
+    {
+      printf("*** GTK-- header files (version %d.%d.%d) do not match\n",
+	     GTKMM_MAJOR_VERSION, GTKMM_MINOR_VERSION, GTKMM_MICRO_VERSION);
+      printf("*** library (version %d.%d.%d)\n",
+	     gtkmm_major_version, gtkmm_minor_version, gtkmm_micro_version);
+    }
+*/
+  else
+    {
+      if ((gtkmm_major_version > major) ||
+        ((gtkmm_major_version == major) && (gtkmm_minor_version > minor)) ||
+        ((gtkmm_major_version == major) && (gtkmm_minor_version == minor) && (gtkmm_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GTK-- (%d.%d.%d) was found.\n",
+               gtkmm_major_version, gtkmm_minor_version, gtkmm_micro_version);
+        printf("*** You need a version of GTK-- newer than %d.%d.%d. The latest version of\n",
+	       major, minor, micro);
+        printf("*** GTK-- is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the gtkmm-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GTK--, but you can also set the GTKMM_CONFIG environment to point to the\n");
+        printf("*** correct copy of gtkmm-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+],, no_gtkmm=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CXXFLAGS="$ac_save_CXXFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gtkmm" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$GTKMM_CONFIG" = "no" ; then
+       echo "*** The gtkmm-config script installed by GTK-- could not be found"
+       echo "*** If GTK-- was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GTKMM_CONFIG environment variable to the"
+       echo "*** full path to gtkmm-config."
+       echo "*** The gtkmm-config script was not available in GTK-- versions"
+       echo "*** prior to 0.9.12. Perhaps you need to update your installed"
+       echo "*** version to 0.9.12 or later"
+     else
+       if test -f conf.gtkmmtest ; then
+        :
+       else
+          echo "*** Could not run GTK-- test program, checking why..."
+          CXXFLAGS="$CFLAGS $GTKMM_CXXFLAGS"
+          LIBS="$LIBS $GTKMM_LIBS"
+          AC_TRY_LINK([
+#include <gtk--.h>
+#include <stdio.h>
+],      [ return ((gtkmm_major_version) || (gtkmm_minor_version) || (gtkmm_micro_version)); ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GTK-- or finding the wrong"
+          echo "*** version of GTK--. If it is not finding GTK--, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" ],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GTK-- was incorrectly installed"
+          echo "*** or that you have moved GTK-- since it was installed. In the latter case, you"
+          echo "*** may want to edit the gtkmm-config script: $GTKMM_CONFIG" ])
+          CXXFLAGS="$ac_save_CXXFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GTKMM_CFLAGS=""
+     GTKMM_LIBS=""
+     ifelse([$3], , :, [$3])
+     AC_LANG_RESTORE
+  fi
+  AC_SUBST(GTKMM_CFLAGS)
+  AC_SUBST(GTKMM_LIBS)
+  rm -f conf.gtkmmtest
+])
+
+
+## libtool.m4 - Configure libtool for the target system. -*-Shell-script-*-
+## Copyright (C) 1996-1999 Free Software Foundation, Inc.
+## Originally by Gordon Matzigkeit <[email protected]>, 1996
+##
+## This program is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+##
+## As a special exception to the GNU General Public License, if you
+## distribute this file as part of a program that contains a
+## configuration script generated by Autoconf, you may include it under
+## the same distribution terms that you use for the rest of that program.
+
+# serial 40 AC_PROG_LIBTOOL
+AC_DEFUN(AC_PROG_LIBTOOL,
+[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl
+
+# Save cache, so that ltconfig can load it
+AC_CACHE_SAVE
+
+# Actually configure libtool.  ac_aux_dir is where install-sh is found.
+CC="$CC" CFLAGS="$CFLAGS" CPPFLAGS="$CPPFLAGS" \
+LD="$LD" LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
+LN_S="$LN_S" NM="$NM" RANLIB="$RANLIB" \
+DLLTOOL="$DLLTOOL" AS="$AS" OBJDUMP="$OBJDUMP" \
+${CONFIG_SHELL-/bin/sh} $ac_aux_dir/ltconfig --no-reexec \
+$libtool_flags --no-verify $ac_aux_dir/ltmain.sh $host \
+|| AC_MSG_ERROR([libtool configure failed])
+
+# Reload cache, that may have been modified by ltconfig
+AC_CACHE_LOAD
+
+# This can be used to rebuild libtool when needed
+LIBTOOL_DEPS="$ac_aux_dir/ltconfig $ac_aux_dir/ltmain.sh"
+
+# Always use our own libtool.
+LIBTOOL='$(SHELL) $(top_builddir)/libtool'
+AC_SUBST(LIBTOOL)dnl
+
+# Redirect the config.log output again, so that the ltconfig log is not
+# clobbered by the next message.
+exec 5>>./config.log
+])
+
+AC_DEFUN(AC_LIBTOOL_SETUP,
+[AC_PREREQ(2.13)dnl
+AC_REQUIRE([AC_ENABLE_SHARED])dnl
+AC_REQUIRE([AC_ENABLE_STATIC])dnl
+AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+AC_REQUIRE([AC_PROG_RANLIB])dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_LD])dnl
+AC_REQUIRE([AC_PROG_NM])dnl
+AC_REQUIRE([AC_PROG_LN_S])dnl
+dnl
+
+# Check for any special flags to pass to ltconfig.
+#
+# the following will cause an existing older ltconfig to fail, so
+# we ignore this at the expense of the cache file... Checking this 
+# will just take longer ... bummer!
+#libtool_flags="--cache-file=$cache_file"
+#
+test "$enable_shared" = no && libtool_flags="$libtool_flags --disable-shared"
+test "$enable_static" = no && libtool_flags="$libtool_flags --disable-static"
+test "$enable_fast_install" = no && libtool_flags="$libtool_flags --disable-fast-install"
+test "$ac_cv_prog_gcc" = yes && libtool_flags="$libtool_flags --with-gcc"
+test "$ac_cv_prog_gnu_ld" = yes && libtool_flags="$libtool_flags --with-gnu-ld"
+ifdef([AC_PROVIDE_AC_LIBTOOL_DLOPEN],
+[libtool_flags="$libtool_flags --enable-dlopen"])
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+[libtool_flags="$libtool_flags --enable-win32-dll"])
+AC_ARG_ENABLE(libtool-lock,
+  [  --disable-libtool-lock  avoid locking (might break parallel builds)])
+test "x$enable_libtool_lock" = xno && libtool_flags="$libtool_flags --disable-lock"
+test x"$silent" = xyes && libtool_flags="$libtool_flags --silent"
+
+# Some flags need to be propagated to the compiler or linker for good
+# libtool support.
+case "$host" in
+*-*-irix6*)
+  # Find out which ABI we are using.
+  echo '[#]line __oline__ "configure"' > conftest.$ac_ext
+  if AC_TRY_EVAL(ac_compile); then
+    case "`/usr/bin/file conftest.o`" in
+    *32-bit*)
+      LD="${LD-ld} -32"
+      ;;
+    *N32*)
+      LD="${LD-ld} -n32"
+      ;;
+    *64-bit*)
+      LD="${LD-ld} -64"
+      ;;
+    esac
+  fi
+  rm -rf conftest*
+  ;;
+
+*-*-sco3.2v5*)
+  # On SCO OpenServer 5, we need -belf to get full-featured binaries.
+  SAVE_CFLAGS="$CFLAGS"
+  CFLAGS="$CFLAGS -belf"
+  AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf,
+    [AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no])])
+  if test x"$lt_cv_cc_needs_belf" != x"yes"; then
+    # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf
+    CFLAGS="$SAVE_CFLAGS"
+  fi
+  ;;
+
+ifdef([AC_PROVIDE_AC_LIBTOOL_WIN32_DLL],
+[*-*-cygwin* | *-*-mingw*)
+  AC_CHECK_TOOL(DLLTOOL, dlltool, false)
+  AC_CHECK_TOOL(AS, as, false)
+  AC_CHECK_TOOL(OBJDUMP, objdump, false)
+  ;;
+])
+esac
+])
+
+# AC_LIBTOOL_DLOPEN - enable checks for dlopen support
+AC_DEFUN(AC_LIBTOOL_DLOPEN, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])])
+
+# AC_LIBTOOL_WIN32_DLL - declare package support for building win32 dll's
+AC_DEFUN(AC_LIBTOOL_WIN32_DLL, [AC_BEFORE([$0], [AC_LIBTOOL_SETUP])])
+
+# AC_ENABLE_SHARED - implement the --enable-shared flag
+# Usage: AC_ENABLE_SHARED[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_SHARED, [dnl
+define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(shared,
+changequote(<<, >>)dnl
+<<  --enable-shared[=PKGS]  build shared libraries [default=>>AC_ENABLE_SHARED_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_shared=yes ;;
+no) enable_shared=no ;;
+*)
+  enable_shared=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_shared=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_shared=AC_ENABLE_SHARED_DEFAULT)dnl
+])
+
+# AC_DISABLE_SHARED - set the default shared flag to --disable-shared
+AC_DEFUN(AC_DISABLE_SHARED, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_SHARED(no)])
+
+# AC_ENABLE_STATIC - implement the --enable-static flag
+# Usage: AC_ENABLE_STATIC[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_STATIC, [dnl
+define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(static,
+changequote(<<, >>)dnl
+<<  --enable-static[=PKGS]  build static libraries [default=>>AC_ENABLE_STATIC_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_static=yes ;;
+no) enable_static=no ;;
+*)
+  enable_static=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_static=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_static=AC_ENABLE_STATIC_DEFAULT)dnl
+])
+
+# AC_DISABLE_STATIC - set the default static flag to --disable-static
+AC_DEFUN(AC_DISABLE_STATIC, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_STATIC(no)])
+
+
+# AC_ENABLE_FAST_INSTALL - implement the --enable-fast-install flag
+# Usage: AC_ENABLE_FAST_INSTALL[(DEFAULT)]
+#   Where DEFAULT is either `yes' or `no'.  If omitted, it defaults to
+#   `yes'.
+AC_DEFUN(AC_ENABLE_FAST_INSTALL, [dnl
+define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl
+AC_ARG_ENABLE(fast-install,
+changequote(<<, >>)dnl
+<<  --enable-fast-install[=PKGS]  optimize for fast installation [default=>>AC_ENABLE_FAST_INSTALL_DEFAULT],
+changequote([, ])dnl
+[p=${PACKAGE-default}
+case "$enableval" in
+yes) enable_fast_install=yes ;;
+no) enable_fast_install=no ;;
+*)
+  enable_fast_install=no
+  # Look at the argument we got.  We use all the common list separators.
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}:,"
+  for pkg in $enableval; do
+    if test "X$pkg" = "X$p"; then
+      enable_fast_install=yes
+    fi
+  done
+  IFS="$ac_save_ifs"
+  ;;
+esac],
+enable_fast_install=AC_ENABLE_FAST_INSTALL_DEFAULT)dnl
+])
+
+# AC_ENABLE_FAST_INSTALL - set the default to --disable-fast-install
+AC_DEFUN(AC_DISABLE_FAST_INSTALL, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+AC_ENABLE_FAST_INSTALL(no)])
+
+# AC_PROG_LD - find the path to the GNU or non-GNU linker
+AC_DEFUN(AC_PROG_LD,
+[AC_ARG_WITH(gnu-ld,
+[  --with-gnu-ld           assume the C compiler uses GNU ld [default=no]],
+test "$withval" = no || with_gnu_ld=yes, with_gnu_ld=no)
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+AC_REQUIRE([AC_CANONICAL_BUILD])dnl
+ac_prog=ld
+if test "$ac_cv_prog_gcc" = yes; then
+  # Check if gcc -print-prog-name=ld gives a path.
+  AC_MSG_CHECKING([for ld used by GCC])
+  ac_prog=`($CC -print-prog-name=ld) 2>&5`
+  case "$ac_prog" in
+    # Accept absolute paths.
+changequote(,)dnl
+    [\\/]* | [A-Za-z]:[\\/]*)
+      re_direlt='/[^/][^/]*/\.\./'
+changequote([,])dnl
+      # Canonicalize the path of ld
+      ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'`
+      while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do
+	ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"`
+      done
+      test -z "$LD" && LD="$ac_prog"
+      ;;
+  "")
+    # If it fails, then pretend we aren't using GCC.
+    ac_prog=ld
+    ;;
+  *)
+    # If it is relative, then search for the first ld in PATH.
+    with_gnu_ld=unknown
+    ;;
+  esac
+elif test "$with_gnu_ld" = yes; then
+  AC_MSG_CHECKING([for GNU ld])
+else
+  AC_MSG_CHECKING([for non-GNU ld])
+fi
+AC_CACHE_VAL(ac_cv_path_LD,
+[if test -z "$LD"; then
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then
+      ac_cv_path_LD="$ac_dir/$ac_prog"
+      # Check to see if the program is GNU ld.  I'd rather use --version,
+      # but apparently some GNU ld's only accept -v.
+      # Break only if it was the GNU/non-GNU ld that we prefer.
+      if "$ac_cv_path_LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then
+	test "$with_gnu_ld" != no && break
+      else
+	test "$with_gnu_ld" != yes && break
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+else
+  ac_cv_path_LD="$LD" # Let the user override the test with a path.
+fi])
+LD="$ac_cv_path_LD"
+if test -n "$LD"; then
+  AC_MSG_RESULT($LD)
+else
+  AC_MSG_RESULT(no)
+fi
+test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH])
+AC_SUBST(LD)
+AC_PROG_LD_GNU
+])
+
+AC_DEFUN(AC_PROG_LD_GNU,
+[AC_CACHE_CHECK([if the linker ($LD) is GNU ld], ac_cv_prog_gnu_ld,
+[# I'd rather use --version here, but apparently some GNU ld's only accept -v.
+if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then
+  ac_cv_prog_gnu_ld=yes
+else
+  ac_cv_prog_gnu_ld=no
+fi])
+])
+
+# AC_PROG_NM - find the path to a BSD-compatible name lister
+AC_DEFUN(AC_PROG_NM,
+[AC_MSG_CHECKING([for BSD-compatible nm])
+AC_CACHE_VAL(ac_cv_path_NM,
+[if test -n "$NM"; then
+  # Let the user override the test.
+  ac_cv_path_NM="$NM"
+else
+  IFS="${IFS= 	}"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR-:}"
+  for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do
+    test -z "$ac_dir" && ac_dir=.
+    if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext ; then
+      # Check to see if the nm accepts a BSD-compat flag.
+      # Adding the `sed 1q' prevents false positives on HP-UX, which says:
+      #   nm: unknown option "B" ignored
+      if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+	ac_cv_path_NM="$ac_dir/nm -B"
+	break
+      elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then
+	ac_cv_path_NM="$ac_dir/nm -p"
+	break
+      else
+	ac_cv_path_NM=${ac_cv_path_NM="$ac_dir/nm"} # keep the first match, but
+	continue # so that we can try to find one that supports BSD flags
+      fi
+    fi
+  done
+  IFS="$ac_save_ifs"
+  test -z "$ac_cv_path_NM" && ac_cv_path_NM=nm
+fi])
+NM="$ac_cv_path_NM"
+AC_MSG_RESULT([$NM])
+AC_SUBST(NM)
+])
+
+# AC_CHECK_LIBM - check for math library
+AC_DEFUN(AC_CHECK_LIBM,
+[AC_REQUIRE([AC_CANONICAL_HOST])dnl
+LIBM=
+case "$host" in
+*-*-beos* | *-*-cygwin*)
+  # These system don't have libm
+  ;;
+*-ncr-sysv4.3*)
+  AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw")
+  AC_CHECK_LIB(m, main, LIBM="$LIBM -lm")
+  ;;
+*)
+  AC_CHECK_LIB(m, main, LIBM="-lm")
+  ;;
+esac
+])
+
+# AC_LIBLTDL_CONVENIENCE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl convenience library, adds --enable-ltdl-convenience to
+# the configure arguments.  Note that LIBLTDL is not AC_SUBSTed, nor
+# is AC_CONFIG_SUBDIRS called.  If DIR is not provided, it is assumed
+# to be `${top_builddir}/libltdl'.  Make sure you start DIR with
+# '${top_builddir}/' (note the single quotes!) if your package is not
+# flat, and, if you're not using automake, define top_builddir as
+# appropriate in the Makefiles.
+AC_DEFUN(AC_LIBLTDL_CONVENIENCE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  case "$enable_ltdl_convenience" in
+  no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;;
+  "") enable_ltdl_convenience=yes
+      ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;;
+  esac
+  LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdlc.la
+  INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
+])
+
+# AC_LIBLTDL_INSTALLABLE[(dir)] - sets LIBLTDL to the link flags for
+# the libltdl installable library, and adds --enable-ltdl-install to
+# the configure arguments.  Note that LIBLTDL is not AC_SUBSTed, nor
+# is AC_CONFIG_SUBDIRS called.  If DIR is not provided, it is assumed
+# to be `${top_builddir}/libltdl'.  Make sure you start DIR with
+# '${top_builddir}/' (note the single quotes!) if your package is not
+# flat, and, if you're not using automake, define top_builddir as
+# appropriate in the Makefiles.
+# In the future, this macro may have to be called after AC_PROG_LIBTOOL.
+AC_DEFUN(AC_LIBLTDL_INSTALLABLE, [AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl
+  AC_CHECK_LIB(ltdl, main,
+  [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no],
+  [if test x"$enable_ltdl_install" = xno; then
+     AC_MSG_WARN([libltdl not installed, but installation disabled])
+   else
+     enable_ltdl_install=yes
+   fi
+  ])
+  if test x"$enable_ltdl_install" = x"yes"; then
+    ac_configure_args="$ac_configure_args --enable-ltdl-install"
+    LIBLTDL=ifelse($#,1,$1,['${top_builddir}/libltdl'])/libltdl.la
+    INCLTDL=ifelse($#,1,-I$1,['-I${top_builddir}/libltdl'])
+  else
+    ac_configure_args="$ac_configure_args --enable-ltdl-install=no"
+    LIBLTDL="-lltdl"
+    INCLTDL=
+  fi
+])
+
+dnl old names
+AC_DEFUN(AM_PROG_LIBTOOL, [indir([AC_PROG_LIBTOOL])])dnl
+AC_DEFUN(AM_ENABLE_SHARED, [indir([AC_ENABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_ENABLE_STATIC, [indir([AC_ENABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_DISABLE_SHARED, [indir([AC_DISABLE_SHARED], $@)])dnl
+AC_DEFUN(AM_DISABLE_STATIC, [indir([AC_DISABLE_STATIC], $@)])dnl
+AC_DEFUN(AM_PROG_LD, [indir([AC_PROG_LD])])dnl
+AC_DEFUN(AM_PROG_NM, [indir([AC_PROG_NM])])dnl
+
+dnl This is just to silence aclocal about the macro not being used
+ifelse([AC_DISABLE_FAST_INSTALL])dnl

+ 96 - 0
dtool/dtool_config.h

@@ -0,0 +1,96 @@
+/* dtool_config.h.  Generated automatically by ppremake 0.20 from Sources.pp. */
+
+/* Define if you have the ANSI C header files.  */
+#define STDC_HEADERS 1
+
+/* Define if your processor stores words with the most significant
+   byte first (like Motorola and SPARC, unlike Intel and VAX).  */
+#undef WORDS_BIGENDIAN
+
+/* Define if the X Window System is missing or not being used.  */
+#undef X_DISPLAY_MISSING
+
+/* Define if lex declares yytext as a char * by default, not a char[].  */
+#undef YYTEXT_POINTER
+
+/* Define if the C++ compiler uses namespaces.  */
+#define HAVE_NAMESPACE 1
+
+/* Define if the C++ iostream library supports ios::binary.  */
+#define HAVE_IOS_BINARY 1
+
+/* Define if we have Python installed.  */
+#define HAVE_PYTHON 1
+
+/* Define if we have NSPR installed.  */
+#define HAVE_NSPR 1
+
+/* Define if we have VRPN installed.  */
+#undef HAVE_VRPN
+
+/* Define if we have zlib installed.  */
+#define HAVE_ZLIB 1
+
+/* Define if we have OpenGL installed and want to build for GL.  */
+#define HAVE_GL 1
+
+/* Define if we have GLU installed.  */
+#undef HAVE_GLU
+
+/* Define if we have GLX installed and want to build for GLX.  */
+#define HAVE_GLX 1
+
+/* Define if we have Glut installed and want to build for Glut.  */
+#undef HAVE_GLUT
+
+/* Define if we want to build the Renderman interface.  */
+#undef HAVE_RIB
+
+/* Define if we want to use mikmod for audio.  */
+#undef HAVE_MIKMOD
+
+/* Define if we have a gettimeofday() function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define if gettimeofday() takes only one parameter. */
+#undef GETTIMEOFDAY_ONE_PARAM
+
+/* Define if you have the getopt function.  */
+#define HAVE_GETOPT 1
+
+/* Define if you have the getopt_long_only function.  */
+#define HAVE_GETOPT_LONG_ONLY 1
+
+/* Define if you have the <alloca.h> header file.  */
+#define HAVE_ALLOCA_H 1
+
+/* Define if you have the <io.h> header file.  */
+#undef HAVE_IO_H
+
+/* Define if you have the <iostream> header file.  */
+#undef HAVE_IOSTREAM
+
+/* Define if you have the <malloc.h> header file.  */
+#define HAVE_MALLOC_H 1
+
+/* Define if you have the <alloca.h> header file.  */
+#define HAVE_ALLOCA_H 1
+
+/* Define if you have the <minmax.h> header file.  */
+#undef HAVE_MINMAX_H
+
+/* Define if you have the <sstream> header file.  */
+#undef HAVE_SSTREAM
+
+/* Define if you have the <sys/types.h> header file.  */
+#undef HAVE_SYS_TYPES
+
+/* Define if you have the <unistd.h> header file.  */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+#define PACKAGE dtool
+
+/* Version number of package */
+#define VERSION 0.80
+

+ 7 - 0
dtool/metalibs/Sources.pp

@@ -0,0 +1,7 @@
+// This is a group directory: a directory level above a number of
+// source subdirectories.
+
+#define DIR_TYPE group
+
+// The metalibs directory always depends on the src directory.
+#define DEPENDS src

+ 17 - 0
dtool/metalibs/dtool/Sources.pp

@@ -0,0 +1,17 @@
+// DIR_TYPE "metalib" indicates we are building a shared library that
+// consists mostly of references to other shared libraries.  Under
+// Windows, this directly produces a DLL (as opposed to the regular
+// src libraries, which don't produce anything but a pile of OBJ files
+// under Windows).
+
+#define DIR_TYPE metalib
+#define BUILDING_DLL BUILDING_DTOOL
+
+#define LOCAL_LIBS interrogatedb dconfig dtoolutil dtoolbase
+
+#begin metalib_target
+  #define TARGET dtool
+
+  #define SOURCES dtool.cxx
+  #define IF_PYTHON_SOURCES pydtool.cxx
+#end metalib_target

+ 11 - 0
dtool/metalibs/dtool/dtool.cxx

@@ -0,0 +1,11 @@
+// Filename: dtool.C
+// Created by:  drose (15May00)
+// 
+////////////////////////////////////////////////////////////////////
+
+// This is a dummy file whose sole purpose is to give the compiler
+// something to compile when making libdtool.so in NO_DEFER mode,
+// which generates an empty library that itself links with all the
+// other shared libraries that make up libdtool.
+
+

+ 1680 - 0
dtool/metalibs/dtool/pydtool.cxx

@@ -0,0 +1,1680 @@
+/*
+ * This file generated by:
+ * interrogate -nodb -python -promiscuous -I /usr/local/dtool/include -module dtool -library libdtool -true-names -do-module -oc pydtool.cc interrogate_interface.h 
+ *
+ */
+
+
+#include "interrogate_interface.h"
+#include <dtoolbase.h>
+
+#undef HAVE_LONG_LONG
+#include <Python.h>
+
+extern "C" {
+
+/*
+ * Python wrapper for
+ * int interrogate_number_of_manifests();
+ */
+static PyObject *
+_inPCPDJwgip(PyObject *, PyObject *args) {
+  if (PyArg_ParseTuple(args, "")) {
+    int return_value = interrogate_number_of_manifests();
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_manifest(int n);
+ */
+static PyObject *
+_inPCPDJKkDz(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_get_manifest((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_manifest_by_name(char const *manifest_name);
+ */
+static PyObject *
+_inPCPDJZz9N(PyObject *, PyObject *args) {
+  char *param0;
+  if (PyArg_ParseTuple(args, "s", &param0)) {
+    int return_value = interrogate_get_manifest_by_name((char const *)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_manifest_name(int manifest);
+ */
+static PyObject *
+_inPCPDJKqIx(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_manifest_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_manifest_definition(int manifest);
+ */
+static PyObject *
+_inPCPDJ_uSj(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_manifest_definition((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_manifest_has_type(int manifest);
+ */
+static PyObject *
+_inPCPDJsBN6(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_manifest_has_type((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_manifest_get_type(int manifest);
+ */
+static PyObject *
+_inPCPDJc8Lg(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_manifest_get_type((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_manifest_has_getter(int manifest);
+ */
+static PyObject *
+_inPCPDJ3MkE(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_manifest_has_getter((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_manifest_getter(int manifest);
+ */
+static PyObject *
+_inPCPDJsk9F(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_manifest_getter((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_manifest_has_int_value(int manifest);
+ */
+static PyObject *
+_inPCPDJC9u_(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_manifest_has_int_value((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_manifest_get_int_value(int manifest);
+ */
+static PyObject *
+_inPCPDJS_tk(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_manifest_get_int_value((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_element_name(int element);
+ */
+static PyObject *
+_inPCPDJ_U2J(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_element_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_element_scoped_name(int element);
+ */
+static PyObject *
+_inPCPDJZ4Us(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_element_scoped_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_element_by_name(char const *element_name);
+ */
+static PyObject *
+_inPCPDJd695(PyObject *, PyObject *args) {
+  char *param0;
+  if (PyArg_ParseTuple(args, "s", &param0)) {
+    int return_value = interrogate_get_element_by_name((char const *)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_element_by_scoped_name(char const *element_name);
+ */
+static PyObject *
+_inPCPDJeISc(PyObject *, PyObject *args) {
+  char *param0;
+  if (PyArg_ParseTuple(args, "s", &param0)) {
+    int return_value = interrogate_get_element_by_scoped_name((char const *)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_element_type(int element);
+ */
+static PyObject *
+_inPCPDJpHUf(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_element_type((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_element_has_getter(int element);
+ */
+static PyObject *
+_inPCPDJk5ao(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_element_has_getter((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_element_getter(int element);
+ */
+static PyObject *
+_inPCPDJV4dk(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_element_getter((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_element_has_setter(int element);
+ */
+static PyObject *
+_inPCPDJQApo(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_element_has_setter((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_element_setter(int element);
+ */
+static PyObject *
+_inPCPDJV_Io(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_element_setter((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_number_of_globals();
+ */
+static PyObject *
+_inPCPDJNQAC(PyObject *, PyObject *args) {
+  if (PyArg_ParseTuple(args, "")) {
+    int return_value = interrogate_number_of_globals();
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_global(int n);
+ */
+static PyObject *
+_inPCPDJAfO2(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_get_global((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_number_of_global_functions();
+ */
+static PyObject *
+_inPCPDJV5jm(PyObject *, PyObject *args) {
+  if (PyArg_ParseTuple(args, "")) {
+    int return_value = interrogate_number_of_global_functions();
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_global_function(int n);
+ */
+static PyObject *
+_inPCPDJwsjw(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_get_global_function((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_number_of_functions();
+ */
+static PyObject *
+_inPCPDJZjcX(PyObject *, PyObject *args) {
+  if (PyArg_ParseTuple(args, "")) {
+    int return_value = interrogate_number_of_functions();
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_function(int n);
+ */
+static PyObject *
+_inPCPDJR_w6(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_get_function((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_function_name(int function);
+ */
+static PyObject *
+_inPCPDJw6ns(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_function_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_function_scoped_name(int function);
+ */
+static PyObject *
+_inPCPDJGX78(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_function_scoped_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_function_has_comment(int type);
+ */
+static PyObject *
+_inPCPDJ_iVJ(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_function_has_comment((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_function_comment(int type);
+ */
+static PyObject *
+_inPCPDJg3TW(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_function_comment((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_function_prototype(int type);
+ */
+static PyObject *
+_inPCPDJi9Wj(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_function_prototype((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_function_is_method(int function);
+ */
+static PyObject *
+_inPCPDJG2QW(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_function_is_method((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_function_class(int function);
+ */
+static PyObject *
+_inPCPDJIZTX(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_function_class((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_function_has_module_name(int function);
+ */
+static PyObject *
+_inPCPDJu8Rq(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_function_has_module_name((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_function_module_name(int function);
+ */
+static PyObject *
+_inPCPDJ9_el(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_function_module_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_function_is_virtual(int function);
+ */
+static PyObject *
+_inPCPDJaus9(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_function_is_virtual((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_function_number_of_c_wrappers(int function);
+ */
+static PyObject *
+_inPCPDJaf25(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_function_number_of_c_wrappers((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_function_c_wrapper(int function, int n);
+ */
+static PyObject *
+_inPCPDJnPrB(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_function_c_wrapper((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_function_number_of_python_wrappers(int function);
+ */
+static PyObject *
+_inPCPDJDmkY(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_function_number_of_python_wrappers((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_function_python_wrapper(int function, int n);
+ */
+static PyObject *
+_inPCPDJKL_W(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_function_python_wrapper((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_wrapper_name(int wrapper);
+ */
+static PyObject *
+_inPCPDJtc9G(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_wrapper_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_wrapper_is_callable_by_name(int wrapper);
+ */
+static PyObject *
+_inPCPDJa0Pp(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_wrapper_is_callable_by_name((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_wrapper_has_return_value(int wrapper);
+ */
+static PyObject *
+_inPCPDJ9GJl(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_wrapper_has_return_value((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_wrapper_return_type(int wrapper);
+ */
+static PyObject *
+_inPCPDJKfmo(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_wrapper_return_type((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_wrapper_caller_manages_return_value(int wrapper);
+ */
+static PyObject *
+_inPCPDJPhA0(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_wrapper_caller_manages_return_value((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_wrapper_return_value_destructor(int wrapper);
+ */
+static PyObject *
+_inPCPDJVMJl(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_wrapper_return_value_destructor((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_wrapper_number_of_parameters(int wrapper);
+ */
+static PyObject *
+_inPCPDJ6ACv(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_wrapper_number_of_parameters((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_wrapper_parameter_type(int wrapper, int n);
+ */
+static PyObject *
+_inPCPDJNJX7(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_wrapper_parameter_type((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_wrapper_parameter_has_name(int wrapper, int n);
+ */
+static PyObject *
+_inPCPDJI3Xf(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    bool return_value = interrogate_wrapper_parameter_has_name((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_wrapper_parameter_name(int wrapper, int n);
+ */
+static PyObject *
+_inPCPDJWOel(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    char const *return_value = interrogate_wrapper_parameter_name((int)param0, (int)param1);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_wrapper_parameter_is_this(int wrapper, int n);
+ */
+static PyObject *
+_inPCPDJWvbH(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    bool return_value = interrogate_wrapper_parameter_is_this((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_wrapper_has_pointer(int wrapper);
+ */
+static PyObject *
+_inPCPDJ6JG0(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_wrapper_has_pointer((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_wrapper_unique_name(int wrapper);
+ */
+static PyObject *
+_inPCPDJauwR(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_wrapper_unique_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_wrapper_by_unique_name(char const *unique_name);
+ */
+static PyObject *
+_inPCPDJ5OfF(PyObject *, PyObject *args) {
+  char *param0;
+  if (PyArg_ParseTuple(args, "s", &param0)) {
+    int return_value = interrogate_get_wrapper_by_unique_name((char const *)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_number_of_global_types();
+ */
+static PyObject *
+_inPCPDJlLys(PyObject *, PyObject *args) {
+  if (PyArg_ParseTuple(args, "")) {
+    int return_value = interrogate_number_of_global_types();
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_global_type(int n);
+ */
+static PyObject *
+_inPCPDJFt0z(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_get_global_type((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_number_of_types();
+ */
+static PyObject *
+_inPCPDJbw3v(PyObject *, PyObject *args) {
+  if (PyArg_ParseTuple(args, "")) {
+    int return_value = interrogate_number_of_types();
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_type(int n);
+ */
+static PyObject *
+_inPCPDJxpx8(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_get_type((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_type_by_name(char const *type_name);
+ */
+static PyObject *
+_inPCPDJGhcs(PyObject *, PyObject *args) {
+  char *param0;
+  if (PyArg_ParseTuple(args, "s", &param0)) {
+    int return_value = interrogate_get_type_by_name((char const *)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_type_by_scoped_name(char const *type_name);
+ */
+static PyObject *
+_inPCPDJjhrb(PyObject *, PyObject *args) {
+  char *param0;
+  if (PyArg_ParseTuple(args, "s", &param0)) {
+    int return_value = interrogate_get_type_by_scoped_name((char const *)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_get_type_by_true_name(char const *type_name);
+ */
+static PyObject *
+_inPCPDJToqq(PyObject *, PyObject *args) {
+  char *param0;
+  if (PyArg_ParseTuple(args, "s", &param0)) {
+    int return_value = interrogate_get_type_by_true_name((char const *)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_type_name(int type);
+ */
+static PyObject *
+_inPCPDJoIf5(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_type_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_type_scoped_name(int type);
+ */
+static PyObject *
+_inPCPDJ6Xo_(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_type_scoped_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_type_true_name(int type);
+ */
+static PyObject *
+_inPCPDJ8eET(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_type_true_name((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_nested(int type);
+ */
+static PyObject *
+_inPCPDJNMOE(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_nested((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_outer_class(int type);
+ */
+static PyObject *
+_inPCPDJidlm(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_outer_class((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_has_comment(int type);
+ */
+static PyObject *
+_inPCPDJ5FdF(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_has_comment((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_type_comment(int type);
+ */
+static PyObject *
+_inPCPDJR9bU(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    char const *return_value = interrogate_type_comment((int)param0);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_atomic(int type);
+ */
+static PyObject *
+_inPCPDJqZbO(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_atomic((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * AtomicToken interrogate_type_atomic_token(int type);
+ */
+static PyObject *
+_inPCPDJiCgZ(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    AtomicToken return_value = interrogate_type_atomic_token((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_unsigned(int type);
+ */
+static PyObject *
+_inPCPDJvj9C(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_unsigned((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_signed(int type);
+ */
+static PyObject *
+_inPCPDJ5Tjz(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_signed((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_long(int type);
+ */
+static PyObject *
+_inPCPDJTV9E(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_long((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_longlong(int type);
+ */
+static PyObject *
+_inPCPDJPd3W(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_longlong((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_short(int type);
+ */
+static PyObject *
+_inPCPDJRIvd(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_short((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_wrapped(int type);
+ */
+static PyObject *
+_inPCPDJeAKS(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_wrapped((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_pointer(int type);
+ */
+static PyObject *
+_inPCPDJE_rr(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_pointer((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_const(int type);
+ */
+static PyObject *
+_inPCPDJpZxy(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_const((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_wrapped_type(int type);
+ */
+static PyObject *
+_inPCPDJZ__l(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_wrapped_type((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_enum(int type);
+ */
+static PyObject *
+_inPCPDJQDIY(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_enum((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_number_of_enum_values(int type);
+ */
+static PyObject *
+_inPCPDJA7Ig(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_number_of_enum_values((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_type_enum_value_name(int type, int n);
+ */
+static PyObject *
+_inPCPDJY50T(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    char const *return_value = interrogate_type_enum_value_name((int)param0, (int)param1);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * char const *interrogate_type_enum_value_scoped_name(int type, int n);
+ */
+static PyObject *
+_inPCPDJypPX(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    char const *return_value = interrogate_type_enum_value_scoped_name((int)param0, (int)param1);
+    return Py_BuildValue("s", return_value);
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_enum_value(int type, int n);
+ */
+static PyObject *
+_inPCPDJIKx5(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_type_enum_value((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_struct(int type);
+ */
+static PyObject *
+_inPCPDJI_e3(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_struct((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_class(int type);
+ */
+static PyObject *
+_inPCPDJCAx3(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_class((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_union(int type);
+ */
+static PyObject *
+_inPCPDJKOMc(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_union((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_fully_defined(int type);
+ */
+static PyObject *
+_inPCPDJVUhE(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_fully_defined((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_is_unpublished(int type);
+ */
+static PyObject *
+_inPCPDJu8T0(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_is_unpublished((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_number_of_constructors(int type);
+ */
+static PyObject *
+_inPCPDJsPNn(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_number_of_constructors((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_get_constructor(int type, int n);
+ */
+static PyObject *
+_inPCPDJP_f2(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_type_get_constructor((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_has_destructor(int type);
+ */
+static PyObject *
+_inPCPDJuE9q(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_has_destructor((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_destructor_is_inherited(int type);
+ */
+static PyObject *
+_inPCPDJh1o6(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    bool return_value = interrogate_type_destructor_is_inherited((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_get_destructor(int type);
+ */
+static PyObject *
+_inPCPDJc4vK(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_get_destructor((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_number_of_elements(int type);
+ */
+static PyObject *
+_inPCPDJXbpM(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_number_of_elements((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_get_element(int type, int n);
+ */
+static PyObject *
+_inPCPDJYAfN(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_type_get_element((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_number_of_methods(int type);
+ */
+static PyObject *
+_inPCPDJDbCl(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_number_of_methods((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_get_method(int type, int n);
+ */
+static PyObject *
+_inPCPDJ2R7K(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_type_get_method((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_number_of_casts(int type);
+ */
+static PyObject *
+_inPCPDJg6iq(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_number_of_casts((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_get_cast(int type, int n);
+ */
+static PyObject *
+_inPCPDJNxR0(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_type_get_cast((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_number_of_derivations(int type);
+ */
+static PyObject *
+_inPCPDJ8n7D(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_number_of_derivations((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_get_derivation(int type, int n);
+ */
+static PyObject *
+_inPCPDJazFz(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_type_get_derivation((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_derivation_has_upcast(int type, int n);
+ */
+static PyObject *
+_inPCPDJgkPe(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    bool return_value = interrogate_type_derivation_has_upcast((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_get_upcast(int type, int n);
+ */
+static PyObject *
+_inPCPDJIRmS(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_type_get_upcast((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_derivation_downcast_is_impossible(int type, int n);
+ */
+static PyObject *
+_inPCPDJN_Lp(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    bool return_value = interrogate_type_derivation_downcast_is_impossible((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * bool interrogate_type_derivation_has_downcast(int type, int n);
+ */
+static PyObject *
+_inPCPDJ2xei(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    bool return_value = interrogate_type_derivation_has_downcast((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_get_downcast(int type, int n);
+ */
+static PyObject *
+_inPCPDJTgkE(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_type_get_downcast((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_number_of_nested_types(int type);
+ */
+static PyObject *
+_inPCPDJh4_l(PyObject *, PyObject *args) {
+  int param0;
+  if (PyArg_ParseTuple(args, "i", &param0)) {
+    int return_value = interrogate_type_number_of_nested_types((int)param0);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+/*
+ * Python wrapper for
+ * int interrogate_type_get_nested_type(int type, int n);
+ */
+static PyObject *
+_inPCPDJnedH(PyObject *, PyObject *args) {
+  int param0;
+  int param1;
+  if (PyArg_ParseTuple(args, "ii", &param0, &param1)) {
+    int return_value = interrogate_type_get_nested_type((int)param0, (int)param1);
+    return Py_BuildValue("i", (int)(return_value));
+  }
+  return (PyObject *)NULL;
+}
+
+}  /* close extern "C" */
+
+static PyMethodDef python_methods[] = {
+  { "interrogate_type_get_method", &_inPCPDJ2R7K, METH_VARARGS },
+  { "interrogate_type_derivation_has_downcast", &_inPCPDJ2xei, METH_VARARGS },
+  { "interrogate_manifest_has_getter", &_inPCPDJ3MkE, METH_VARARGS },
+  { "interrogate_type_has_comment", &_inPCPDJ5FdF, METH_VARARGS },
+  { "interrogate_get_wrapper_by_unique_name", &_inPCPDJ5OfF, METH_VARARGS },
+  { "interrogate_type_is_signed", &_inPCPDJ5Tjz, METH_VARARGS },
+  { "interrogate_wrapper_number_of_parameters", &_inPCPDJ6ACv, METH_VARARGS },
+  { "interrogate_wrapper_has_pointer", &_inPCPDJ6JG0, METH_VARARGS },
+  { "interrogate_type_scoped_name", &_inPCPDJ6Xo_, METH_VARARGS },
+  { "interrogate_type_true_name", &_inPCPDJ8eET, METH_VARARGS },
+  { "interrogate_type_number_of_derivations", &_inPCPDJ8n7D, METH_VARARGS },
+  { "interrogate_wrapper_has_return_value", &_inPCPDJ9GJl, METH_VARARGS },
+  { "interrogate_function_module_name", &_inPCPDJ9_el, METH_VARARGS },
+  { "interrogate_type_number_of_enum_values", &_inPCPDJA7Ig, METH_VARARGS },
+  { "interrogate_get_global", &_inPCPDJAfO2, METH_VARARGS },
+  { "interrogate_manifest_has_int_value", &_inPCPDJC9u_, METH_VARARGS },
+  { "interrogate_type_is_class", &_inPCPDJCAx3, METH_VARARGS },
+  { "interrogate_type_number_of_methods", &_inPCPDJDbCl, METH_VARARGS },
+  { "interrogate_function_number_of_python_wrappers", &_inPCPDJDmkY, METH_VARARGS },
+  { "interrogate_type_is_pointer", &_inPCPDJE_rr, METH_VARARGS },
+  { "interrogate_get_global_type", &_inPCPDJFt0z, METH_VARARGS },
+  { "interrogate_function_is_method", &_inPCPDJG2QW, METH_VARARGS },
+  { "interrogate_function_scoped_name", &_inPCPDJGX78, METH_VARARGS },
+  { "interrogate_get_type_by_name", &_inPCPDJGhcs, METH_VARARGS },
+  { "interrogate_wrapper_parameter_has_name", &_inPCPDJI3Xf, METH_VARARGS },
+  { "interrogate_type_enum_value", &_inPCPDJIKx5, METH_VARARGS },
+  { "interrogate_type_get_upcast", &_inPCPDJIRmS, METH_VARARGS },
+  { "interrogate_function_class", &_inPCPDJIZTX, METH_VARARGS },
+  { "interrogate_type_is_struct", &_inPCPDJI_e3, METH_VARARGS },
+  { "interrogate_function_python_wrapper", &_inPCPDJKL_W, METH_VARARGS },
+  { "interrogate_type_is_union", &_inPCPDJKOMc, METH_VARARGS },
+  { "interrogate_wrapper_return_type", &_inPCPDJKfmo, METH_VARARGS },
+  { "interrogate_get_manifest", &_inPCPDJKkDz, METH_VARARGS },
+  { "interrogate_manifest_name", &_inPCPDJKqIx, METH_VARARGS },
+  { "interrogate_wrapper_parameter_type", &_inPCPDJNJX7, METH_VARARGS },
+  { "interrogate_type_is_nested", &_inPCPDJNMOE, METH_VARARGS },
+  { "interrogate_number_of_globals", &_inPCPDJNQAC, METH_VARARGS },
+  { "interrogate_type_derivation_downcast_is_impossible", &_inPCPDJN_Lp, METH_VARARGS },
+  { "interrogate_type_get_cast", &_inPCPDJNxR0, METH_VARARGS },
+  { "interrogate_type_get_constructor", &_inPCPDJP_f2, METH_VARARGS },
+  { "interrogate_type_is_longlong", &_inPCPDJPd3W, METH_VARARGS },
+  { "interrogate_wrapper_caller_manages_return_value", &_inPCPDJPhA0, METH_VARARGS },
+  { "interrogate_element_has_setter", &_inPCPDJQApo, METH_VARARGS },
+  { "interrogate_type_is_enum", &_inPCPDJQDIY, METH_VARARGS },
+  { "interrogate_type_comment", &_inPCPDJR9bU, METH_VARARGS },
+  { "interrogate_type_is_short", &_inPCPDJRIvd, METH_VARARGS },
+  { "interrogate_get_function", &_inPCPDJR_w6, METH_VARARGS },
+  { "interrogate_manifest_get_int_value", &_inPCPDJS_tk, METH_VARARGS },
+  { "interrogate_type_is_long", &_inPCPDJTV9E, METH_VARARGS },
+  { "interrogate_type_get_downcast", &_inPCPDJTgkE, METH_VARARGS },
+  { "interrogate_get_type_by_true_name", &_inPCPDJToqq, METH_VARARGS },
+  { "interrogate_element_getter", &_inPCPDJV4dk, METH_VARARGS },
+  { "interrogate_number_of_global_functions", &_inPCPDJV5jm, METH_VARARGS },
+  { "interrogate_wrapper_return_value_destructor", &_inPCPDJVMJl, METH_VARARGS },
+  { "interrogate_type_is_fully_defined", &_inPCPDJVUhE, METH_VARARGS },
+  { "interrogate_element_setter", &_inPCPDJV_Io, METH_VARARGS },
+  { "interrogate_wrapper_parameter_name", &_inPCPDJWOel, METH_VARARGS },
+  { "interrogate_wrapper_parameter_is_this", &_inPCPDJWvbH, METH_VARARGS },
+  { "interrogate_type_number_of_elements", &_inPCPDJXbpM, METH_VARARGS },
+  { "interrogate_type_enum_value_name", &_inPCPDJY50T, METH_VARARGS },
+  { "interrogate_type_get_element", &_inPCPDJYAfN, METH_VARARGS },
+  { "interrogate_element_scoped_name", &_inPCPDJZ4Us, METH_VARARGS },
+  { "interrogate_type_wrapped_type", &_inPCPDJZ__l, METH_VARARGS },
+  { "interrogate_number_of_functions", &_inPCPDJZjcX, METH_VARARGS },
+  { "interrogate_get_manifest_by_name", &_inPCPDJZz9N, METH_VARARGS },
+  { "interrogate_element_name", &_inPCPDJ_U2J, METH_VARARGS },
+  { "interrogate_function_has_comment", &_inPCPDJ_iVJ, METH_VARARGS },
+  { "interrogate_manifest_definition", &_inPCPDJ_uSj, METH_VARARGS },
+  { "interrogate_wrapper_is_callable_by_name", &_inPCPDJa0Pp, METH_VARARGS },
+  { "interrogate_function_number_of_c_wrappers", &_inPCPDJaf25, METH_VARARGS },
+  { "interrogate_function_is_virtual", &_inPCPDJaus9, METH_VARARGS },
+  { "interrogate_wrapper_unique_name", &_inPCPDJauwR, METH_VARARGS },
+  { "interrogate_type_get_derivation", &_inPCPDJazFz, METH_VARARGS },
+  { "interrogate_number_of_types", &_inPCPDJbw3v, METH_VARARGS },
+  { "interrogate_type_get_destructor", &_inPCPDJc4vK, METH_VARARGS },
+  { "interrogate_manifest_get_type", &_inPCPDJc8Lg, METH_VARARGS },
+  { "interrogate_get_element_by_name", &_inPCPDJd695, METH_VARARGS },
+  { "interrogate_type_is_wrapped", &_inPCPDJeAKS, METH_VARARGS },
+  { "interrogate_get_element_by_scoped_name", &_inPCPDJeISc, METH_VARARGS },
+  { "interrogate_function_comment", &_inPCPDJg3TW, METH_VARARGS },
+  { "interrogate_type_number_of_casts", &_inPCPDJg6iq, METH_VARARGS },
+  { "interrogate_type_derivation_has_upcast", &_inPCPDJgkPe, METH_VARARGS },
+  { "interrogate_type_destructor_is_inherited", &_inPCPDJh1o6, METH_VARARGS },
+  { "interrogate_type_number_of_nested_types", &_inPCPDJh4_l, METH_VARARGS },
+  { "interrogate_function_prototype", &_inPCPDJi9Wj, METH_VARARGS },
+  { "interrogate_type_atomic_token", &_inPCPDJiCgZ, METH_VARARGS },
+  { "interrogate_type_outer_class", &_inPCPDJidlm, METH_VARARGS },
+  { "interrogate_get_type_by_scoped_name", &_inPCPDJjhrb, METH_VARARGS },
+  { "interrogate_element_has_getter", &_inPCPDJk5ao, METH_VARARGS },
+  { "interrogate_number_of_global_types", &_inPCPDJlLys, METH_VARARGS },
+  { "interrogate_function_c_wrapper", &_inPCPDJnPrB, METH_VARARGS },
+  { "interrogate_type_get_nested_type", &_inPCPDJnedH, METH_VARARGS },
+  { "interrogate_type_name", &_inPCPDJoIf5, METH_VARARGS },
+  { "interrogate_element_type", &_inPCPDJpHUf, METH_VARARGS },
+  { "interrogate_type_is_const", &_inPCPDJpZxy, METH_VARARGS },
+  { "interrogate_type_is_atomic", &_inPCPDJqZbO, METH_VARARGS },
+  { "interrogate_manifest_has_type", &_inPCPDJsBN6, METH_VARARGS },
+  { "interrogate_type_number_of_constructors", &_inPCPDJsPNn, METH_VARARGS },
+  { "interrogate_manifest_getter", &_inPCPDJsk9F, METH_VARARGS },
+  { "interrogate_wrapper_name", &_inPCPDJtc9G, METH_VARARGS },
+  { "interrogate_function_has_module_name", &_inPCPDJu8Rq, METH_VARARGS },
+  { "interrogate_type_is_unpublished", &_inPCPDJu8T0, METH_VARARGS },
+  { "interrogate_type_has_destructor", &_inPCPDJuE9q, METH_VARARGS },
+  { "interrogate_type_is_unsigned", &_inPCPDJvj9C, METH_VARARGS },
+  { "interrogate_function_name", &_inPCPDJw6ns, METH_VARARGS },
+  { "interrogate_number_of_manifests", &_inPCPDJwgip, METH_VARARGS },
+  { "interrogate_get_global_function", &_inPCPDJwsjw, METH_VARARGS },
+  { "interrogate_get_type", &_inPCPDJxpx8, METH_VARARGS },
+  { "interrogate_type_enum_value_scoped_name", &_inPCPDJypPX, METH_VARARGS },
+  { NULL, NULL }
+};
+
+#ifdef _WIN32
+extern "C" __declspec(dllexport) void initlibdtool();
+#else
+extern "C" void initlibdtool();
+#endif
+
+void initlibdtool() {
+  Py_InitModule("libdtool", python_methods);
+}
+

+ 4 - 0
dtool/src/Sources.pp

@@ -0,0 +1,4 @@
+// This is a group directory: a directory level above a number of
+// source subdirectories.
+
+#define DIR_TYPE group

+ 13 - 0
dtool/src/attach/Sources.pp

@@ -0,0 +1,13 @@
+#define INSTALL_HEADERS \
+    ctattch.pl ctattch.pl.rnd ctunattach.pl ctquery.pl ctdelta.pl \
+    ctdelta.pl.rnd unco.pl ctvspec.pl ctcm.pl ctccase.pl ctntool.pl \
+    ctcvs.pl
+
+#define INSTALL_SCRIPTS \
+    ctattach.drv ctunattach.drv ctquery ctdelta ctihave ctallihave \
+    ctunco ctattachcc cttimewarp get-cttree update-cttree get-delta \
+    ctsanity ctmkelem ctmkdir ctci ctco ctrm ctmv ctmake neartool
+
+#define INSTALL_DATA \
+    dtool.cshrc dtool.init dtool.emacs dtool.alias \
+    dtool.sh dtool.alias-sh

+ 33 - 0
dtool/src/attach/ctallihave

@@ -0,0 +1,33 @@
+#!/usr/local/bin/perl
+
+if ($#ARGV != -1) {
+   exit print "Usage: ctihave\n" ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "not configured for using CTtools\n" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$projs = $ENV{"CTPROJS"} ;
+@projsplit = split( / +/, $projs ) ;
+
+foreach $item ( @projsplit ) {
+    @items = split( /:/, $item ) ;
+    $thisproj = $items[0] ;
+    $thisflav = $items[1] ;
+    $thisspec = &CTResolveSpec( $thisproj, $thisflav ) ;
+    $result = $result . &CTCMIHave( $thisproj, $thisflav, $thisspec ) ;
+}
+if ( $result ne "" ) {
+    @splitlist = split( /\n/, $result ) ;
+    foreach $item ( @splitlist ) {
+	print $item . "\n" ;
+    }
+}

+ 149 - 0
dtool/src/attach/ctattach.drv

@@ -0,0 +1,149 @@
+#!/usr/local/bin/perl
+
+# acceptable forms:
+#   ctattach                     - give usage message
+#   ctattach project             - attach to the personal flavor of the project
+#   ctattach project flavor      - attach to a specific flavor of the project
+#   ctattach -                   - list projects that can be attached to
+#   ctattach project -           - list flavors of a given project
+#   ctattach - flavor            - list projects with a certain flavor
+#   ctattach -def project flavor - attach to project, setting CTDEFAULT_FLAV
+#                                  to flavor for the scope of this attach
+
+sub CTAttachUsage {
+   print STDERR "Usage: ctattach -def project flavor  -or-\n" ;
+   print STDERR "       ctattach project [flavor]     -or-\n" ;
+   print STDERR "       ctattach project -            -or-\n" ;
+   print STDERR "       ctattach - [flavor]\n" ;
+   &CTAttachWriteNullScript( $tmpname ) ;
+   print $tmpname . "\n" ;
+   exit;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+    die "$DTOOL environment must be set to use CTtools\n" ;
+}
+
+require "$tool/inc/ctattch.pl" ;
+
+$tmpname = "/tmp/script.$$" ;
+
+if ( $#ARGV == -1 ) {
+    &CTUDebug( "got no arguments\n" ) ;
+    &CTAttachUsage ;
+}
+
+$idx = 0 ;
+$proj = "" ;
+$flav = "" ;
+$noflav = 0 ;
+$defflav = "" ;
+$spread = 0 ;
+$anydef = 0 ;
+
+#
+# parse arguemnts
+#
+
+if ( $ARGV[$idx] eq "-def" ) {
+   &CTUDebug( "got '-def' parameter\n" ) ;
+   if ( $#ARGV < ($idx + 2) ) {
+       &CTUDebug( "not enough arguments after -def\n" ) ;
+       &CTAttachUsage ;
+   }
+   $defflav = $ARGV[$idx+2] ;
+   $spread = 1;
+   &CTUDebug( "spread default flavor is '$defflav'\n" ) ;
+   $idx++ ;
+} else {
+   if ( $ENV{"CTDEFAULT_FLAV"} ne "" ) {
+      $defflav = $ENV{"CTDEFAULT_FLAV"} ;
+      &CTUDebug( "environment default flavor is '$defflav'\n" ) ;
+   }
+}
+
+$proj = $ARGV[$idx] ;
+&CTUDebug( "project is '$proj'\n" ) ;
+
+if ( $defflav eq "" ) {
+   $defflav = "default" ;
+   &CTUDebug( "no environmental default, using 'default'\n" ) ;
+}
+
+if ( $#ARGV > $idx ) {
+   $flav = $ARGV[$idx+1] ;
+   &CTUDebug( "provided flavor is '$flav'\n" ) ;
+} else {
+   if ( $proj ne "-" ) {
+      $flav = $defflav;
+      &CTUDebug( "using environment default flavor '$flav'\n" ) ;
+      $noflav = 1 ;
+   }
+}
+
+if (( $noflav == 1 ) || ( $flav eq "default" )) {
+   $anydef = 1 ;
+}
+
+#
+# act on the arguments we got
+#
+
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+
+if (( $proj eq "-" ) || ( $flav eq "-" )) {
+   if ( $#ARGV == 0 ) {
+      # list projects that can be attached to
+      print STDERR "Projects that can be attached to:\n" ;
+      $_ = &CTListAllProjects ;
+      @projlist = split ;
+      foreach $item ( @projlist ) {
+	 print STDERR "   $item\n" ;
+      }
+   } elsif ( $proj eq "-" ) {
+      # list project that have a given flavor
+      print STDERR "Projects that have a '$flav' flavor:\n" ;
+      $_ = &CTListAllProjects ;
+      @projlist = split ;
+      foreach $item ( @projlist ) {
+	 $tmp = &CTResolveSpec( $item, $flav ) ;
+	 if ( $tmp ne "" ) {
+	    print STDERR "   $item\n" ;
+	 }
+      }
+   } else {
+      # list flavors of a given project
+      print STDERR "Flavors of project '$proj':\n" ;
+      $_ = &CTListAllFlavors( $proj ) ;
+      @flavlist = split ;
+      foreach $item ( @flavlist ) {
+	 print STDERR "   $item\n" ;
+      }
+   }
+   &CTAttachWriteNullScript( $tmpname ) ;
+   print $tmpname . "\n" ;
+} else {
+   # output a real attachment
+   $curflav = &CTQueryProj( $proj ) ;
+   if (( $curflav eq "" ) || ( $noflav == 0 )) {
+      $envsep{"PATH"} = ":" ;
+      $envsep{"LD_LIBRARY_PATH"} = ":" ;
+      $envsep{"PFPATH"} = ":" ;
+      $envsep{"SSPATH"} = ":" ;
+      $envsep{"STKPATH"} = ":" ;
+      $envsep{"DC_PATH"} = ":" ;
+      $spec = &CTAttachCompute( $proj, $flav, $anydef ) ;
+      if ( $spec eq "" ) {
+	 &CTAttachWriteNullScript( $tmpname ) ;
+	 print $tmpname . "\n" ;
+      } else {
+	 &CTAttachWriteScript( $tmpname ) ;
+	 print $tmpname . "\n" ;
+      }
+   } else {
+      &CTAttachWriteNullScript( $tmpname ) ;
+      print $tmpname . "\n" ;
+   }
+}

+ 86 - 0
dtool/src/attach/ctattachcc

@@ -0,0 +1,86 @@
+#!/usr/local/bin/perl
+
+if ( $#ARGV != 5 ) {
+   print STDERR "This is for internal use by attach ONLY\n" ;
+   exit ;
+}
+
+$root = $ARGV[0] ;
+$view = $ARGV[1] ;
+$branch = $ARGV[2] ;
+$label = $ARGV[3] ;
+$vobname = $ARGV[4] ;
+$proj = $ARGV[5] ;
+$tmpname = "/tmp/config.$$" ;
+
+$emitted = 0 ;
+
+$ctdebug = $ENV{"CTATTACH_DEBUG"} ;
+
+if ($ctdebug) {
+   print STDERR "Params:\n  0: '$root'\n  1: '$view'\n  2: '$branch'\n" ;
+   print STDERR "  3: '$label'\n  4: '$vobname'\n  5: '$proj'\n" ;
+   print STDERR "making branch and label types for view " . $view . "\n" ;
+   print STDERR "executing: /usr/atria/bin/cleartool mkbrtype -vob /vobs/$vobname -c \"Branch type for the $view view\" $branch 2> /dev/null > /dev/null\n" ;
+   print STDERR "executing: /usr/atria/bin/cleartool mklbtype -vob /vobs/$vobname -c \"Label type for the $view view\" $label 2> /dev/null > /dev/null\n" ;
+}
+system "/usr/atria/bin/cleartool mkbrtype -vob /vobs/$vobname -c \"Branch type for the $view view\" $branch 2> /dev/null > /dev/null\n" ;
+system "/usr/atria/bin/cleartool mklbtype -vob /vobs/$vobname -c \"Label type for the $view view\" $label 2> /dev/null > /dev/null\n" ;
+
+if ($ctdebug) {
+   print STDERR "creating/updating the config-spec for view " . $view . "\n" ;
+}
+open( CTINTERFACE, "/usr/atria/bin/cleartool catcs -tag $view |" ) ;
+open( TMPFILE, "> $tmpname" ) ;
+while ( <CTINTERFACE> ) {
+   if ( $_ =~ "CHECKEDOUT" ) {
+      if ($ctdebug) {
+	 print STDERR "case 1:\noutputting: '$_'\n" ;
+      }
+      print TMPFILE "$_" ;
+   } elsif (( $_ =~ /^element \*/ ) && ( $_ =~ "/main/LATEST" ) &&
+	    !( $_ =~ /\/$proj\// )) {
+      if ( ! $emitted ) {
+	 $emitted = 1 ;
+	 print TMPFILE "element $root/... .../$branch/LATEST\n" ;
+	 print TMPFILE "element $root/... $label -mkbranch $branch\n" ;
+	 print TMPFILE "element $root/... /main/LATEST -mkbranch $branch\n" ;
+	 if ($ctdebug) {
+	    print STDERR "case 2:\n" ;
+	    print STDERR "outputting: 'element $root/... .../$branch/LATEST'\n" ;
+	    print STDERR "outputting: 'element $root/... $label -mkbranch $branch'\n" ;
+	    print STDERR "outputting: 'element $root/... /main/LATEST -mkbranch $branch'\n" ;
+	 }
+      }
+      if ($ctdebug) {
+	 print STDERR "case 3:\n" ;
+	 print STDERR "outputting: '$_'\n" ;
+      }
+      print TMPFILE "$_" ;
+   } elsif ( $_ =~ /\/$proj\// ) {
+      if ( ! $emitted ) {
+	 $emitted = 1 ;
+	 print TMPFILE "element $root/... .../$branch/LATEST\n" ;
+	 print TMPFILE "element $root/... $label -mkbranch $branch\n" ;
+	 print TMPFILE "element $root/... /main/LATEST -mkbranch $branch\n" ;
+	 if ($ctdebug) {
+	    print STDERR "case 4:\n" ;
+	    print STDERR "outputting: 'element $root/... .../$branch/LATEST'\n" ;
+	    print STDERR "outputting: 'element $root/... $label -mkbranch $branch'\n" ;
+	    print STDERR "outputting: 'element $root/... /main/LATEST -mkbranch $branch'\n" ;
+	 }
+      }
+   } else {
+      if ($ctdebug) {
+	 print STDERR "case 5:\n" ;
+	 print STDERR "outputting: '$_'\n" ;
+      }
+      print TMPFILE "$_" ;
+   }
+}
+close( CTINTERFACE ) ;
+close( TMPFILE ) ;
+if ($ctdebug) {
+   print STDERR "output to execute: '/usr/atria/bin/cleartool setcs -tag $view $tmpname ; rm $tmpname'\n" ;
+}
+system "/usr/atria/bin/cleartool setcs -tag $view $tmpname ; rm $tmpname\n" ;

+ 474 - 0
dtool/src/attach/ctattch.pl

@@ -0,0 +1,474 @@
+require "$tool/inc/ctutils.pl" ;
+
+$shell_type = "csh" ;
+if ( $ENV{"SHELL_TYPE"} ne "" ) {
+    if ( $ENV{"SHELL_TYPE"} eq "sh" ) {
+	$shell_type = "sh" ;
+    }
+}
+
+$docnt = 0 ;
+@attachqueue = () ;
+
+require "$tool/inc/ctquery.pl" ;
+
+# force set a variable in the 'new' environment
+# input is in:
+# $_[0] = variable
+# $_[1] = value
+#
+# output is in:
+# %newenv = variable marked to be set to value
+sub CTAttachSet {
+    if ( ( $_[0] ne "" ) && ( $_[1] ne "" ) ) {
+	&CTUDebug( "setting " . $_[0] . " to '" . $_[1] . "'\n" ) ;
+	$newenv{$_[0]} = $_[1] ;
+    }
+}
+
+# get a variable from the environment and split it out to unified format
+# (ie: space separated)
+# input is in:
+# $_[0] = variable to get
+#
+# output is in:
+# string returned with value
+sub CTSpoolEnv {
+    local( $ret ) = $ENV{$_[0]} ;
+    if ( $envsep{$_[0]} ne "" ) {
+	local( @splitlist ) = split( $envsep{$_[0]}, $ret );
+	$ret = join( " ", @splitlist ) ;
+    }
+    $ret ;
+}
+
+# modify a possibly existing variable to have a value in the 'new' environment
+# input is in:
+# $_[0] = variable
+# $_[1] = value
+# $_[2] = root
+# $_[3] = project
+#
+# output is in:
+# %newenv = variable adjusted to have the new value
+sub CTAttachMod {
+    &CTUDebug( "in CTAttachMod\n" ) ;
+    if ( $_[0] eq "CTPROJS" ) {
+	# as part of the system, this one is special
+	&CTUDebug( "doing a mod on $CTPROJS\n" ) ;
+	if ( $newenv{$_[0]} eq "" ) {
+	    $newenv{$_[0]} = $ENV{$_[0]} ;
+	}
+	local( $proj ) = $_[3] ;
+	$proj =~ tr/A-Z/a-z/ ;
+	local( $curflav ) = &CTQueryProj( $proj ) ;
+	if ( $curflav ne "" ) {
+	    local( $tmp ) = $_[3] . ":" . $curflav ;
+	    if ( $newenv{$_[0]} =~ /$tmp/ ) {
+		local( $hold ) = $newenv{$_[0]} ;
+		$hold =~ s/$tmp/$_[1]/ ;
+		&CTUDebug( "already attached to " . $_[3] . " changing '" .
+			   $tmp . "' to '" . $_[1] . "' yielding '" . $hold .
+			   "'\n" ) ;
+		$newenv{$_[0]} = $hold ;
+	    } else {
+		&CTUDebug( "prepending '" . $_[1] . "' to CTPROJS\n" ) ;
+		$newenv{$_[0]} = $_[1] . " " . $newenv{$_[0]} ;
+	    }
+	} else {
+	    &CTUDebug( "writing '" . $_[1] . "' to CTPROJS\n" ) ;
+	    if ( $newenv{$_[0]} eq "" ) {
+		$newenv{$_[0]} = $_[1] ;
+	    } else {
+		$newenv{$_[0]} = $_[1] . " " . $newenv{$_[0]} ;
+	    }
+	}
+    } elsif ( ( $_[0] ne "" ) && ( $_[1] ne "" ) ) {
+	local( $dosimple ) = 0 ;
+	if ( $newenv{$_[0]} eq "" ) {
+	    # not in our 'new' environment yet, add it.
+	    # may still be empty
+	    $newenv{$_[0]} = &CTSpoolEnv( $_[0] ) ;
+	}
+	if ( ! ( $newenv{$_[0]} =~ /$_[1]/ )) {
+	    # if it's in there already, we're done before we started.
+	    if ( $_[1] =~ /^$_[2]/ ) {
+		# damn, might need to do an in-place edit
+		local( $curroot ) = $ENV{$_[3]} ;
+		if ( $curroot eq "" ) {
+		    $dosimple = 1 ;
+		} else {
+		    local( $test ) = $_[1] ;
+		    $test =~ s/^$_[2]// ;
+		    $test = $curroot . $test ;
+		    if ( $newenv{$_[0]} =~ /$test/ ) {
+			# there it is.  in-place edit
+			local( $foo ) = $newenv{$_[0]} ;
+			$foo =~ s/$test/$_[1]/ ;
+			&CTUDebug( "doing in-place edit on " . $_[0] .
+				   " changing '" . $test . "' to '" .
+				   $_[1] . "' yielding '" . $foo . "'\n" ) ;
+			$newenv{$_[0]} = $foo ;
+		    } else {
+			$dosimple = 1 ;
+		    }
+		}
+	    } else {
+		# don't have to sweat in-place edits
+		$dosimple = 1 ;
+	    }
+	}
+	if ( $dosimple ) {
+	    if ( $newenv{$_[0]} eq "" ) {
+		&CTUDebug( "no pre-existing value in " . $_[0] .
+			   " setting it to '" . $_[1] . "'\n" ) ;
+		$newenv{$_[0]} = $_[1] ;
+	    } elsif ( $envpostpend{$_[0]} ) {
+		&CTUDebug( "post-pending '" . $_[1] . "' to " . $_[0] .
+			   "\n" ) ;
+		$newenv{$_[0]} = $newenv{$_[0]} . " " . $_[1] ;
+	    } else {
+		&CTUDebug( "pre-pending '" . $_[1] . "' to " . $_[0] .
+			   "\n" ) ;
+		$newenv{$_[0]} = $_[1] . " " . $newenv{$_[0]} ;
+	    }
+	}
+    }
+}
+
+require "$tool/inc/ctcm.pl" ;
+
+# given the project and flavor, build the lists of variables to set/modify
+# input is in:
+# $_[0] = project
+# $_[1] = flavor
+# $_[2] = is some kind of default?
+#
+# output is in:
+# return value is config line
+# %newenv      = an image of those parts of the environment we want to change
+# %envsep      = seperator
+# %envcmd      = set or setenv
+# %envdo       = direct commands to add to attach script
+# %envpostpend = flag that variable should be postpended
+sub CTAttachCompute {
+   &CTUDebug( "in CTAttachCompute\n" ) ;
+   local( $done ) = 0 ;
+   local( $flav ) = $_[1] ;
+   local( $prevflav ) = &CTQueryProj( $_[0] ) ;
+   local( $spec ) ;
+   local( $root ) ;
+   if ( $_[2] && ( $prevflav ne "" )) {
+      # want some form of default attachment, and are already attached.  Short
+      # circuit.
+      $done = 1 ;
+   }
+
+   #
+   # choose real flavor and find/validate root
+   #
+   while ( ! $done ) {
+      $spec = &CTResolveSpec( $_[0], $flav ) ;
+      &CTUDebug( "spec line = '$spec'\n" ) ;
+      if ( $spec ne "" ) {
+	 $root = &CTComputeRoot( $_[0], $flav, $spec ) ;
+	 &CTCMSetup( $_[0], $spec, $flav ) ;
+	 if ( -e $root ) {
+	    $done = 1 ;
+	 }
+      }
+      if (( ! $done ) && $_[2] ) {
+	 if ( $flav eq "install" ) {
+	    # oh my! are we ever in trouble
+	    # want some sort of default, but couldn't get to what we wanted
+	    print STDERR "you are in a strange alien universe\n" ;
+	    $spec = "" ;
+	    $done = 1 ;
+	 } elsif ( $flav eq "release" ) {
+	    $flav = "install" ;
+	 } elsif ( $flav eq "ship" ) {
+	    $flav = "release" ;
+	 } else {
+	    $flav = "ship" ;
+	 }
+      }
+   }
+
+   #
+   # start real work
+   #
+   if ( $spec ne "" ) {
+      local( $proj ) = $_[0] ;
+      $proj =~ tr/a-z/A-Z/ ;
+      local( $item ) ;
+
+      # we scan the .init file first because if there are needed sub-attaches
+      # they must happen before the rest of our work
+      local( $init ) = "$root/etc/$_[0].init" ;
+      local( %localmod );
+      local( %localset );
+      local( %localsep );
+      local( %localcmd );
+      local( %localdo );
+      local( $localdocnt ) = 0 ;
+      local( %localpost );
+      if ( -e $init ) {
+	  &CTUDebug( "scanning " . $_[0] . ".init\n" ) ;
+	  local( @linesplit ) ;
+	  local( $linetmp ) ;
+	  local( $loop ) ;
+	  local( $looptmp ) ;
+	  local( *INITFILE ) ;
+	  if ( -x $init ) {
+	      open( INITFILE, "$init $_[0] $_[1] $root |" ) ;
+	  } else {
+	      open( INITFILE, "< $init" ) ;
+	  }
+	  while ( <INITFILE> ) {
+	      s/\n$// ;
+	      @linesplit = split( /\#/ ) ;
+	      $_ = $linesplit[0] ;
+	      if ( $_ =~ /^MODABS/ ) {
+		  @linesplit = split ;
+		  $linetmp = $linesplit[1] ;
+		  shift( @linesplit ) ;
+		  shift( @linesplit ) ;
+		  if ( $localmod{$linetmp} eq "" ) {
+		      $localmod{$linetmp} = join( " ", @linesplit ) ;
+		  } else {
+		      $localmod{$linetmp} = $localmod{$linetmp} . " " .
+			  join( " ", @linesplit ) ;
+		  }
+	      } elsif ( $_ =~ /^MODREL/ ) {
+		  @linesplit = split ;
+		  $linetmp = $linesplit[1] ;
+		  shift( @linesplit ) ;
+		  shift( @linesplit ) ;
+		  foreach $loop ( @linesplit ) {
+		      $looptmp = $root . "/" . &CTUShellEval($loop) ;
+		      if ( -e $looptmp ) {
+			  if ( $localmod{$linetmp} eq "" ) {
+			      $localmod{$linetmp} = $looptmp ;
+			  } else {
+			      $localmod{$linetmp} = $localmod{$linetmp} . " " .
+				  $looptmp ;
+			  }
+		      }
+		  }
+	      } elsif ( $_ =~ /^SETABS/ ) {
+		  @linesplit = split ;
+		  $linetmp = $linesplit[1] ;
+		  shift( @linesplit ) ;
+		  shift( @linesplit ) ;
+		  if ( $localset{$linetmp} eq "" ) {
+		      $localset{$linetmp} = join( " ", @linesplit ) ;
+		  } else {
+		      $localset{$linetmp} = $localset{$linetmp} . " " .
+			  join( " ", @linesplit ) ;
+		  }
+	      } elsif ( $_ =~ /^SETREL/ ) {
+		  @linesplit = split ;
+		  $linetmp = $linesplit[1] ;
+		  shift( @linesplit ) ;
+		  shift( @linesplit ) ;
+		  foreach $loop ( @linesplit ) {
+		      $looptmp = $root . "/" . &CTUShellEval($loop) ;
+		      if ( -e $looptmp ) {
+			  if ( $localset{$linetmp} eq "" ) {
+			      $localset{$linetmp} = $looptmp ;
+			  } else {
+			      $localset{$linetmp} = $localset{$linetmp} . " " .
+				  $looptmp ;
+			  }
+		      }
+		  }
+	      } elsif ( $_ =~ /^SEP/ ) {
+		  @linesplit = split ;
+		  $localsep{$linesplit[1]} = $linesplit[2] ;
+	      } elsif ( $_ =~ /^CMD/ ) {
+		  @linesplit = split ;
+		  $localcmd{$linesplit[1]} = $linesplit[2] ;
+	      } elsif ( $_ =~ /^DOCSH/ ) {
+		  if ( $shell_type ne "sh" ) {
+		      @linesplit = split ;
+		      shift( @linesplit ) ;
+		      $localdo{$localdocnt} = join( " ", @linesplit ) ;
+		      $localdocnt++ ;
+		  }
+	      } elsif ( $_ =~ /^DOSH/ ) {
+		  if ( $shell_type eq "sh" ) {
+		      @linesplit = split ;
+		      shift( @linesplit ) ;
+		      $localdo{$localdocnt} = join( " ", @linesplit ) ;
+		      $localdocnt++ ;
+		  }
+	      } elsif ( $_ =~ /^DO/ ) {
+		  @linesplit = split ;
+		  shift( @linesplit ) ;
+		  $localdo{$localdocnt} = join( " ", @linesplit ) ;
+		  $localdocnt++ ;
+	      } elsif ( $_ =~ /^POSTPEND/ ) {
+		  @linesplit = split ;
+		  $localpost{$linesplit[1]} = 1 ;
+	      } elsif ( $_ =~ /^ATTACH/ ) {
+		  @linesplit = split ;
+		  shift( @linesplit ) ;
+		  foreach $loop ( @linesplit ) {
+		      push( @attachqueue, $loop ) ;
+		  }
+	      } elsif ( $_ ne "" ) {
+		  print STDERR "Unknown .init directive '$_'\n" ;
+	      }
+	  }
+	  close( INITFILE ) ;
+      }
+
+      # now handle sub-attaches
+      &CTUDebug( "performing sub-attaches\n" ) ;
+      while ( @attachqueue != () ) {
+	  $item = shift( @attachqueue ) ;
+	  &CTUDebug( "attaching to " . $item . "\n" ) ;
+	  &CTAttachCompute( $item, $defflav, 1 ) ;
+      }
+
+      # now we will do our extentions, then apply the mods from the .init
+      # file, if any
+      &CTUDebug( "extending paths\n" ) ;
+      local( $type ) = &CTSpecType( $spec ) ;
+      if ( $type eq "vroot" ) {
+	  &CTAttachMod( "PATH", "/usr/atria/bin", $root, $proj ) ;
+      }
+
+      # For now, we will not check whether the various /bin, /lib,
+      # /inc directories exist before adding them to the paths.  This
+      # helps when attaching to unitialized trees that do not have
+      # these directories yet (but will shortly).
+
+      $item = $root . "/bin" ;
+      #if ( -e $item ) {
+	  &CTAttachMod( "PATH", $item, $root, $proj ) ;
+      #}
+      $item = $root . "/lib" ;
+      #if ( -e $item ) {
+	  if ( $ENV{"PENV"} eq "WIN32" ) {
+	      &CTAttachMod( "PATH", $item, $root, $proj ) ;
+	  }
+	  &CTAttachMod( "LD_LIBRARY_PATH", $item, $root, $proj ) ;
+      #}
+      $item = $root . "/src" ;
+      #if ( -e $item ) {
+	  &CTAttachMod( "CDPATH", $item, $root, $proj ) ;
+      #}
+      $item = $root . "/inc" ;
+      #if ( -e $item ) {
+	  &CTAttachMod( "CT_INCLUDE_PATH", $item, $root, $proj ) ;
+      #}
+      $item = $root . "/etc" ;
+      #if ( -e $item ) {
+	  &CTAttachMod( "ETC_PATH", $item, $root, $proj ) ;
+      #}
+      &CTAttachMod( "CTPROJS", $proj . ":" . $flav, $root, $proj ) ;
+      &CTAttachSet( $proj, $root ) ;
+
+      # run thru the stuff saved up from the .init file
+      foreach $item ( keys %localsep ) {
+	  $envsep{$item} = $localsep{$item} ;
+      }
+      foreach $item ( keys %localpost ) {
+	  $envpostpend{$item} = $localpost{$item} ;
+      }
+      foreach $item ( keys %localmod ) {
+	  local( @splitthis ) = split( / +/, $localmod{$item} ) ;
+	  local( $thing ) ;
+	  foreach $thing ( @splitthis ) {
+	      &CTAttachMod( $item, $thing, $root, $proj ) ;
+	  }
+      }
+      foreach $item ( keys %localset ) {
+	  &CTAttachSet( $item, $localset{$item} ) ;
+      }
+      foreach $item ( keys %localcmd ) {
+	  $envcmd{$item} = $localcmd{$item} ;
+      }
+      foreach $item ( keys %localdo ) {
+	  $envdo{$docnt} = $localdo{$item} ;
+	  $docnt++ ;
+      }
+   }
+
+   &CTUDebug( "out of CTAttachCompute\n" ) ;
+   $spec ;
+}
+
+# write a script to NOT change the environment
+# Input is:
+# $_[0] = filename
+sub CTAttachWriteNullScript {
+   &CTUDebug( "in CTAttachWriteNullScript\n" ) ;
+   local( *OUTFILE ) ;
+   open( OUTFILE, ">$_[0]" ) ;
+   print OUTFILE "#!/bin/" . $shell_type . " -f\n" ;
+   print OUTFILE "echo No attachment actions performed\n" ;
+   print OUTFILE "rm -f $_[0]\n" ;
+   close( OUTFILE ) ;
+   &CTUDebug( "out of CTAtachWriteNullScript\n" ) ;
+}
+
+# write a script to setup the environment
+# Input is:
+# $_[0] = filename
+sub CTAttachWriteScript {
+   &CTUDebug( "in CTAttachWriteScript\n" ) ;
+   local( *OUTFILE ) ;
+   open( OUTFILE, ">$_[0]" ) ;
+   print OUTFILE "#!/bin/" . $shell_type . " -f\n" ;
+   local( $item ) ;
+
+   foreach $item ( keys %newenv ) {
+       local( $sep ) = " " ;
+       if ( $envsep{$item} ne "" ) {
+	   $sep = $envsep{$item} ;
+       }
+       local( @splitlist ) = split( / +/, $newenv{$item} ) ;
+       local( $outval ) = join( $sep, @splitlist ) ;
+
+       if ( $shell_type eq "sh" ) {
+	   print OUTFILE "$item=\"" . $outval . "\"\n" ;
+	   if ( $envcmd{$item} ne "set" ) {
+	       print OUTFILE "export $item\n" ;
+	   }
+       } else {
+	   if ( $envcmd{$item} ne "" ) {
+	       print OUTFILE $envcmd{$item} . " $item " ;
+	       if ( $envcmd{$item} eq "set" ) {
+		   print OUTFILE "= ( " ;
+	       }
+	       print OUTFILE $outval ;
+	       if ( $envcmd{$item} eq "set" ) {
+		   print OUTFILE ")" ;
+	       }
+	       print OUTFILE "\n" ;
+	   } else {
+	       print OUTFILE "setenv $item \"$outval\"\n" ;
+	   }
+       }
+   }
+
+   if ( $newenv{"CDPATH"} ne "" ) {
+       if ( $shell_type ne "sh" ) {
+	   print OUTFILE "set cdpath = ( \$" . "CDPATH )\n" ;
+       }
+   }
+   foreach $item ( keys %envdo ) {
+      print OUTFILE $envdo{$item} . "\n" ;
+   }
+   if (! $ctdebug) {
+      print OUTFILE "rm -f $_[0]\n" ;
+   } else {
+      print STDERR "no self-destruct script '" . $_[0] . "'\n" ;
+   }
+   close( OUTFILE ) ;
+   &CTUDebug( "out of CTAttachWriteScript\n" ) ;
+}
+
+1;

+ 953 - 0
dtool/src/attach/ctattch.pl.rnd

@@ -0,0 +1,953 @@
+require "$tool/inc/ctutils.pl" ;
+
+# get list of all projects
+sub CTAttachListProj {
+   if ($ctdebug ne "") {
+      print STDERR "in CTAttachListProj\n" ;
+   }
+   local( $ret ) = "" ;
+   local( $done ) = 0 ;
+   local( *DIRFILES ) ;
+   open( DIRFILES, "(cd /var/etc ; /bin/ls -1 *.vspec ; echo blahblah) |" ) ;
+   while ( ! $done ) {
+      $_ = <DIRFILES> ;
+      s/\n$// ;
+      if ( $_ eq "blahblah" ) {
+	 $done = 1 ;
+      } else {
+	 s/.vspec$// ;
+	 $ret = $ret . " " . $_ ;
+      }
+   }
+   close( DIRFILES ) ;
+   if ($ctdebug ne "") {
+      print STDERR "out of CTAttachListProj\n" ;
+   }
+   $ret ;
+}
+
+# get list of flavors for a project
+# $_[0] = project
+sub CTAttachListFlav {
+   if ($ctdebug) {
+      print STDERR "in CTAttachListFlav\n" ;
+   }
+   local( $ret ) = "" ;
+   $vobname = $_[0] ;
+   if ( -e "/var/etc/$_[0].vspec" ) {
+      local( *SPECFILE ) ;
+      open( SPECFILE, "</var/etc/$_[0].vspec" ) ;
+      local( @partlist ) ;
+      while ( <SPECFILE> ) {
+	 if ( $_ =~ /^VOBNAME/ ) {
+	    @partlist = split( /=/ ) ;
+	    $vobname = $partlist[1] ;
+	    $vobname =~ s/\n$// ;
+	 } else {
+	    @partlist = split( /:/ ) ;
+	    $ret = $ret . " " . $partlist[0] ;
+	 }
+      }
+      close( SPECFILE ) ;
+   } else {
+      print STDERR "CTAttachListFlav: cannot locate '/var/etc/$_[0]'\n" ;
+   }
+   if ($ctdebug) {
+      print STDERR "out of CTAttachListFlav\n" ;
+   }
+   $ret ;
+}
+
+# get the flavor line for the given project
+# $_[0] = project
+# $_[1] = flavor
+sub CTAttachFindFlav {
+   if ($ctdebug) {
+      print STDERR "in CTAttachFindFlav\n" ;
+   }
+   local( $ret ) = "" ;
+   $vobname = $_[0] ;
+   if ( -e "/var/etc/$_[0].vspec" ) {
+      local( *SPECFILE ) ;
+      open( SPECFILE, "</var/etc/$_[0].vspec" ) ;
+      local( $done ) = 0 ;
+      local( @partlist ) ;
+      while (( $_ = <SPECFILE> ) && ! $done ) {
+	 s/\n$// ;
+	 if ( $_ =~ /^VOBNAME/ ) {
+	    @partlist = split( /=/ ) ;
+	    $vobname = $partlist[1] ;
+	 } else {
+	    @partlist = split( /:/ ) ;
+	    if ( $partlist[0] eq $_[1] ) {
+	       $done = 1 ;
+	       $ret = join( " ", @partlist );
+	    }
+	 }
+      }
+      close( SPECFILE ) ;
+   } else {
+      print STDERR "CTAttachFindFlav: cannot locate '/var/etc/$_[0]'\n" ;
+   }
+   if ($ctdebug) {
+      if ($ret ne "") {
+	 print STDERR "found flavor " . $_[1] . " of project " . $_[0] . "\n" ;
+      } else {
+	 print STDERR "did not find flavor " . $_[1] . " of project " . $_[0] . "\n" ;
+      }
+      print STDERR "out of CTAttachFindFlav\n" ;
+   }
+   $ret ;
+}
+
+# given the project and flavor, resolve the final config line
+# $_[0] = project
+# $_[1] = flavor
+sub CTAttachResolve {
+   if ($ctdebug) {
+      print STDERR "in CTAttachResolve\n" ;
+   }
+   local( $spec ) = &CTAttachFindFlav( $_[0], $_[1] ) ;
+   local( $ret ) = "" ;
+   if ( $spec ne "" ) {
+      local( @speclist ) ;
+      @speclist = split( / +/, $spec ) ;
+      if ( $speclist[1] eq "root" ) {
+	 $ret = join( " " , @speclist ) ;
+	 if ($ctdebug) {
+	    print STDERR "resolved to a 'root'\n" ;
+	 }
+      } elsif  ( $speclist[1] eq "vroot" ) {
+	 if ( $ENV{"HAVE_ATRIA"} ne "" ) {
+	    $ret = join( " " , @speclist ) ;
+	    if ($ctdebug) {
+	       print STDERR "resolved to a 'vroot'\n" ;
+	    }
+	 }
+      } elsif ( $speclist[1] eq "ref" ) {
+	 local( $tmp ) = &CTUShellEval( $speclist[2] ) ;
+	 if ($ctdebug) {
+	    print STDERR "resolved to a 'ref', recursing\n" ;
+	 }
+	 $ret = &CTAttachResolve( $_[0], $tmp ) ;
+      } else {
+	 print STDERR "CTAttachResolve: unknown flavor type '$speclist[1]'\n" ;
+      }
+   }
+   if ($ctdebug) {
+      print STDERR "out of CTAttachResolve\n" ;
+   }
+   $ret ;
+}
+
+# given the config line, determine the view name
+# $_[0] = config line
+sub CTAttachComputeView {
+   if ($ctdebug) {
+      print STDERR "in CTAttachComputeView\n" ;
+   }
+   local( $ret ) = "" ;
+   if ( $_[0] ne "" ) {
+      local( @speclist ) ;
+      @speclist = split( / +/, $_[0] ) ;
+      if ( $speclist[1] eq "vroot" ) {
+	 local( $vname ) = $speclist[0] ;
+	 shift( @speclist ) ;
+	 shift( @speclist ) ;
+	 local( $item ) ;
+	 local( @itemlist ) ;
+	 foreach $item ( @speclist ) {
+	    @itemlist = split( /=/, $item ) ;
+	    if ( $itemlist[0] eq "VN" ) {
+	       $vname = $itemlist[1] ;
+	    }
+	 }
+	 $ret = &CTUShellEval( $vname ) ;
+      }
+   }
+   if ($ctdebug) {
+      print STDERR "config line '" . $_[0] . "' yields view name '" . $ret . "'\n" ;
+      print STDERR "out of CTAttachComputeView\n" ;
+   }
+   $ret ;
+}
+
+# given the config line, determine the branch name
+# $_[0] = config line
+sub CTAttachComputeBranch {
+   if ($ctdebug) {
+      print STDERR "in CTAttachComputeBranch\n" ;
+   }
+   local( $ret ) = "" ;
+   if ( $_[0] ne "" ) {
+      local( @speclist ) ;
+      @speclist = split( / +/, $_[0] ) ;
+      if ( $speclist[1] eq "vroot" ) {
+	 local( $bname ) = &CTAttachComputeView( $_[0] ) ;
+	 shift( @speclist ) ;
+	 shift( @speclist ) ;
+	 local( $item ) ;
+	 local( @itemlist ) ;
+	 foreach $item ( @speclist ) {
+	    @itemlist = split( /=/, $item ) ;
+	    if ( $itemlist[0] eq "BN" ) {
+	       $bname = $itemlist[1] ;
+	    }
+	 }
+	 $ret = &CTUShellEval( $bname ) ;
+      }
+   }
+   if ($ctdebug) {
+      print STDERR "config line '" . $_[0] . "' yields branch name '" . $ret . "'\n" ;
+      print STDERR "out of CTAttachComputeBranch\n" ;
+   }
+   $ret ;
+}
+
+# given the config line, determine the label name
+# $_[0] = config line
+sub CTAttachComputeLabel {
+   if ($ctdebug) {
+      print STDERR "in CTAttachComputeLabel\n" ;
+   }
+   local( $ret ) = "" ;
+   if ( $_[0] ne "" ) {
+      local( @speclist ) ;
+      @speclist = split( / +/, $_[0] ) ;
+      if ( $speclist[1] eq "vroot" ) {
+	 local( $lname ) = &CTAttachComputeView( $_[0] ) ;
+	 shift( @speclist ) ;
+	 shift( @speclist ) ;
+	 local( $item ) ;
+	 local( @itemlist ) ;
+	 foreach $item ( @speclist ) {
+	    @itemlist = split( /=/, $item ) ;
+	    if ( $itemlist[0] eq "LB" ) {
+	       $lname = $itemlist[1] ;
+	    }
+	 }
+	 $ret = &CTUShellEval( $lname ) ;
+	 $ret =~ tr/a-z/A-Z/ ;
+      }
+   }
+   if ($ctdebug) {
+      print STDERR "config line '" . $_[0] . "' yields label name '" . $ret . "'\n" ;
+      print STDERR "out of CTAttachComputeLabel\n" ;
+   }
+   $ret ;
+}
+
+# given the project name and config line, determine the root of the project
+# $_[0] = project
+# $_[1] = config line
+sub CTAttachComputeRoot {
+   if ($ctdebug) {
+      print STDERR "in CTAttachComputeRoot\n" ;
+   }
+   local( $ret ) = "" ;
+   if ( $_[1] ne "" ) {
+      local( @speclist ) ;
+      @speclist = split( / +/, $_[1] ) ;
+      if ( $speclist[1] eq "root" ) {
+	 $ret = $speclist[2] ;
+      } elsif ( $speclist[1] eq "vroot" ) {
+	 $ret = &CTAttachComputeView( $_[1] ) ;
+	 $ret = "/view/$ret/vobs/$vobname" ;
+      } else {
+	 print STDERR "CTAttachComputeRoot: unknown flavor type '$speclist[1]'\n" ;
+      }
+   }
+   if ($ctdebug) {
+      print STDERR "out of CTAttachComputeRoot\n" ;
+   }
+   $ret ;
+}
+
+# given the project name and config line, determine the root of the project as
+# needed by the config spec.
+# $_[0] = project
+# $_[1] = config line
+sub CTAttachComputeElemRoot {
+   if ($ctdebug) {
+      print STDERR "in CTAttachComputeElemRoot\n" ;
+   }
+   local( $ret ) = "" ;
+   if ( $_[1] ne "" ) {
+      local( @speclist ) ;
+      @speclist = split( / +/, $_[1] ) ;
+      if ( $speclist[1] eq "root" ) {
+	 $ret = $speclist[2] ;
+      } elsif ( $speclist[1] eq "vroot" ) {
+	 $ret = &CTAttachComputeView( $_[1] ) ;
+	 $ret = "/vobs/$vobname" ;
+      } else {
+	 print STDERR "CTAttachComputeElemRoot: unknown flavor type '$speclist[1]'\n" ;
+      }
+   }
+   if ($ctdebug) {
+      print STDERR "out of CTAttachComputeElemRoot\n" ;
+   }
+   $ret ;
+}
+
+# do whatever setup is needed for ClearCase
+# input is in:
+# $_[0] = project
+# $_[1] = $spec
+sub CTAttachCCSetup {
+   if ($ctdebug) {
+      print STDERR "in CTAttachCCSetup\n" ;
+   }
+   local( $root ) = &CTAttachComputeElemRoot( $_[0], $_[1] ) ;
+   local( $view ) = &CTAttachComputeView( $_[1] ) ;
+   local( $branch ) = &CTAttachComputeBranch( $_[1] ) ;
+   local( $label ) = &CTAttachComputeLabel( $_[1] ) ;
+   local( *CTINTERFACE ) ;
+   local( *TMPFILE ) ;
+   local( $tmpname ) = "/tmp/config.$$" ;
+   local( $emitted ) = 0 ;
+
+   if ($ctdebug) {
+      print STDERR "checking for existance of view '" . $view . "'\n" ;
+   }
+   open( CTINTERFACE, "/usr/atria/bin/cleartool lsview $view |" ) ;
+   $_ = <CTINTERFACE> ;
+   close( CTINTERFACE ) ;
+   if ( $_ eq "" ) {             # need to make the view
+      if ($ctdebug) {
+	 print STDERR "creating view '" . $view . "'\n" ;
+      }
+      system "umask 2 ; /usr/atria/bin/cleartool mkview -tag $view /var/views/$view.vws 2> /dev/null > /dev/null ; /usr/atria/bin/cleartool startview $view 2> /dev/null > /dev/null\n" ;
+   } elsif ( ! ( $_ =~ /\*/ )) { # need to start the view
+      if ($ctdebug) {
+	 print STDERR "starting view '" . $view . "'\n" ;
+      }
+      system "/usr/atria/bin/cleartool startview $view 2> /dev/null > /dev/null &\n" ;
+   }
+
+   if ($ctdebug) {
+      print STDERR "making branch and label types for view " . $view . "\n" ;
+   }
+   system "/usr/atria/bin/cleartool mkbrtype -vob /vobs/$vobname -c \"Branch type for the $view view\" $branch 2> /dev/null > /dev/null &\n" ;
+   system "/usr/atria/bin/cleartool mklbtype -vob /vobs/$vobname -c \"Label type for the $view view\" $label 2> /dev/null > /dev/null &\n" ;
+
+   if ($ctdebug) {
+      print STDERR "creating/updating the config-spec for view " . $view . "\n" ;
+   }
+   open( CTINTERFACE, "/usr/atria/bin/cleartool catcs -tag $view |" ) ;
+   open( TMPFILE, "> $tmpname" ) ;
+   while ( <CTINTERFACE> ) {
+      if ( $_ =~ "CHECKEDOUT" ) {
+	 print TMPFILE "$_" ;
+      } elsif (( $_ =~ /^element \*/ ) && ( $_ =~ "/main/LATEST" ) &&
+	       !( $_ =~ /$_[0]/ )) {
+	 if ( ! $emitted ) {
+	    $emitted = 1 ;
+	    print TMPFILE "element $root/... .../$branch/LATEST\n" ;
+	    print TMPFILE "element $root/... $label -mkbranch $branch\n" ;
+	    print TMPFILE "element $root/... /main/LATEST -mkbranch $branch\n" ;
+	 }
+	 print TMPFILE "$_" ;
+      } elsif ( $_ =~ /$_[0]/ ) {
+	 if ( ! $emitted ) {
+	    $emitted = 1 ;
+	    print TMPFILE "element $root/... .../$branch/LATEST\n" ;
+	    print TMPFILE "element $root/... $label -mkbranch $branch\n" ;
+	    print TMPFILE "element $root/... /main/LATEST -mkbranch $branch\n" ;
+	 }
+      } else {
+	 print TMPFILE "$_" ;
+      }
+   }
+   close( CTINTERFACE ) ;
+   close( TMPFILE ) ;
+   system "/usr/atria/bin/cleartool setcs -tag $view $tmpname ; rm $tmpname &\n" ;
+   if ($ctdebug) {
+      print STDERR "out of CTAttachCCSetup\n" ;
+   }
+}
+
+# do whatever setup is needed for ClearCase, but do it in the background
+# input is in:
+# $_[0] = project
+# $_[1] = $spec
+sub CTAttachCCSetupBG {
+   if ($ctdebug) {
+      print STDERR "in CTAttachCCSetupBG\n" ;
+   }
+   local( $root ) = &CTAttachComputeElemRoot( $_[0], $_[1] ) ;
+   local( $view ) = &CTAttachComputeView( $_[1] ) ;
+   local( $branch ) = &CTAttachComputeBranch( $_[1] ) ;
+   local( $label ) = &CTAttachComputeLabel( $_[1] ) ;
+
+   system "$tool/bin/ctattachcc $root $view $branch $label $vobname $_[0]\n" ;
+
+   if ($ctdebug) {
+      print STDERR "out of CTAttachCCSetupBG\n" ;
+   }
+}
+
+# prepend an entry onto the envmod of the given key.
+# input is in:
+# $_[0] = key
+# $_[1] = data
+#
+# output is in:
+# %envmod = has 'data' prepended at 'key'
+sub CTAttachPrependMod {
+   if ( $envmod{$_[0]} eq "" ) {
+      $envmod{$_[0]} = $_[1] ;
+   } else {
+      $envmod{$_[0]} = $_[1] . " " . $envmod{$_[0]} ;
+   }
+}
+
+# postpend an entry onto the envmod of the given key.
+# input is in:
+# $_[0] = key
+# $_[1] = data
+#
+# output is in:
+# %envmod = has 'data' postpended at 'key'
+sub CTAttachPostpendMod {
+   if ( $envmod{$_[0]} eq "" ) {
+      $envmod{$_[0]} = $_[1] ;
+   } else {
+      $envmod{$_[0]} = $envmod{$_[0]} . " " . $_[1] ;
+   }
+}
+
+# pre/post-pend an entry onto the envmod of the given key, as set/controlled
+# by envpospend, et al.
+# input is in:
+# $_[0] = key
+# $_[1] = data
+#
+# output is in:
+# %envmod = data pre/post pended at the given key
+sub CTAttachAddToMod {
+   if ($envpostpend{$_[0]} ne "") {
+      &CTAttachPostpendMod( $_[0], $_[1] ) ;
+   } else {
+      &CTAttachPrependMod( $_[0], $_[1] ) ;
+   }
+}
+
+# prepend the given entry to the envset of the given key
+# input is in:
+# $_[0] = key
+# $_[1] = data
+#
+# output is in:
+# %envset = prepended at key with data
+sub CTAttachPrependSet {
+   local( $sep ) = " " ;
+   if ( $envsep{$_[0]} ne "" ) {
+      $sep = $envsep{$_[0]} ;
+   }
+   if ($envset{$_[0]} ne "") {
+      $envset{$_[0]} = $_[1] . $sep . $envset{$_[0]} ;
+   } else {
+      $envset{$_[0]} = $_[1] ;
+   }
+}
+
+# postpend the given entry to the envset of the given key
+# input is in:
+# $_[0] = key
+# $_[1] = data
+#
+# output is in:
+# %envset = postpended at key with data
+sub CTAttachPostpendSet {
+   local( $sep ) = " " ;
+   if ( $envsep{$_[0]} ne "" ) {
+      $sep = $envsep{$_[0]} ;
+   }
+   if ($envset{$_[0]} ne "") {
+      $envset{$_[0]} = $envset{$_[0]} . $sep . $_[1] ;
+   } else {
+      $envset{$_[0]} = $_[1] ;
+   }
+}
+
+# pre/post-pend an entry onto the envset of the given key, as set/controlled
+# by envpospend, et al.
+# input is in:
+# $_[0] = key
+# $_[1] = data
+#
+# output is in:
+# %envset = data pre/post pended at the given key
+sub CTAttachAddToSet {
+   if ($envpostpend{$_[0]} ne "") {
+      &CTAttachPostpendSet( $_[0], $_[1] ) ;
+   } else {
+      &CTAttachPrependSet( $_[0], $_[1] ) ;
+   }
+}
+
+$docnt = 0 ;
+@attachqueue = () ;
+
+require "$tool/inc/ctquery.pl" ;
+
+# given the project and flavor, build the lists of variables to set/modify
+# input is in:
+# $_[0] = project
+# $_[1] = flavor
+# $_[2] = is some kind of default?
+#
+# output is in:
+# return value is config line
+# %envmod      = environment variables to modify
+# %envset      = environment variables to outright set
+# %envsep      = seperator
+# %envcmd      = set or setenv
+# %envdo       = direct commands to add to attach script
+# %envpostpend = flag that variable should be postpended
+sub CTAttachCompute {
+   if ($ctdebug) {
+      print STDERR "in CTAttachCompute\n" ;
+   }
+   local( $done ) = 0 ;
+   local( $flav ) = $_[1] ;
+   local( $prevflav ) = &CTQueryProj( $_[0] ) ;
+   local( $spec ) ;
+   local( $root ) ;
+   if ( $_[2] && ( $prevflav ne "" )) {
+      # short circuit attaching, we're already there.
+      $done = 1 ;
+   }
+   while ( ! $done ) {
+      $spec = &CTAttachResolve( $_[0], $flav ) ;
+      if ( $ctdebug ne "" ) {
+	 print STDERR "spec line = '$spec'\n" ;
+      }
+      if ( $spec ne "" ) {
+	 $root = &CTAttachComputeRoot( $_[0], $spec ) ;
+	 if ( -e $root ) {
+	    $done = 1 ;
+	    if ( $spec =~ /vroot/ ) {
+	       &CTAttachCCSetupBG( $_[0], $spec ) ;
+	    }
+	 } elsif ( $spec =~ /vroot/ ) {
+	    &CTAttachCCSetup( $_[0], $spec ) ;
+	    if ( -e $root ) {
+	       $done = 1 ;
+	    }
+	 }
+      }
+      if (( ! $done ) && $_[2] ) {
+	 if ( $flav eq "install" ) {
+	    # oh my! are we ever in trouble
+	    print STDERR "you are in a strange alien universe\n" ;
+	    $spec = "" ;
+	    $done = 1 ;
+	 } elsif ( $flav eq "release" ) {
+	    $flav = "install" ;
+	 } elsif ( $flav eq "ship" ) {
+	    $flav = "release" ;
+	 } else {
+	    $flav = "ship" ;
+	 }
+      }
+   }
+
+   if ( $spec ne "" ) {
+      local( $proj ) = $_[0] ;
+      $proj =~ tr/a-z/A-Z/ ;
+      local( $view ) = &CTAttachComputeView( $spec ) ;
+
+      if ($ctdebug) {
+	 print STDERR "extending paths\n" ;
+      }
+
+      &CTAttachAddToMod( "PATH", $root . "/bin" ) ;
+      &CTAttachAddToMod( "LD_LIBRARY_PATH", $root . "/lib" ) ;
+      &CTAttachAddToMod( "CDPATH", $root . "/src/all" ) ;
+      &CTAttachAddToMod( "CT_INCLUDE_PATH", $root . "/inc" ) ;
+      &CTAttachAddToMod( "DC_PATH", $root . "/etc" ) ;
+      &CTAttachAddToMod( "PFPATH", $root . "/etc/models" ) ;
+      &CTAttachAddToMod( "SSPATH", $root . "/lib/ss" ) ;
+      &CTAttachAddToMod( "STKPATH", $root . "/lib/stk" ) ;
+      &CTAttachAddToMod( "CTPROJS", $proj . ":" . $flav ) ;
+      $envset{$proj} = $root;
+
+#      if ( $view ne "" ) {
+#	 &CTAttachCCSetup( $_[0], $spec ) ;
+#      }
+
+      if ( -e "$root/etc/$_[0].init" ) {
+	 if ($ctdebug) {
+	    print STDERR "scanning .init file\n" ;
+	 }
+	 local( @linesplit ) ;
+	 local( $linetmp ) ;
+	 local( $loop );
+	 local( *INITFILE ) ;
+	 if ( -x "$root/etc/$_[0].init" ) {
+	    open( INITFILE, "$root/etc/$_[0].init $_[0] $_[1] $root |" ) ;
+	 } else {
+	    open( INITFILE, "< $root/etc/$_[0].init" ) ;
+	 }
+	 while ( <INITFILE> ) {
+	    s/\n$// ;
+	    if ( $_ =~ /^MODABS/ ) {
+	       @linesplit = split ;
+	       $linetmp = $linesplit[1] ;
+	       shift( @linesplit ) ;
+	       shift( @linesplit ) ;
+	       &CTAttachPostpendMod( $linetmp, &CTUShellEval(join(" ", @linesplit))) ;
+	    } elsif ( $_ =~ /^MODREL/ ) {
+	       @linesplit = split ;
+	       $linetmp = $linesplit[1] ;
+	       shift( @linesplit ) ;
+	       shift( @linesplit ) ;
+	       foreach $loop ( @linesplit ) {
+		  &CTAttachPostpendMod( $linetmp, $root . "/" . &CTUShellEval($loop)) ;
+	       }
+	    } elsif ( $_ =~ /^SETABS/ ) {
+	       @linesplit = split ;
+	       $linetmp = $linesplit[1] ;
+	       shift( @linesplit ) ;
+	       shift( @linesplit ) ;
+	       &CTAttachPrependSet( $linetmp, &CTUShellEval(join(" ", @linesplit))) ;
+	    } elsif ( $_ =~ /^SETREL/ ) {
+	       @linesplit = split ;
+	       $linetmp = $linesplit[1] ;
+	       shift( @linesplit ) ;
+	       shift( @linesplit ) ;
+	       foreach $loop ( @linesplit ) {
+		   &CTAttachPrependSet( $linetmp, $root . "/" . &CTUShellEval($loop)) ;
+	       }
+	    } elsif ( $_ =~ /^SEP/ ) {
+	       @linesplit = split ;
+	       $envsep{$linesplit[1]} = $linesplit[2] ;
+	    } elsif ( $_ =~ /^CMD/ ) {
+	       @linesplit = split ;
+	       $envcmd{$linesplit[1]} = $linesplit[2] ;
+	    } elsif ( $_ =~ /^DO/ ) {
+	       @linesplit = split ;
+	       shift( @linesplit ) ;
+	       $envdo{$docnt} = join( " ", @linesplit ) ;
+	       $docnt++ ;
+	    } elsif ( $_ =~ /^POSTPEND/ ) {
+	       @linesplit = split ;
+	       $envpospend{$linesplit[1]} = 1 ;
+	    } elsif ( $_ =~ /^ATTACH/ ) {
+	       @linesplit = split ;
+	       shift( @linesplit ) ;
+	       foreach $loop ( @linesplit ) {
+		  push( @attachqueue, $loop ) ;
+	       }
+	    } else {
+	       print STDERR "Unknown .init directive '$_'\n" ;
+	    }
+	 }
+	 close( INITFILE ) ;
+      }
+
+      # save mods away until after sub-attach
+      local( %locmod ) ;
+      local( $item ) ;
+
+      foreach $item ( keys %envmod ) {
+	 $locmod{$item} = $envmod{$item} ;
+	 delete $envmod{$item} ;
+      }
+
+      # do sub-attaches
+      while ( @attachqueue != () ) {
+	 $item = shift( @attachqueue ) ;
+	 &CTAttachCompute( $item, $defflav, 1 ) ;
+      }
+
+      # restore saved mods and merge them in with existing
+      foreach $item ( keys %locmod ) {
+	 $envmod{$item} = $locmod{$item} ;
+	 delete $locmod{$item} ;
+      }
+
+      &CTAttachCheckVars( $_[0], $spec ) ;
+   }
+   if ($ctdebug) {
+      print STDERR "out of CTAttachCompute\n" ;
+   }
+   $spec ;
+}
+
+# take a mod list and merge it into set.  Uniqueifying as we go.
+# input is in:
+# $_[0] = mod list
+# $_[1] = key
+#
+# output is:
+# %envset = now has the mod line merged in with it.
+sub CTAttachMergeToSet {
+   if ( $ctdebug ) {
+      print STDERR "trying to add '$_[0]' to '$envset{$_[1]}'\n" ;
+   }
+   local( @splitlist ) ;
+   local( $loop ) ;
+   local( $sep ) = " " ;
+   if ( $envsep{$_[1]} ne "" ) {
+      $sep = $envsep{$_[1]} ;
+   }
+   @splitlist = split( / /, $_[0] ) ;
+   foreach $loop ( @splitlist ) {
+       if ( ! (( $envset{$_[1]} eq $loop ) ||
+	       ( $envset{$_[1]} =~ /^$loop$sep/ ) ||
+	       ( $envset{$_[1]} =~ /$sep$loop$/ ) ||
+	       ( $envset{$_[1]} =~ /$sep$loop$sep/ ))) {
+	  &CTAttachPostpendSet( $_[1], $loop ) ;
+       }
+   }
+   if ( $ctdebug ) {
+      print STDERR "yielding '$envset{$_[1]}'\n" ;
+   }
+}
+
+# Perform cleanup operations on the variable that are going to be set/modified
+# eg:
+#    * check to see if we're already attached to the project, and alter sets
+#      based on that
+#    * move mods of pre-existing variables to sets w/ the changes included
+#    * move mods of non-existing variables to sets
+#
+# input:
+# $_[0] = project
+# $_[1] = config line
+sub CTAttachCheckVars {
+   if ($ctdebug) {
+      print STDERR "in CTAttachCheckVars\n" ;
+   }
+   local( $prevflav ) = &CTQueryProj( $_[0] ) ;
+   local( $proj ) = $_[0] ;
+   $proj =~ tr/a-z/A-Z/ ;
+   local( $atria ) = "/usr/atria/bin" ;
+   if ( $ENV{"HAVE_ATRIA"} ne "" ) {
+      if ( !( $ENV{"PATH"} =~ /$atria/ )) {
+	 $envmod{"PATH"} = "$atria " . $envmod{"PATH"} ;
+      }
+   }
+   if ( $prevflav ne "" ) {  # are already attached to the project
+      if ( $ctdebug ne "" ) {
+	 print STDERR "am already attached\n" ;
+      }
+      local( $prevspec ) = &CTAttachResolve( $_[0], $prevflav ) ;
+      local( $prevroot ) = &CTAttachComputeRoot( $_[0], $prevspec ) ;
+      local( $root ) = &CTAttachComputeRoot( $_[0], $_[1] ) ;
+      local( $loop ) ;
+      local( $item ) ;
+      local( @splitlist ) ;
+      local( $modsave ) ;
+      foreach $item ( keys %envmod ) {
+	 if ( $ENV{$item} ne "" ) {
+	    if ( $ctdebug ne "" ) {
+	       print STDERR "'$item' is already in the environment\n" ;
+	    }
+	    if ( $item eq "CTPROJS" ) {
+	       local( $prevmark ) = $proj . ":" . $prevflav ;
+	       local( $curmark ) = $envmod{$item} ;
+	       if ( $ctdebug ne "" ) {
+		  print STDERR "changing '$prevmark' to '$curmark' yielding " ;
+	       }
+	       if ( ! $gotenv{$item} ) {
+		  $envset{$item} = $ENV{$item} ;
+	       }
+	       $envset{$item} =~ s/$prevmark/$curmark/ ;
+	       if ( $ctdebug ne "" ) {
+		  print STDERR "'$envset{$item}'\n" ;
+	       }
+	       delete $envmod{$item} ;
+	    } else {
+	       local( $src ) ;
+	       if ( $gotenv{$item} ) {
+		  $src = $envset{$item} ;
+	       } else {
+		  $src = $ENV{$item} ;
+	       }
+	       if ( $envsep{$item} ne "" ) {
+		  @splitlist = split( $envsep{$item}, $src ) ;
+	       } else {
+		  @splitlist = split( / +/, $src ) ;
+	       }
+	       $modsave = $envmod{$item} ;
+	       delete $envmod{$item} ;
+	       foreach $loop ( @splitlist ) {
+		  $loop =~ s/$prevroot/$root/ ;
+		  &CTAttachPostpendMod( $item, $loop ) ;
+	       }
+	       if ( $ctdebug ne "" ) {
+		  print STDERR "env '$src' -> '$envmod{$item}'\n" ;
+	       }
+	       @splitlist = split( / +/, $modsave ) ;
+	       foreach $loop ( @splitlist ) {
+		  if ( ! (( $envmod{$item} eq $loop ) ||
+			  ( $envmod{$item} =~ /^$loop / ) ||
+			  ( $envmod{$item} =~ / $loop$/ ) ||
+			  ( $envmod{$item} =~ / $loop / ))) {
+		     &CTAttachAddToMod( $item, $loop ) ;
+		  }
+	       }
+	       if ( $ctdebug ne "" ) {
+		  print STDERR "env final = '$envmod{$item}'\n" ;
+	       }
+	    }
+	 }
+	 if ( $envmod{$item} ne "" ) {
+	    $envset{$item} = $envmod{$item} ;
+	    if ( $envsep{$item} ne "" ) {
+	       $envset{$item} =~ s/ /$envsep{$item}/g ;
+	    }
+	    # &CTAttachMergeToSet( $envmod{$item}, $item ) ;
+	    delete $envmod{$item} ;
+	    $gotenv{$item} = 1 ;
+	 }
+      }
+   } else { # not already attached.  mods -> sets
+      if ( $ctdebug ne "" ) {
+	 print STDERR "am not already attached\n" ;
+      }
+      local( $item ) ;
+      local( $loop ) ;
+      local( $modsave ) ;
+      local( @splitlist ) ;
+      foreach $item ( keys %envmod ) {
+	 if ( $ENV{$item} ne "" ) {
+	    local( $src ) ;
+	    if ( $gotenv{$item} ) {
+	       $src = $envset{$item} ;
+	    } else {
+	       $src = $ENV{$item} ;
+	    }
+	    if ( $envsep{$item} ne "" ) {
+	       @splitlist = split( $envsep{$item}, $src ) ; 
+	    } else {
+	       @splitlist = split( / +/, $src ) ; 
+	    }
+	    $modsave = $envmod{$item} ;
+	    delete $envmod{$item} ;
+	    foreach $loop ( @splitlist ) {
+	       &CTAttachPostpendMod( $item, $loop ) ;
+	    }
+	    if ( $ctdebug ne "" ) {
+	       print STDERR "env '$src' -> '$envmod{$item}'\n" ;
+	    }
+	    @splitlist = split( / +/, $modsave ) ;
+	    foreach $loop ( @splitlist ) {
+	       if ( ! (( $envmod{$item} eq $loop ) ||
+		       ( $envmod{$item} =~ /^$loop / ) ||
+		       ( $envmod{$item} =~ / $loop$/ ) ||
+		       ( $envmod{$item} =~ / $loop / ))) {
+		  &CTAttachAddToMod( $item, $loop ) ;
+	       }
+	    }
+	    if ( $ctdebug ne "" ) {
+	       print STDERR "env final = '$envmod{$item}'\n" ;
+	    }
+	 }
+	 $envset{$item} = $envmod{$item} ;
+	 if ( $envsep{$item} ne "" ) {
+	    $envset{$item} =~ s/ /$envsep{$item}/g ;
+	 }
+	 # &CTAttachMergeToSet( $envmod{$item}, $item ) ;
+	 delete $envmod{$item} ;
+	 $gotenv{$item} = 1 ;
+      }
+   }
+   if ($ctdebug) {
+      print STDERR "out of CTAttachCheckVars\n" ;
+   }
+}
+
+# write a script to NOT change the environment
+# Input is:
+# $_[0] = filename
+sub CTAttachWriteNullScript {
+   if ($ctdebug) {
+      print STDERR "in CTAttachWriteNullScript\n" ;
+   }
+   local( *OUTFILE ) ;
+   open( OUTFILE, ">$_[0]" ) ;
+   print OUTFILE "#!/bin/csh -f\n" ;
+   print OUTFILE "echo No attachment actions performed\n" ;
+   print OUTFILE "/sbin/rm $_[0]\n" ;
+   close( OUTFILE ) ;
+   if ($ctdebug) {
+      print STDERR "out of CTAtachWriteNullScript\n" ;
+   }
+}
+
+# write a script to setup the environment
+# Input is:
+# $_[0] = filename
+sub CTAttachWriteScript {
+   if ($ctdebug) {
+      print STDERR "in CTAttachWriteScript\n" ;
+   }
+   local( *OUTFILE ) ;
+   open( OUTFILE, ">$_[0]" ) ;
+   print OUTFILE "#!/bin/csh -f\n" ;
+   local( $item ) ;
+   foreach $item ( keys %envset ) {
+      if ( $envcmd{$item} ne "" ) {
+	 print OUTFILE $envcmd{$item} . " $item " ;
+	 if ( $envcmd{$item} eq "set" ) {
+	    print OUTFILE "= " ;
+	 }
+	 print OUTFILE $envset{$item} . "\n" ;
+      } else {
+	 print OUTFILE "setenv $item \"$envset{$item}\"\n" ;
+      }
+   }
+   foreach $item ( keys %envmod ) {
+      print STDERR "SHOULD NOT BE HERE\n" ;
+      if ( $envcmd{$item} ne "" ) {
+	 print OUTFILE $envcmd{$item} . " $item " ;
+	 if ( $envcmd{$item} eq "set" ) {
+	    print OUTFILE "= ( " ;
+	 } else {
+	    print OUTFILE "\"" ;
+	 }
+      } else {
+	 print OUTFILE "setenv $item \"" ;
+      }
+      if ( $envsep{$item} ne "" ) {
+	 @itemlist = split( / +/, $envmod{$item} ) ;
+	 foreach $tmp ( @itemlist ) {
+	    print OUTFILE $tmp . $envsep{$item} ;
+	 }
+      } else {
+	 print OUTFILE $envmod{$item} ;
+      }
+      if ( $envcmd{$item} ne "" ) {
+	 if ( $envcmd{$item} eq "set" ) {
+	    print OUTFILE ")" ;
+	 } else {
+	    print OUTFILE "\"" ;
+	 }
+	 print OUTFILE "\n" ;
+      } else {
+	 print OUTFILE $ENV{$item} . "\"\n" ;
+      }
+   }
+   if (( $envset{"CDPATH"} ne "" ) || ( $envmod{"CDPATH"} ne "" )) {
+      print OUTFILE "set cdpath = ( \$" . "CDPATH )\n" ;
+   }
+   foreach $item ( keys %envdo ) {
+      print OUTFILE $envdo{$item} . "\n" ;
+   }
+   if (! $ctdebug) {
+      print OUTFILE "/sbin/rm $_[0]\n" ;
+   } else {
+      print STDERR "no self-destruct script '" . $_[0] . "'\n" ;
+   }
+   close( OUTFILE ) ;
+   if ($ctdebug) {
+      print STDERR "out of CTAttachWriteScript\n" ;
+   }
+}
+
+1;

+ 439 - 0
dtool/src/attach/ctccase.pl

@@ -0,0 +1,439 @@
+# given the config line, determine the view name
+# $_[0] = config line
+# $_[1] = flavor
+# $_[2] = project
+sub CTAttachComputeView {
+   &CTUDebug( "in CTAttachComputeView\n" ) ;
+   local( $ret ) = &CTResolveSpecName( $_[2], $_[1] ) ;
+   local( $options ) = &CTSpecOptions( $_[0] ) ;
+   if ( $options ne "" ) {
+       local( $name ) = &CTSpecFindOption( $options, "name" ) ;
+       if ( $name ne "" ) {
+	   &CTUDebug( "found a name '" . $name . "'\n" ) ;
+	   $ret = $name ;
+       } else {
+	   &CTUDebug( "no name option found, going with default\n" ) ;
+       }
+   }
+   &CTUDebug( "config line '" . $_[0] . "' yields view name '" . $ret .
+	      "'\n" . "out of CTAttachComputeView\n" ) ;
+   $ret ;
+}
+
+# given the config line, determine the branch name
+# $_[0] = config line
+# $_[1] = flavor
+# $_[2] = project
+sub CTAttachComputeBranch {
+   &CTUDebug( "in CTAttachComputeBranch\n" ) ;
+   local( $ret ) = &CTAttachComputeView( $_[0], $_[1], $_[2] ) ;
+   &CTUDebug( "config line '" . $_[0] . "' yields branch name '" . $ret .
+	      "'\n" . "out of CTAttachComputeBranch\n" ) ;
+   $ret ;
+}
+
+# given the config line, determine the label name
+# $_[0] = config line
+# $_[1] = flavor
+# $_[2] = project
+sub CTAttachComputeLabel {
+   &CTUDebug( "in CTAttachComputeLabel\n" ) ;
+   local( $ret ) = &CTAttachComputeView( $_[0], $_[1], $_[2] ) ;
+   $ret =~ tr/a-z/A-Z/ ;
+   &CTUDebug( "config line '" . $_[0] . "' yields label name '" . $ret .
+	      "'\n" . "out of CTAttachComputeLabel\n" ) ;
+   $ret ;
+}
+
+# given the project name and config line, determine the root of the project as
+# needed by the config spec.
+# $_[0] = project
+# $_[1] = config line
+# $_[2] = flavor
+sub CTAttachComputeElemRoot {
+   &CTUDebug( "in CTAttachComputeElemRoot\n" ) ;
+   local( $ret ) = "/vobs/$_[0]" ;
+   &CTUDebug( "out of CTAttachComputeElemRoot\n" ) ;
+   $ret ;
+}
+
+# do whatever setup is needed for ClearCase
+# input is in:
+# $_[0] = project
+# $_[1] = $spec
+# $_[2] = flavor
+sub CTAttachCCSetup {
+   &CTUDebug( "in CTAttachCCSetup\n" ) ;
+   local( $root ) = &CTAttachComputeElemRoot( $_[0], $_[1], $_[2] ) ;
+   local( $view ) = &CTAttachComputeView( $_[1], $_[2], $_[0] ) ;
+   local( $branch ) = &CTAttachComputeBranch( $_[1], $_[2], $_[0] ) ;
+   local( $label ) = &CTAttachComputeLabel( $_[1], $_[2], $_[0] ) ;
+   local( *CTINTERFACE ) ;
+   local( *TMPFILE ) ;
+   local( $tmpname ) = "/tmp/config.$$" ;
+   local( $emitted ) = 0 ;
+
+   &CTUDebug( "checking for existance of view '" . $view . "'\n" ) ;
+   open( CTINTERFACE, "/usr/atria/bin/cleartool lsview $view |" ) ;
+   $_ = <CTINTERFACE> ;
+   close( CTINTERFACE ) ;
+   if ( $_ eq "" ) {             # need to make the view
+      &CTUDebug( "creating view '" . $view . "'\n" ) ;
+      system "umask 2 ; /usr/atria/bin/cleartool mkview -tag $view /var/views/$view.vws 2> /dev/null > /dev/null ; /usr/atria/bin/cleartool startview $view 2> /dev/null > /dev/null\n" ;
+   } elsif ( ! ( $_ =~ /\*/ )) { # need to start the view
+      &CTUDebug( "starting view '" . $view . "'\n" ) ;
+      system "/usr/atria/bin/cleartool startview $view 2> /dev/null > /dev/null &\n" ;
+   }
+
+   &CTUDebug( "making branch and label types for view " . $view . "\n" ) ;
+   system "/usr/atria/bin/cleartool mkbrtype -vob /vobs/$vobname -c \"Branch type for the $view view\" $branch 2> /dev/null > /dev/null &\n" ;
+   system "/usr/atria/bin/cleartool mklbtype -vob /vobs/$vobname -c \"Label type for the $view view\" $label 2> /dev/null > /dev/null &\n" ;
+
+   &CTUDebug( "creating/updating the config-spec for view " . $view . "\n" ) ;
+   open( CTINTERFACE, "/usr/atria/bin/cleartool catcs -tag $view |" ) ;
+   open( TMPFILE, "> $tmpname" ) ;
+   while ( <CTINTERFACE> ) {
+      if ( $_ =~ "CHECKEDOUT" ) {
+	 print TMPFILE "$_" ;
+      } elsif (( $_ =~ /^element \*/ ) && ( $_ =~ "/main/LATEST" ) &&
+	       !( $_ =~ /$_[0]/ )) {
+	 if ( ! $emitted ) {
+	    $emitted = 1 ;
+	    print TMPFILE "element $root/... .../$branch/LATEST\n" ;
+	    print TMPFILE "element $root/... $label -mkbranch $branch\n" ;
+	    print TMPFILE "element $root/... /main/LATEST -mkbranch $branch\n" ;
+	 }
+	 print TMPFILE "$_" ;
+      } elsif ( $_ =~ /$_[0]/ ) {
+	 if ( ! $emitted ) {
+	    $emitted = 1 ;
+	    print TMPFILE "element $root/... .../$branch/LATEST\n" ;
+	    print TMPFILE "element $root/... $label -mkbranch $branch\n" ;
+	    print TMPFILE "element $root/... /main/LATEST -mkbranch $branch\n" ;
+	 }
+      } else {
+	 print TMPFILE "$_" ;
+      }
+   }
+   close( CTINTERFACE ) ;
+   close( TMPFILE ) ;
+   system "/usr/atria/bin/cleartool setcs -tag $view $tmpname ; rm -f $tmpname &\n" ;
+   &CTUDebug( "out of CTAttachCCSetup\n" ) ;
+}
+
+# do whatever setup is needed for ClearCase, but do it in the background
+# input is in:
+# $_[0] = project
+# $_[1] = $spec
+# $_[2] = flavor
+sub CTAttachCCSetupBG {
+   &CTUDebug( "in CTAttachCCSetupBG\n" ) ;
+   local( $root ) = &CTAttachComputeElemRoot( $_[0], $_[1], $_[2] ) ;
+   local( $view ) = &CTAttachComputeView( $_[1], $_[2], $_[0] ) ;
+   local( $branch ) = &CTAttachComputeBranch( $_[1], $_[2], $_[0] ) ;
+   local( $label ) = &CTAttachComputeLabel( $_[1], $_[2], $_[0] ) ;
+
+   system "$tool/bin/ctattachcc $root $view $branch $label $vobname $_[0]\n" ;
+
+   &CTUDebug( "out of CTAttachCCSetupBG\n" ) ;
+}
+
+# given a possibly empty string, format it into a comment or -nc
+# input is in:
+# $_[0] = possible comment string
+#
+# output is:
+# string for use by ClearCase functions
+sub CTCcaseFormatComment {
+    local( $ret ) = "" ;
+    if ( $_[0] eq "" ) {
+	$ret = "-nc" ;
+    } else {
+	$ret = "-c " . $_[0] ;
+    }
+    $ret ;
+}
+
+# make a versioned directory
+# input is in:
+# $_[0] = directory to create
+# $_[1] = curr dir
+# $_[2] = possible comment
+#
+# output:
+# return success or failure
+sub CTCcaseMkdir {
+    &CTUDebug( "in CTCcaseMkdir\n" ) ;
+    local( $ret ) = 0 ;
+    local( $dir ) = $_[0] ;
+    if ( ! ( $dir =~ /^\// )) {
+	$dir = $_[1] . "/" . $dir ;
+    }
+    local( $comment) = &CTCcaseFormatComment( $_[2] ) ;
+    # first we have to check out the parent directory
+    local( @alist ) = split( /\//, $dir ) ;
+    pop( @alist ) ;
+    local( $parent ) = join( "/", @alist ) ;
+    &CTUDebug( "parent directory of '" . $dir . "' is '" . $parent . "'\n" ) ;
+    $ret = system( "cleartool co -nc $parent\n" ) ;
+    if ( $ret == 0 ) {
+	# now make the dir
+	$ret = &CTURetCode( system( "cleartool mkdir " . $comment .
+				    " $dir\n" )) ;
+    } else {
+	$ret = 0 ;
+    }
+    &CTUDebug( "out of CTCcaseMkdir\n" ) ;
+    $ret ;
+}
+
+# make a versioned element
+# input is in:
+# $_[0] = element to version
+# $_[1] = curr dir
+# $_[2] = possible comment
+# $_[3] = possible eltype
+#
+# output:
+# return success or failure
+sub CTCcaseMkelem {
+    &CTUDebug( "in CTCcaseMkelem\n" ) ;
+    local( $ret ) = 0 ;
+    local( $elem ) = $_[0] ;
+    if ( ! ( $elem =~ /^\// )) {
+	$elem = $_[1] . "/" . $elem ;
+    }
+    local( $comment) = &CTCcaseFormatComment( $_[2] ) ;
+    local( $eltype ) = $_[3] ;
+    if ( $eltype ne "" ) {
+	$eltype = "-eltype " . $eltype ;
+    }
+    # first we have to check out the parent directory
+    local( @alist ) = split( /\//, $elem ) ;
+    pop( @alist ) ;
+    local( $parent ) = join( "/", @alist ) ;
+    &CTUDebug( "parent directory of '" . $elem . "' is '" . $parent . "'\n" ) ;
+    $ret = system( "cleartool co -nc $parent\n" ) ;
+    if ( $ret != 0 ) {
+	&CTUDebug( "checking out the dirctory gave return code: " . $ret .
+		  "\n" ) ;
+	$ret = 0 ;
+    }
+    # now make the elem
+    $ret = &CTURetCode( system( "cleartool mkelem " . $comment . " " .
+			       $eltype . " $elem\n" )) ;
+    &CTUDebug( "out of CTCcaseMkelem\n" ) ;
+    $ret ;
+}
+
+# done here so there will be coherence if multiple deltas are done
+require "ctime.pl" ;
+$timestamp = &ctime(time) ;
+$timestamp =~ s/\n$// ;
+@timelist = split( /\s+/, $timestamp ) ;
+$timestamp = $timelist[2] . $timelist[1] . $timelist[5] . "_" . $timelist[3] ;
+$timestamp =~ s/:/_/g ;
+
+# delta an element
+# input is in:
+# $_[0] = element to delta
+#
+# output:
+# return success or failure
+sub CTCcaseDelta {
+    require "$tool/inc/ctdelta.pl" ;
+
+    &CTUDebug( "in CTCcaseDelta\n" ) ;
+    local( $ret ) = 0 ;
+    # this is ripped from the old ctdelta script
+    &CTDeltaCheckin( $_[0] ) ;
+    local( $ver ) = &CTDeltaGetVersion( $_[0] ) ;
+    &CTUDebug( "got version '" . $ver . "'\n" ) ;
+    if ( &CTDeltaOk( $ver )) {
+	local( @verlist ) = split( /\//, $ver ) ;
+	pop( @verlist ) ;
+	pop( @verlist ) ;
+	local( $ver2 ) = join( "/", @verlist ) ;
+	&CTUDebug( "ver2 = '" . $ver2 . "'\n" ) ;
+	&CTDeltaSafeMerge( $_[0], $ver, $ver2 ) ;
+	system "cleartool checkin -nc $_[0] 2> /dev/null > /dev/null" ;
+	&CTUDebug( "merge complete, doing branch check\n" ) ;
+	&CTDeltaBranchCheck( $_[0], $ver, $timestamp ) ;
+	&CTUDebug( "logging potentially felonious activity for future" .
+		   "  incrimination\n" ) ;
+	&CTDeltaLog( $_[0], $ver, $ver2 ) ;
+	# better detection needs to be done
+	$ret = 1 ;
+    } else {
+	&CTUDebug( "cannot merge '" . $_[0] . "', no branches.\n" ) ;
+    }
+    &CTUDebug( "out of CTCcaseDelta\n" ) ;
+    $ret ;
+}
+
+# checkout an element
+# input is in:
+# $_[0] = element to checkout
+# $_[1] = possible comment
+#
+# output:
+# return success or failure
+sub CTCcaseCheckout {
+    &CTUDebug( "in CTCcaseCheckout\n" ) ;
+    local( $comment) = &CTCcaseFormatComment( $_[1] ) ;
+    local( $ret ) = &CTURetCode( system( "cleartool co " . $comment .
+					 " $_[0]\n" )) ;
+    &CTUDebug( "out of CTCcaseCheckout\n" ) ;
+    $ret ;
+}
+
+# checkin an element
+# input is in:
+# $_[0] = element to checkin
+
+#
+# output:
+# return success or failure
+sub CTCcaseCheckin {
+    &CTUDebug( "in CTCcaseCheckin\n" ) ;
+    local( $comment) = &CTCcaseFormatComment( $_[1] ) ;
+    local( $ret ) = &CTURetCode( system( "cleartool ci " . $comment .
+					 " $_[0]\n" )) ;
+    &CTUDebug( "out of CTCcaseCheckin\n" ) ;
+    $ret ;
+}
+
+# uncheckout an element
+# input is in:
+# $_[0] = element to uncheckout
+#
+# output:
+# return success or failure
+sub CTCcaseUncheckout {
+    require "$tool/inc/unco.pl" ;
+    &CTUDebug( "in CTCcaseUncheckout\n" ) ;
+    local( $ret ) = 1 ;
+    # need better error checking on this
+    system( "cleartool unco -rm $_[0]\n" ) ;
+    &CTUncoDoIt( $_[0] ) ;
+    &CTUDebug( "out of CTCcaseUncheckout\n" ) ;
+    $ret ;
+}
+
+# figure out what all I have checked out or on my branch
+# input is in:
+# $_[0] = project
+# $_[1] = flavor
+# $_[2] = spec line
+#
+# output:
+# return a \n serperated list of elements checked out
+sub CTCcaseIHave {
+    &CTUDebug( "in CTCcaseIHave\n" ) ;
+    local( $ret ) = "" ;
+    local( $branch ) = &CTAttachComputeBranch( $_[2], $_[1], $_[0] ) ;
+    local( $root ) = &CTProjRoot( $_[0] ) ;
+    local( *OUTPUT ) ;
+    open( OUTPUT, "cleartool find " . $root . " -element \"brtype(" .
+	  $branch . ")\" -nxn -print |" ) ;
+    while ( <OUTPUT> ) {
+	$ret = $ret . $_ ;
+    }
+    close( OUTPUT ) ;
+    &CTUDebug( "out of CTCcaseIHave\n" ) ;
+    $ret ;
+}
+
+# remove a versioned element
+# input is in:
+# $_[0] = element to remove
+# $_[1] = curr dir
+#
+# output:
+# return success or failure
+sub CTCcaseRmElem {
+    &CTUDebug( "in CTCcaseRmElem\n" ) ;
+    local( $ret ) = 0 ;
+    local( $elem ) = $_[0] ;
+    if ( ! ( $elem =~ /^\// )) {
+	$elem = $_[1] . "/" . $elem ;
+    }
+    # first we have to check out the parent directory
+    local( @alist ) = split( /\//, $elem ) ;
+    pop( @alist ) ;
+    local( $parent ) = join( "/", @alist ) ;
+    &CTUDebug( "parent directory of '" . $elem . "' is '" . $parent . "'\n" ) ;
+    $ret = system( "cleartool co -nc $parent\n" ) ;
+    if ( $ret == 0 ) {
+	# now nuke the element
+	$ret = &CTURetCode( system( "cleartool rmname $elem\n" )) ;
+    } else {
+	$ret = 0 ;
+    }
+    &CTUDebug( "out of CTCcaseRmElem\n" ) ;
+    $ret ;
+}
+
+# mv a versioned element from one name to another
+# input is in:
+# $_[0] = from element
+# $_[1] = to element
+# $_[2] = current directory
+#
+# output:
+# return success or failure
+sub CTCcaseMv {
+    &CTUDebug( "in CTCcaseMv\n" ) ;
+    local( $ret ) = 0 ;
+    local( $elem ) = $_[0] ;
+    if ( ! ( $elem =~ /^\// )) {
+	$elem = $_[2] . "/" . $elem ;
+    }
+    # first we have to check out the parent directory
+    local( @alist ) = split( /\//, $elem ) ;
+    pop( @alist ) ;
+    local( $parent ) = join( "/", @alist ) ;
+    &CTUDebug( "parent directory of '" . $elem . "' is '" . $parent . "'\n" ) ;
+    local( $elem2 ) = $_[1] ;
+    if ( ! ( $elem2 =~ /^\// )) {
+	$elem2 = $_[2] . "/" . $elem2 ;
+    }
+    local( @alist ) = split( /\//, $elem2 ) ;
+    pop( @alist ) ;
+    local( $parent2 ) = join( "/", @alist ) ;
+    &CTUDebug( "parent directory of '" . $elem2 . "' is '" . $parent2 .
+	       "'\n" ) ;
+    $ret = system( "cleartool co -nc $parent\n" ) ;
+    if ( $ret == 0 ) {
+	$ret = system( "cleartool co -nc $parent2\n" ) ;
+	if ( $ret == 0 ) {
+	    # now move the element
+	    $ret = &CTURetCode( system( "cleartool mv $elem $elem2\n" )) ;
+	} else {
+	    $ret = 0 ;
+	}
+    } else {
+	$ret = 0 ;
+    }
+    &CTUDebug( "out of CTCcaseMv\n" ) ;
+    $ret ;
+}
+
+# build a list of targets
+# input is in:
+# $_[0] = targets
+#
+# output:
+# return success or failure
+sub CTCcaseMake {
+    &CTUDebug( "in CTCcaseMake\n" ) ;
+    local( $ret ) = 0 ;
+    local( $line ) = "clearmake -C gnu " . $_[0] .
+	" |& grep -v \"^clearmake: Warning: Config\"\n" ;
+    &CTUDebug( "line = '" . $line . "'\n" ) ;
+    $ret = &CTURetCode( system( $line )) ;
+    &CTUDebug( "out of CTCcaseMake\n" ) ;
+    $ret ;
+}
+
+1;

+ 55 - 0
dtool/src/attach/ctci

@@ -0,0 +1,55 @@
+#!/usr/local/bin/perl
+
+sub CTCiUsage {
+    print STDERR "Usage: ctci [-c \"comment\"] [-nc] element-name [...]\n" ;
+    print STDERR "Options:\n" ;
+    print STDERR "  -c \"comment\" : provide a comment about this action\n" ;
+    print STDERR "  -nc : expect no comment on this action\n" ;
+    exit;
+}
+
+if ( $#ARGV < 0 ) {
+    &CTCiUsage ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured for CTtools" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$comment = "" ;
+if ( $ARGV[0] eq "-nc" ) {
+    shift( @ARGV ) ;
+    &CTUDebug( "-nc processed\n" ) ;
+}
+if ( $ARGV[0] eq "-c" ) {
+    shift( @ARGV ) ;
+    $comment = $ARGV[0] ;
+    shift( @ARGV ) ;
+    &CTUDebug( "setting comment to '" . $comment . "'\n" ) ;
+}
+
+if ( $#ARGV < 0 ) {
+    &CTCiUsage ;
+}
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+foreach $item ( @ARGV ) {
+    if ( -e $item ) {
+	if ( ! &CTCMCheckin( $item, $projname, $spec, $comment ) ) {
+	    print STDERR "Could not checkin '$item'\n" ;
+	}
+    } else {
+	print STDERR "No such file '$item'.\n" ;
+    }
+}

+ 580 - 0
dtool/src/attach/ctcm.pl

@@ -0,0 +1,580 @@
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+
+# given a spec line, do the 'correct' setup for it
+# input is in:
+# $_[0] = project
+# $_[1] = spec line
+# $_[2] = flavor
+sub CTCMSetup {
+    local( $type ) = &CTSpecType( $_[1] ) ;
+    if ( $type eq "vroot" ) {
+	&CTUDebug( "running setup for an atria tree\n" ) ;
+	if ( $ENV{"HAVE_ATRIA"} eq "yes" ) {
+	    require "$tool/inc/ctccase.pl" ;
+	    &CTAttachCCSetup( $_[0], $_[1], $_[2] ) ;
+	} else {
+	    &CTUDebug( "don't HAVE_ATRIA!\n" ) ;
+	}
+	# if we don't have atria, and it's a vroot, well..
+    } elsif ( $type eq "croot" ) {
+	&CTUDebug( "running setup for CVS\n" ) ;
+	require "$tool/inc/ctcvs.pl" ;
+	local( $serve ) = &CTCvsServerLine( $_[0], $_[1] ) ;
+	local( $thing ) = &CTCvsLogin( $serve ) ;
+	if ( ! $thing ) {
+	    print STDERR "CVS login failed given server line '" . $serve .
+		"'\n" ;
+	}
+	print STDERR "I don't know how to setup CVS stuff yet!!\n" ;
+    }
+    # no other types have any work that needs to be done at this time
+}
+
+# given a directory, make sure it's versioned
+# input is in:
+# $_[0] = directory
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = comment (optional, "" if none)
+#
+# output:
+# return success or failure
+sub CTCMMkdir {
+    &CTUDebug( "in CTCMMkdir\n" ) ;
+    local( $ret ) = 0 ;
+    # first check that the directory is in the project, and is not the root
+    local( $flav ) = &CTQueryProj( $_[1] ) ;
+    local( $root ) = &CTComputeRoot( $_[1], $flav, $_[2] ) ;
+    local( $pwd ) = &CTUCurrDir() ;
+    local( $isok ) = 0 ;
+    if ( $_[0] =~ /^\// ) {
+	# starts with a /, might not be in the project we are
+	if (( $_[0] =~ /^$root/ ) && ( $_[0] ne $root )) {
+	    $isok = 1 ;
+	} else {
+	    $isok = 0 ;
+	}
+    } else {
+	# are we sitting in the project?
+	if ( $pwd =~ /^$root/ ) {
+	    $isok = 1 ;
+	} else {
+	    $isok = 0 ;
+	}
+    }
+    if ( $isok ) {
+	# ok, it is.  Does one already exist?
+	if ( -e $_[0] ) {
+	    # already one there, nothing to do
+	    &CTUDebug( "directory '" . $_[0] . "' already exists\n" ) ;
+	    $ret = 1 ;
+	} else {
+	    # now switch off on how to actually do it
+	    local( $type ) = &CTSpecType( $_[2] ) ;
+	    if ( $type eq "vroot" ) {
+		require "$tool/inc/ctccase.pl" ;
+		$ret = &CTCcaseMkdir( $_[0], $pwd, $_[3] ) ;
+	    } elsif ( $type eq "root" ) {
+		require "$tool/inc/ctntool.pl" ;
+		$ret = &CTNtoolMkdir( $_[0], $pwd, $_[3] ) ;
+	    } elsif ( $type eq "croot" ) {
+		require "$tool/inc/ctcvs.pl" ;
+		$ret = &CTCvsMkdir( $_[0], $_[1], $_[2], $_[3] ) ;
+	    } else {
+		print STDERR "CTCMMkdir::error! got invalid spec type '" .
+		    $type . "'\n" ;
+	    }
+	}
+    } else {
+	print STDERR "directory '" . $_[0] . "' not in project '" . $_[1] .
+	    "' or is the root.\n" ;
+    }
+    &CTUDebug( "out of CTCMMkdir\n" ) ;
+    $ret ;
+}
+
+# given a file, make sure it's versioned
+# input is in:
+# $_[0] = file
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = comment (optional, "" if none)
+# $_[4] = eltype (optional, "" if none)
+#
+# output:
+# return success or failure
+sub CTCMMkelem {
+    &CTUDebug( "in CTCMMkelem\n" ) ;
+    local( $ret ) = 0;
+    # first check that the directory is in the project
+    local( $flav ) = &CTQueryProj( $_[1] ) ;
+    local( $root ) = &CTComputeRoot( $_[1], $flav, $_[2] ) ;
+    local( $isok ) = 0 ;
+    local( $pwd ) = &CTUCurrDir() ;
+    # synth an eltype if there is none
+    if ( ! -e $_[0] ) {
+	# need it to already exist
+	$isok = 0 ;
+    } else {
+	if ( -d $_[0] ) {
+	    # wrong command for a directory
+	    $isok = 0 ;
+	} else {
+	    if ( $_[0] =~ /^\// ) {
+		# starts with a /, might not be in the project we are
+		if ( $_[0] =~ /^$root/ ) {
+		    $isok = 1 ;
+		} else {
+		    $isok = 0 ;
+		}
+	    } else {
+		# are we sitting in the project?
+		if ( $pwd =~ /^$root/ ) {
+		    $isok = 1 ;
+		} else {
+		    $isok = 0 ;
+		}
+	    }
+	}
+    }
+    if ( $isok ) {
+	# now switch off on how to actually do the work
+	local( $type ) = &CTSpecType( $_[2] ) ;
+	if ( $type eq "vroot" ) {
+	    require "$tool/inc/ctccase.pl" ;
+	    $ret = &CTCcaseMkelem( $_[0], $pwd, $_[3], $_[4] ) ;
+	} elsif ( $type eq "root" ) {
+	    require "$tool/inc/ctntool.pl" ;
+	    $ret = &CTNtoolMkelem( $_[0], $pwd, $_[3], $_[4] ) ;
+	} elsif ( $type eq "croot" ) {
+	    require "$tool/inc/ctcvs.pl" ;
+	    $ret = &CTCvsMkelem( $_[0], $_[1], $_[2], $_[3] ) ;
+	} else {
+	    print STDERR "CTCMMkelem::error! got invalid spec type '" .
+		$type . "'\n" ;
+	}
+    }
+    &CTUDebug( "out of CTCMMkelem\n" ) ;
+    $ret ;
+}
+
+# given an element, delta it in
+# input is in:
+# $_[0] = element
+# $_[1] = project
+# $_[2] = spec line
+#
+# output:
+# return success or failure
+sub CTCMDelta {
+    &CTUDebug( "in CTCMDelta\n" ) ;
+    local( $ret ) = 0 ;
+    # first check that the element is in the project
+    local( $flav ) = &CTQueryProj( $_[1] ) ;
+    local( $root ) = &CTComputeRoot( $_[1], $flav, $_[2] ) ;
+    local( $pwd ) = &CTUCurrDir() ;
+    local( $isok ) = 0 ;
+    if ( ! -e $_[0] ) {
+	# can't delta something that doesn't exist
+	$isok = 0 ;
+    } else {
+	if ( $_[0] =~ /^\// ) {
+	    # starts with a /, might not be in the project we are
+	    if ( $_[0] =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	} else {
+	    # are we sitting in the project?
+	    if ( $pwd =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	}
+    }
+    if ( $isok ) {
+	# now switch off on how to actually do the work
+	local( $type ) = &CTSpecType( $_[2] ) ;
+	if ( $type eq "vroot" ) {
+	    require "$tool/inc/ctccase.pl" ;
+	    $ret = &CTCcaseDelta( $_[0] ) ;
+	} elsif ( $type eq "root" ) {
+	    require "$tool/inc/ctntool.pl" ;
+	    $ret = &CTNtoolDelta( $_[0] ) ;
+	} elsif ( $type eq "croot" ) {
+	    require "$tool/inc/ctcvs.pl" ;
+	    $ret = &CTCvsDelta( $_[0], $_[1], $_[2] ) ;
+	} else {
+	    print STDERR "CTCMDelta::error! got invalid spec type '" . $type .
+		"'\n" ;
+	}
+    } else {
+	&CTUDebug( "failed delta pre-checks\n" ) ;
+    }
+    &CTUDebug( "out of CTCMDelta\n" ) ;
+    $ret ;
+}
+
+# given an element, check it out
+# input is in:
+# $_[0] = element
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = comment (optional, "" if none)
+#
+# output:
+# return success or failure
+sub CTCMCheckout {
+    &CTUDebug( "in CTCMCheckout\n" ) ;
+    local( $ret ) = 0 ;
+    # first check that the element is in the project
+    local( $flav ) = &CTQueryProj( $_[1] ) ;
+    local( $root ) = &CTComputeRoot( $_[1], $flav, $_[2] ) ;
+    local( $pwd ) = &CTUCurrDir() ;
+    local( $isok ) = 0 ;
+    if ( ! -e $_[0] ) {
+	# can't checkout something that doesn't exist
+	$isok = 0 ;
+    } else {
+	if ( $_[0] =~ /^\// ) {
+	    # starts with a /, might not be in the project we are
+	    if ( $_[0] =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	} else {
+	    # are we sitting in the project?
+	    if ( $pwd =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	}
+    }
+    if ( $isok ) {
+	# now switch off on how to actually do the work
+	local( $type ) = &CTSpecType( $_[2] ) ;
+	if ( $type eq "vroot" ) {
+	    require "$tool/inc/ctccase.pl" ;
+	    $ret = &CTCcaseCheckout( $_[0], $_[3] ) ;
+	} elsif ( $type eq "root" ) {
+	    require "$tool/inc/ctntool.pl" ;
+	    $ret = &CTNtoolCheckout( $_[0], $_[3] ) ;
+	} elsif ( $type eq "croot" ) {
+	    require "$tool/inc/ctcvs.pl" ;
+	    $ret = &CTCvsCheckout( $_[0], $_[1], $_[2], $_[3] ) ;
+	} else {
+	    print STDERR "CTCMCheckout::error! got invalid spec type '" .
+		$type . "'\n" ;
+	}
+    }
+    &CTUDebug( "out of CTCMCheckout\n" ) ;
+    $ret ;
+}
+
+# given an element, check it in
+# input is in:
+# $_[0] = element
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = comment (optional, "" if none)
+#
+# output:
+# return success or failure
+sub CTCMCheckin {
+    &CTUDebug( "in CTCMCheckin\n" ) ;
+    local( $ret ) = 0 ;
+    # first check that the element is in the project
+    local( $flav ) = &CTQueryProj( $_[1] ) ;
+    local( $root ) = &CTComputeRoot( $_[1], $flav, $_[2] ) ;
+    local( $pwd ) = &CTUCurrDir() ;
+    local( $isok ) = 0 ;
+    if ( ! -e $_[0] ) {
+	# can't checkin something that doesn't exist
+	$isok = 0 ;
+    } else {
+	if ( $_[0] =~ /^\// ) {
+	    # starts with a /, might not be in the project we are
+	    if ( $_[0] =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	} else {
+	    # are we sitting in the project?
+	    if ( $pwd =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	}
+    }
+    if ( $isok ) {
+	# now switch off on how to actually do the work
+	local( $type ) = &CTSpecType( $_[2] ) ;
+	if ( $type eq "vroot" ) {
+	    require "$tool/inc/ctccase.pl" ;
+	    $ret = &CTCcaseCheckin( $_[0], $_[3] ) ;
+	} elsif ( $type eq "root" ) {
+	    require "$tool/inc/ctntool.pl" ;
+	    $ret = &CTNtoolCheckin( $_[0], $_[3] ) ;
+	} elsif ( $type eq "croot" ) {
+	    require "$tool/inc/ctcvs.pl" ;
+	    $ret = &CTCvsCheckin( $_[0], $_[1], $_[2], $_[3] ) ;
+	} else {
+	    print STDERR "CTCMCheckin::error! got invalid spec type '" .
+		$type . "'\n" ;
+	}
+    }
+    &CTUDebug( "out of CTCMCheckin\n" ) ;
+    $ret ;
+}
+
+# given an element, uncheck it out
+# input is in:
+# $_[0] = element
+# $_[1] = project
+# $_[2] = spec line
+#
+# output:
+# return success or failure
+sub CTCMUncheckout {
+    &CTUDebug( "in CTCMUncheckout\n" ) ;
+    local( $ret ) = 0 ;
+    # first check that the element is in the project
+    local( $flav ) = &CTQueryProj( $_[1] ) ;
+    local( $root ) = &CTComputeRoot( $_[1], $flav, $_[2] ) ;
+    local( $pwd ) = &CTUCurrDir() ;
+    local( $isok ) = 0 ;
+    if ( ! -e $_[0] ) {
+	# can't uncheckout something that doesn't exist
+	$isok = 0 ;
+    } else {
+	if ( $_[0] =~ /^\// ) {
+	    # starts with a /, might not be in the project we are
+	    if ( $_[0] =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	} else {
+	    # are we sitting in the project?
+	    if ( $pwd =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	}
+    }
+    if ( $isok ) {
+	# now switch off on how to actually do the work
+	local( $type ) = &CTSpecType( $_[2] ) ;
+	if ( $type eq "vroot" ) {
+	    require "$tool/inc/ctccase.pl" ;
+	    $ret = &CTCcaseUncheckout( $_[0] ) ;
+	} elsif ( $type eq "root" ) {
+	    require "$tool/inc/ctntool.pl" ;
+	    $ret = &CTNtoolUncheckout( $_[0] ) ;
+	} elsif ( $type eq "croot" ) {
+	    require "$tool/inc/ctcvs.pl" ;
+	    $ret = &CTCvsUncheckout( $_[0], $_[1], $_[2] ) ;
+	} else {
+	    print STDERR "CTCMUncheckout::error! got invalid spec type '" .
+		$type . "'\n" ;
+	}
+    }
+    &CTUDebug( "out of CTCMUncheckout\n" ) ;
+    $ret ;
+}
+
+# figure out what all I have checked out in a project
+# input is in:
+# $_[0] = project
+# $_[1] = flavor
+# $_[2] = spec line
+#
+# output:
+# return a \n serperated list of elements checked out
+sub CTCMIHave {
+    &CTUDebug( "in CTCMIHave\n" ) ;
+    local( $ret ) = "" ;
+    local( $type ) = &CTSpecType( $_[2] ) ;
+    if ( $type eq "vroot" ) {
+	require "$tool/inc/ctccase.pl" ;
+	$ret = &CTCcaseIHave( $_[0], $_[1], $_[2] ) ;
+    } elsif ( $type eq "root" ) {
+	require "$tool/inc/ctntool.pl" ;
+	$ret = &CTNtoolIHave( $_[0], $_[1], $_[2] ) ;
+    } elsif ( $type eq "croot" ) {
+	require "$tool/inc/ctcvs.pl" ;
+	$ret = &CTCvsIHave( $_[0], $_[1], $_[2] ) ;
+    } else {
+	print STDERR "CTCMIHave::error! got invalid spec type '" . $type .
+	    "'\n" ;
+    }
+    &CTUDebug( "out of CTCMIHave\n" ) ;
+    $ret ;
+}
+
+# given an element, remove it from the repository
+# input is in:
+# $_[0] = element
+# $_[1] = project
+# $_[2] = spec line
+#
+# output:
+# return success or failure
+sub CTCMRmElem {
+    &CTUDebug( "in CTCMRmElem\n" ) ;
+    local( $ret ) = 0 ;
+    # first check that the element is in the project
+    local( $flav ) = &CTQueryProj( $_[1] ) ;
+    local( $root ) = &CTComputeRoot( $_[1], $flav, $_[2] ) ;
+    local( $pwd ) = &CTUCurrDir() ;
+    local( $isok ) = 0 ;
+    if ( ! -e $_[0] ) {
+	# can't rmname something that doesn't exist
+	$isok = 0 ;
+    } else {
+	if ( $_[0] =~ /^\// ) {
+	    # starts with a /, might not be in the project we are
+	    if ( $_[0] =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	} else {
+	    # are we sitting in the project?
+	    if ( $pwd =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	}
+    }
+    if ( $isok ) {
+	# now switch off on how to actually do the work
+	local( $type ) = &CTSpecType( $_[2] ) ;
+	if ( $type eq "vroot" ) {
+	    require "$tool/inc/ctccase.pl" ;
+	    $ret = &CTCcaseRnElem( $_[0], $pwd ) ;
+	} elsif ( $type eq "root" ) {
+	    require "$tool/inc/ctntool.pl" ;
+	    $ret = &CTNtoolRmElem( $_[0], $pwd ) ;
+	} elsif ( $type eq "croot" ) {
+	    require "$tool/inc/ctcvs.pl" ;
+	    $ret = &CTCvsRmElem( $_[0], $_[1], $_[2] ) ;
+	} else {
+	    print STDERR "CTCMRmElem::error! got invalid spec type '" .
+		$type . "'\n" ;
+	}
+    }
+    &CTUDebug( "out of CTCMRmElem\n" ) ;
+    $ret ;
+}
+
+# move an element from one name to another
+# input is in:
+# $_[0] = from element
+# $_[1] = to element
+# $_[2] = project
+# $_[3] = spec line
+#
+# output:
+# return success or failure
+sub CTCMMv {
+    &CTUDebug( "in CTCMMv\n" ) ;
+    local( $ret ) = 0 ;
+    # first check that the from and to are in the project
+    local( $flav ) = &CTQueryProj( $_[1] ) ;
+    local( $root ) = &CTComputeRoot( $_[1], $flav, $_[2] ) ;
+    local( $pwd ) = &CTUCurrDir() ;
+    local( $isok ) = 0 ;
+    if ( $_[0] =~ /^\// ) {
+	# starts with a /, might not be in the project we are
+	if ( $_[0] =~ /^$root/ ) {
+	    $isok = 1 ;
+	} else {
+	    $isok = 0 ;
+	}
+    } else {
+	# are we sitting in the project?
+	if ( $pwd =~ /^$root/ ) {
+	    $isok = 1 ;
+	} else {
+	    $isok = 0 ;
+	}
+    }
+    if ( $isok ) {
+	if ( $_[1] =~ /^\// ) {
+	    # starts with a /, might not be in the project we are
+	    if ( $_[1] =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	} else {
+	    # are we sitting in the project?
+	    if ( $pwd =~ /^$root/ ) {
+		$isok = 1 ;
+	    } else {
+		$isok = 0 ;
+	    }
+	}
+    }
+    if ( $isok ) {
+	# now switch off on how to actually do the work
+	local( $type ) = &CTSpecType( $_[3] ) ;
+	if ( $type eq "vroot" ) {
+	    require "$tool/inc/ctccase.pl" ;
+	    $ret = &CTCcaseMv( $_[0], $_[1], $pwd ) ;
+	} elsif ( $type eq "root" ) {
+	    require "$tool/inc/ctntool.pl" ;
+	    $ret = &CTNtoolMv( $_[0], $_[1], $pwd ) ;
+	} elsif ( $type eq "croot" ) {
+	    require "$tool/inc/ctcvs.pl" ;
+	    $ret = &CTCvsMv( $_[0], $_[1], $_[2], $_[3] ) ;
+	} else {
+	    print STDERR "CTCMMv::error! got invalid spec type '" .
+		$type . "'\n" ;
+	}
+    }
+    &CTUDebug( "out of CTCMMv\n" ) ;
+    $ret ;
+}
+
+# give a list of targets, build them
+# input is in:
+# $_[0] = targets
+# $_[1] = project
+# $_[2] = spec line
+#
+# output:
+# return success or failure
+sub CTCMMake {
+    &CTUDebug( "in CTCMMake\n" ) ;
+    local( $ret ) = 0 ;
+    # now switch off on how to actually do the work
+    local( $type ) = &CTSpecType( $_[2] ) ;
+    if ( $type eq "vroot" ) {
+	require "$tool/inc/ctccase.pl" ;
+	$ret = &CTCcaseMake( $_[0] ) ;
+    } elsif ( $type eq "root" ) {
+	require "$tool/inc/ctntool.pl" ;
+	$ret = &CTNtoolMake( $_[0] ) ;
+    } elsif ( $type eq "croot" ) {
+	require "$tool/inc/ctcvs.pl" ;
+	$ret = &CTCvsMake( $_[0] ) ;
+    } else {
+	print STDERR "CTCMMake::error! got invalid spec type '" . $type .
+	    "'\n" ;
+    }
+    &CTUDebug( "out of CTCMMake\n" ) ;
+    $ret ;
+}
+
+1;

+ 55 - 0
dtool/src/attach/ctco

@@ -0,0 +1,55 @@
+#!/usr/local/bin/perl
+
+sub CTCoUsage {
+    print STDERR "Usage: ctco [-c \"comment\"] [-nc] element-name [...]\n" ;
+    print STDERR "Options:\n" ;
+    print STDERR "  -c \"comment\" : provide a comment about this action\n" ;
+    print STDERR "  -nc : expect no comment on this action\n" ;
+    exit;
+}
+
+if ( $#ARGV < 0 ) {
+    &CTCoUsage ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured for CTtools" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$comment = "" ;
+if ( $ARGV[0] eq "-nc" ) {
+    shift( @ARGV ) ;
+    &CTUDebug( "-nc processed\n" ) ;
+}
+if ( $ARGV[0] eq "-c" ) {
+    shift( @ARGV ) ;
+    $comment = $ARGV[0] ;
+    shift( @ARGV ) ;
+    &CTUDebug( "setting comment to '" . $comment . "'\n" ) ;
+}
+
+if ( $#ARGV < 0 ) {
+    &CTCoUsage ;
+}
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+foreach $item ( @ARGV ) {
+    if ( -e $item ) {
+	if ( ! &CTCMCheckout( $item, $projname, $spec, $comment ) ) {
+	    print STDERR "Could not checkout '$item'\n" ;
+	}
+    } else {
+	print STDERR "No such file '$item'.\n" ;
+    }
+}

+ 408 - 0
dtool/src/attach/ctcvs.pl

@@ -0,0 +1,408 @@
+# given a possibly empty string, format it into a comment or -nc
+# input is in:
+# $_[0] = possible comment string
+#
+# output is:
+# string for use by CVS functions
+sub CTCvsFormatComment {
+    local( $ret ) = "" ;
+    if ( $_[0] ne "" ) {
+	$ret = "-m " . $_[0] ;
+    }
+    $ret ;
+}
+
+# given a project and spec line, compute the server line
+# input is in:
+# $_[0] = project
+# $_[1] = spec line
+#
+# output:
+# return a sever line, or "" if not a croot
+sub CTCvsServerLine {
+    &CTUDebug( "in CTCvsServerLine\n" ) ;
+    local( $ret ) = "" ;
+    local( $type ) = &CTSpecType( $_[1] ) ;
+    if ( $type eq "croot" ) {
+	local( $options ) = &CTSpecOptions( $_[1] ) ;
+	local( $sline ) = &CTSpecFindOption( $options, "server" ) ;
+	if ( $sline ne "" ) {
+	    $ret = join( ":", split( /,/, $sline ));
+	}
+    }
+    &CTUDebug( "out of CTCvsServerLine\n" ) ;
+    $ret ;
+}
+
+# if needed log into a cvs server
+# input is in:
+# $_[0] = server line
+#
+# output:
+# return success or failure
+sub CTCvsLogin {
+    &CTUDebug( "in CTCvsLogin\n" ) ;
+    local( $ret ) = 0 ;
+    &CTUDebug( "server line is '" . $_[0] . "'\n" ) ;
+    if ( $_[0] ne "" ) {
+	# ok.  we actually have something, lets look in .cvspass
+	local( $path ) ;
+	local( *PASSFILE ) ;
+	if ( $ENV{"PENV"} eq "WIN32" ) {
+	    $path = $ENV{"HOME"} . "/.cvspass" ;
+	} else {
+	    # $path = "~/.cvspass" ;
+	    $path = $ENV{"HOME"} . "/.cvspass" ;
+	}
+	&CTUDebug( "looking for '" . $path . "'\n" ) ;
+	if ( -e $path ) {
+	    open( PASSFILE, "< $path" ) ;
+	    $_ = <PASSFILE> ;
+	    s/\n$// ;
+	    local( @line ) = split ;
+	    # ok, the server line is in [0] and the password in [1].
+	    &CTUDebug( "server line from .cvspass is '" . $line[0] . "'\n" ) ;
+	    if ( $line[0] ne $_[0] ) {
+		local( $line ) = "cvs -d " . $_[0] . " login" ;
+		&CTUDebug( "about to run '" . $line . "'\n" ) ;
+		$ret = &CTURetCode( system( $line )) ;
+	    } else {
+		# we're fine, we're already logged in to that
+		$ret = 1 ;
+	    }
+	} else {
+	    &CTUDebug( $path . " file does not exist\n" ) ;
+	    local( $line ) = "cvs -d " . $_[0] . " login" ;
+	    &CTUDebug( "about to run '" . $line . "'\n" ) ;
+	    $ret = &CTURetCode( system( $line )) ;
+	}
+    }
+    &CTUDebug( "out of CTCvsLogin\n" ) ;
+    $ret ;
+}
+
+require "$tool/inc/ctproj.pl" ;
+
+# add a versioned element to the repository
+# input is in:
+# $_[0] = element
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = possible comment
+#
+# output:
+# return success or failure
+sub CTCvsAdd {
+    &CTUDebug( "in CTCvsAdd\n" ) ;
+    # first we need to 'login' to the repository
+    local( $comment ) = &CTCvsFormatComment( $_[3] ) ;
+    local( $serve ) = &CTCvsServerLine( $_[1], $_[2] ) ;
+    local( $ret ) = &CTCvsLogin( $serve ) ;
+    if ( $ret ) {
+	# now issue the add command
+	local( $root ) = &CTProjRoot( $_[1] ) ;
+	local( $line ) = "" ;
+	local( $elem ) = $_[0] ;
+	if ( $elem =~ /^\// ) {
+	    local( $proj ) = $_[1] ;
+	    $proj =~ tr/a-z/A-Z/ ;
+	    $line = "cd \$" . $proj . "; " ;
+	    $elem =~ s/^$root\/// ;
+	}
+	$line = $line . "cvs -d " . $serve . " add " . $comment . " $elem" ;
+	&CTUDebug( "about to execute '" . $line . "'\n" ) ;
+	$ret = &CTURetCode( system( $line )) ;
+    }
+    &CTUDebug( "out of CTCvsAdd\n" ) ;
+    $ret ;
+}
+
+# ci a versioned element to the repository
+# input is in:
+# $_[0] = element
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = possible comment
+#
+# output:
+# return success or failure
+sub CTCvsCi {
+    &CTUDebug( "in CTCvsCi\n" ) ;
+    # first we need to 'login' to the repository
+    local( $comment ) = &CTCvsFormatComment( $_[3] ) ;
+    local( $serve ) = &CTCvsServerLine( $_[1], $_[2] ) ;
+    local( $ret ) = &CTCvsLogin( $serve ) ;
+    if ( $ret ) {
+	# now issue the add command
+	local( $root ) = &CTProjRoot( $_[1] ) ;
+	local( $line ) = "" ;
+	local( $elem ) = $_[0] ;
+	if ( $elem =~ /^\// ) {
+	    local ( $proj ) = $_[1] ;
+	    $proj =~ tr/a-z/A-Z/ ;
+	    $line = "cd \$" . $proj . "; " ;
+	    $elem =~ s/^$root\/// ;
+	}
+	$line = $line . "cvs -d " . $serve . " ci " . $comment . " $elem" ;
+	&CTUDebug( "about to execute '" . $line . "'\n" ) ;
+	$ret = &CTURetCode( system( $line )) ;
+    }
+    &CTUDebug( "out of CTCvsCi\n" ) ;
+    $ret ;
+}
+
+# rm a versioned element from the repository
+# input is in:
+# $_[0] = element
+# $_[1] = project
+# $_[2] = spec line
+#
+# output:
+# return success or failure
+sub CTCvsRm {
+    &CTUDebug( "in CTCvsRm\n" ) ;
+    # first we need to 'login' to the repository
+    local( $serve ) = &CTCvsServerLine( $_[1], $_[2] ) ;
+    local( $ret ) = &CTCvsLogin( $serve ) ;
+    if ( $ret ) {
+	# now issue the add command
+	$ret = &CTURetCode( system( "cvs -d " . $serve . " rm $_[0]\n" )) ;
+    }
+    &CTUDebug( "out of CTCvsRm\n" ) ;
+    $ret ;
+}
+
+# make a versioned directory
+# input is in:
+# $_[0] = directory to create
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = possible comment
+#
+# output:
+# return success or failure
+sub CTCvsMkdir {
+    &CTUDebug( "in CTCvsMkdir\n" ) ;
+    local( $ret ) = 0 ;
+    # first make the dir
+    $ret = &CTURetCode( system( "mkdir $_[0]\n" )) ;
+    if ( $ret ) {
+	# now version it
+	$ret = &CTCvsAdd( $_[0], $_[1], $_[2], $_[3] ) ;
+    } else {
+	&CTUDebug( "could not create directory '" . $_[0] . "'\n" ) ;
+	$ret = 0 ;
+    }
+    &CTUDebug( "out of CTCvsMkdir\n" ) ;
+    $ret ;
+}
+
+# make a versioned element
+# input is in:
+# $_[0] = element to version
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = possible comment
+#
+# output:
+# return success or failure
+sub CTCvsMkelem {
+    &CTUDebug( "in CTCvsMkelem\n" ) ;
+    # first cvs add the file
+    local( $ret ) = &CTCvsAdd( $_[0], $_[1], $_[2], $_[3] ) ;
+    if ( $ret ) {
+	# now commit it
+	$ret = &CTCvsCi( $_[0], $_[1], $_[2], $_[3] ) ;
+    } else {
+	&CTUDebug( "could not CVS add '" . $_[0] . "'\n" ) ;
+	$ret = 0 ;
+    }
+    &CTUDebug( "out of CTCvsMkelem\n" ) ;
+    $ret ;
+}
+
+# delta an element
+# input is in:
+# $_[0] = element to delta
+# $_[1] = project
+# $_[2] = spec line
+#
+# output:
+# return success or failure
+sub CTCvsDelta {
+    &CTUDebug( "in CTCvsDelta\n" ) ;
+    local( $ret ) = 0 ;
+    # for lack of better idea, this is going to be just checkin for now
+    if ( -d $_[0] ) {
+	# we don't version directories in CVS
+	$ret = 1 ;
+    } else {
+	$ret = &CTCvsCi( $_[0], $_[1], $_[2] ) ;
+    }
+    &CTUDebug( "out of CTCvsDelta\n" ) ;
+    $ret ;
+}
+
+# checkout an element
+# input is in:
+# $_[0] = element to checkout
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = possible comment
+#
+# output:
+# return success or failure
+sub CTCvsCheckout {
+    &CTUDebug( "in CTCvsCheckout\n" ) ;
+    local( $ret ) = 1 ;
+    # for my limited understanding of CVS, there doesn't seem to be any
+    # 'checkout' for it.
+    &CTUDebug( "out of CTCvsCheckout\n" ) ;
+    $ret ;
+}
+
+# checkin an element
+# input is in:
+# $_[0] = element to checkin
+# $_[1] = project
+# $_[2] = spec line
+# $_[3] = possible comment
+#
+# output:
+# return success or failure
+sub CTCvsCheckin {
+    &CTUDebug( "in CTCvsCheckin\n" ) ;
+    local( $ret ) = 0 ;
+    if ( -d $_[0] ) {
+	# we don't version directories in CVS
+	$ret = 1 ;
+    } else {
+	$ret = &CTCvsCi( $_[0], $_[1], $_[2], $_[3] ) ;
+    }
+    &CTUDebug( "out of CTCvsCheckin\n" ) ;
+    $ret ;
+}
+
+# uncheckout an element
+# input is in:
+# $_[0] = element to uncheckout
+# $_[1] = project
+# $_[2] = spec line
+#
+# output:
+# return success or failure
+sub CTCvsUncheckout {
+    &CTUDebug( "in CTCvsUncheckout\n" ) ;
+    local( $ret ) = 0 ;
+    if ( -d $_[0] ) {
+	# we don't version directories in CVS
+	$ret = 1 ;
+    } else {
+	$ret = &CTURetCode( system( "rm $_[0]" ) ) ;
+	if ( $ret ) {
+	    local( $serve ) = &CTCvsServerLine( $_[1], $_[2] ) ;
+	    $ret = &CTCvsLogin( $serve ) ;
+	    if ( $ret ) {
+		$ret = &CTURetCode( system( "cvs -d " . $serve . " update " .
+					    $_[0] )) ;
+	    }
+	}
+    }
+    &CTUDebug( "out of CTCvsUncheckout\n" ) ;
+    $ret ;
+}
+
+# figure out what all I have checked out
+# input is in:
+# $_[0] = project
+# $_[1] = flavor
+# $_[2] = spec line
+#
+# output:
+# return a \n serperated list of elements checked out
+sub CTCvsIHave {
+    &CTUDebug( "in CTCvsIHave\n" ) ;
+    local( $ret ) = "" ;
+    print STDERR "I don't know how to do IHave yet!\n" ;
+    &CTUDebug( "out of CTCvsIHave\n" ) ;
+    $ret ;
+}
+
+# remove an element from the repository
+# input is in:
+# $_[0] = element to uncheckout
+# $_[1] = project
+# $_[2] = spec line
+#
+# output:
+# return success or failure
+sub CTCvsRmElem {
+    &CTUDebug( "in CTCvsRmElem\n" ) ;
+    local( $ret ) = 0 ;
+    if ( -d $_[0] ) {
+	# CVS doesn't really do this.  If there are no files in the directory,
+	# the next time an update -P is run, it will be deleted.
+	$ret = 1 ;
+    } else {
+	$ret = &CTURetCode( system( "rm $_[0]" ) ) ;
+	if ( $ret ) {
+	    $ret = &CTCvsRm( $_[0], $_[1], $_[2] ) ;
+	    if ( $ret ) {
+		$ret = &CTCvsCi( $_[0], $_[1], $_[2] ) ;
+	    }
+	}
+    }
+    &CTUDebug( "out of CTCvsRmElem\n" ) ;
+    $ret ;
+}
+
+# move a versioned element from one name to another
+# input is in:
+# $_[0] = from element
+# $_[1] = to element
+# $_[2] = project
+# $_[3] = spec line
+#
+# output:
+# return success or failure
+sub CTCvsMv {
+    &CTUDebug( "in CTCvsMv\n" ) ;
+    local( $ret ) = 0 ;
+    if ( -d $_[0] ) {
+	# don't have code to do directories yet.  See pp 54 of the CVS book
+	$ret = 0 ;
+    } else {
+	$ret = &CTURetCode( system( "mv $_[0] $_[1]" ) ) ;
+	if ( $ret ) {
+	    $ret = &CTCvsRm( $_[0], $_[2], $_[3] ) ;
+	    if ( $ret ) {
+		$ret = &CTCvsAdd( $_[1], $_[2], $_[3] );
+		if ( $ret ) {
+		    $ret = &CTCvsCi( $_[0], $_[2], $_[3] ) ;
+		    if ( $ret ) {
+			$ret = &CTCvsCi( $_[1], $_[2], $_[3] ) ;
+		    }
+		}
+	    }
+	}
+    }
+    &CTUDebug( "out of CTCvsMv\n" ) ;
+    $ret ;
+}
+
+# build a list of targets
+# input is in:
+# $_[0] = targets
+#
+# output:
+# return success or failure
+sub CTCvsMake {
+    &CTUDebug( "in CTCvsMake\n" ) ;
+    local( $ret ) = 0 ;
+    local( $line ) = "make " . $_[0] . "\n" ;
+    $ret = &CTURetCode( system( $line )) ;
+    &CTUDebug( "out of CTCvsMake\n" ) ;
+    $ret ;
+}
+
+1;

+ 32 - 0
dtool/src/attach/ctdelta

@@ -0,0 +1,32 @@
+#!/usr/local/bin/perl
+
+if ($#ARGV < 0) {
+   exit print "Usage: ctdelta element-name [...]\n" ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+    die "not configured for using ct-tools\n" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+foreach $item ( @ARGV ) {
+    if ( -e $item ) {
+	&CTCMCheckin( $item, $projname, $spec ) ;
+	if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+	    print STDERR "Could not delta '$item'\n" ;
+	}
+    } else {
+	print STDERR "No such file '$item'.\n" ;
+    }
+}

+ 232 - 0
dtool/src/attach/ctdelta.pl

@@ -0,0 +1,232 @@
+# Check in element if needed
+# Input is:
+#   $_[0] = element name
+sub CTDeltaCheckin {
+   local( $cmd ) = "cleartool ci -nc $_[0] 2> /dev/null > /dev/null" ;
+   system $cmd ;
+}
+
+# get the version of an element
+# Input is:
+#   $_[0] = element name
+sub CTDeltaGetVersion {
+   local( *CMDFILE ) ;
+   open( CMDFILE, "cleartool describe -short $_[0] |" ) ;
+   $_ = <CMDFILE> ;
+   close( CMDFILE ) ;
+   s/\n$// ;
+   s/^.*@@// ;
+   s/\"$// ;
+   $_ ;
+}
+
+# Is it ok to try a merge on this version?
+# Input is:
+#   $_[0] = version
+sub CTDeltaOk {
+   local( $ret ) ;
+   local( @verlist ) ;
+   @verlist = split( /\//, $_[0] ) ;
+   pop( @verlist ) ;
+   if ( $#verlist > 1 ) {
+      $ret = 1 ;
+   } else {
+      $ret = 0 ;
+   }
+   $ret ;
+}
+
+# get the comments from a version of an element
+# Input is:
+#   $_[0] = element name
+#   $_[1] = version
+#
+# output in:
+#   @CTDeltaComments
+sub CTDeltaGetComments {
+   local( *CMDFILE ) ;
+   local( $done ) = 0 ;
+   local( $end ) = "  element type:" ;
+   local( $tmp ) = "cleartool describe $_[0]" . "@@" . "$_[1] |" ;
+   open( CMDFILE, $tmp ) ;
+   $_ = <CMDFILE> ;
+   $_ = <CMDFILE> ;
+   while ( ! $done ) {
+      $_ = <CMDFILE> ;
+      if ( $_ =~ /^$end/ ) {
+	 $done = 1 ;
+      } else {
+	 s/^  // ;
+	 s/^ // ;
+	 s/^\"// ;
+	 s/\n$// ;
+	 s/\"$// ;
+	 push( @CTDeltaComments, $_ ) ;
+      }
+   }
+   close( CMDFILE ) ;
+}
+
+# try automatic merge.  If it fails, use xmerge
+# Input is:
+#   $_[0] = element name
+#   $_[1] = source version
+#   $_[2] = target version
+sub CTDeltaSafeMerge {
+   @CTDeltaComments = ();
+   &CTDeltaGetComments($_[0], $_[1]);
+   local( $ret ) ;
+   $ret = "cleartool checkout -branch $_[2] -nc $_[0] 2> /dev/null > /dev/null" ;
+   $ret = system $ret ;
+   if ( $ret != 0 ) {
+      print STDERR "got return value $ret from checkout on '$_[0]" . "@@" . "$_[2]'\n" ;
+      exit -1;
+   }
+   local( $item ) ;
+   foreach $item ( @CTDeltaComments ) {
+      $ret = "cleartool chevent -append -c \"" . $item . "\" $_[0]" . "@@" . "$_[2]" . "/LATEST 2> /dev/null > /dev/null" ;
+      system $ret ;
+   }
+   print STDERR "merging '$_[0]'...\n" ;
+   $ret = "cleartool merge -abort -to $_[0] -version $_[1] 2> /dev/null > /dev/null" ;
+   $ret = system $ret ;
+   if ( $ret != 0 ) {
+      $ret = system "cleartool xmerge -to $_[0] -version $_[1]" ;
+   }
+   if ( ! -d $_[0] ) {
+      system "rm $_[0]" . ".contrib" ;
+   }
+   $ret ;
+}
+
+# test a branch for 'triviality'
+# Input is:
+#   $_[0] = element name
+#   $_[1] = branch name
+#
+# Output is:
+#   true/false
+sub CTDeltaTestBranch {
+   local( *CTCMD ) ;
+   local( $ret ) ;
+   local( $done ) = 0 ;
+   local( $bfrom ) ;
+   local( @blist ) ;
+   local( $bto ) ;
+   local( $bdiff ) ;
+   local( $blast ) ;
+   @blist = split( /\//, $_[1] ) ;
+   pop( @blist ) ;
+   $ret = join( "/", @blist ) ;
+   $ret = "cleartool describe $_[0]" . "@@" . "$ret |" ;
+   open( CTCMD, $ret ) ;
+   while ( ! $done ) {
+      $_ = <CTCMD> ;
+      if ( $_ =~ /^  branched from version/ ) {
+	 $done = 1 ;
+      }
+   }
+   close( CTCMD ) ;
+   s/^  branched from version: // ;
+   s/\n$// ;
+   $bfrom = $_ ;
+   @blist = split( /\//, $_ ) ;
+   pop( @blist ) ;
+   push( @blist, "LATEST" ) ;
+   $ret = join( "/", @blist ) ;
+   $ret = "cleartool describe $_[0]" . "@@" . "$ret |" ;
+   open( CTCMD, $ret ) ;
+   $_ = <CTCMD> ;
+   close( CTCMD ) ;
+   s/\n$// ;
+   s/^.*@@// ;
+   s/\"$// ;
+   $bto = $_ ;
+   @blist = split( /\//, $bfrom ) ;
+   $bfrom = pop( @blist ) ;
+   @blist = split( /\//, $bto ) ;
+   $bto = pop( @blist ) ;
+   $bdiff = $bto - $bfrom ;
+   $ret = "cleartool describe $_[0]" . "@@" . "$_[1] |" ;
+   open( CTCMD, $ret ) ;
+   $_ = <CTCMD> ;
+   close( CTCMD ) ;
+   s/\n$// ;
+   s/^.*@@// ;
+   s/\"$// ;
+   @blist = split( /\//, $_ ) ;
+   $blast = pop( @blist ) ;
+   if (( $bdiff > 1 ) || ( $blast > 1 )) {
+      $ret = 0 ;
+   } else {
+      $ret = 1 ;
+   }
+}
+
+# check for trivial branch elimination
+# Input is:
+#   $_[0] = element name
+#   $_[1] = last branch version
+#   $_[2] = timestamp string
+sub CTDeltaBranchCheck {
+   local( $test ) = &CTDeltaTestBranch( $_[0], $_[1] ) ;
+   local( $cmd ) ;
+   local( @blist ) ;
+   local( $branch ) ;
+   @blist = split( /\//, $_[1] ) ;
+   if ( $test ) {
+       pop( @blist ) ;
+       $cmd = join( "/", @blist ) ;
+       $branch = join( "/", @blist ) ;
+       $cmd = "cleartool rmbranch -force $_[0]" . "@@" . "$cmd 2> /dev/null > /dev/null" ;
+       print STDERR "deleting branch '$branch'...\n" ;
+       system $cmd ;
+   } else {
+       pop( @blist ) ;
+       $branch = join( "/", @blist ) ;
+       $test = pop( @blist ) ;
+       $test = $test . $_[2] ;
+       $cmd = "cleartool mkbrtype -c \"non-trivial branch\" $test 2> /dev/null > /dev/null" ;
+       system $cmd ;
+       $cmd = "cleartool chtype -c \"renaming non-trivial branch\" $test $_[0]" . "@@" . "$branch 2> /dev/null > /dev/null" ;
+       print STDERR "renaming branch '$branch'...\n" ;
+       system $cmd ;
+   }
+}
+
+# log merge to /usr/local/etc/delta_log
+# Input is:
+#   $_[0] = element name
+#   $_[1] = source version
+#   $_[2] = target version
+sub CTDeltaLog {
+   local( *LOGFILE ) ;
+   local( *CMDFILE ) ;
+   local( $cmd ) ;
+   open( LOGFILE, ">>/usr/local/etc/delta_log" ) ;
+   print LOGFILE $_[0] . ": " . $_[1] . " -> " . $_[2] . " : " ;
+   if ( $ctdebug ne "" ) {
+      print STDERR "CTDeltaLog: outputting '" . $_[0] . ": " . $_[1] . " -> " . $_[2] . " : '\n" ;
+   }
+   $cmd = "ypmatch `whoami` passwd | cut -d: -f5 |" ;
+   open( CMDFILE, $cmd ) ;
+   $_ = <CMDFILE> ;
+   s/\n$//;
+   print LOGFILE $_ . " " ;
+   if ( $ctdebug ne "" ) {
+      print STDERR "CTDeltaLog: outputting '" . $_ . " '\n" ;
+   }
+   close( CMDFILE ) ;
+   $cmd = "/bin/date '+%m/%d/%y %H:%M:%S' |" ;
+   open( CMDFILE, $cmd ) ;
+   $_ = <CMDFILE> ;
+   s/\n$//;
+   print LOGFILE $_ . "\n" ;
+   if ( $ctdebug ne "" ) {
+      print STDERR "CTDeltaLog: outputting '" . $_ . " '\n" ;
+   }
+   close( CMDFILE ) ;
+   close( LOGFILE ) ;
+}
+
+1;

+ 232 - 0
dtool/src/attach/ctdelta.pl.rnd

@@ -0,0 +1,232 @@
+# Check in element if needed
+# Input is:
+#   $_[0] = element name
+sub CTDeltaCheckin {
+   local( $cmd ) = "cleartool ci -nc $_[0] 2> /dev/null > /dev/null" ;
+   system $cmd ;
+}
+
+# get the version of an element
+# Input is:
+#   $_[0] = element name
+sub CTDeltaGetVersion {
+   local( *CMDFILE ) ;
+   open( CMDFILE, "cleartool describe -short $_[0] |" ) ;
+   $_ = <CMDFILE> ;
+   close( CMDFILE ) ;
+   s/\n$// ;
+   s/^.*@@// ;
+   s/\"$// ;
+   $_ ;
+}
+
+# Is it ok to try a merge on this version?
+# Input is:
+#   $_[0] = version
+sub CTDeltaOk {
+   local( $ret ) ;
+   local( @verlist ) ;
+   @verlist = split( /\//, $_[0] ) ;
+   pop( @verlist ) ;
+   if ( $#verlist > 1 ) {
+      $ret = 1 ;
+   } else {
+      $ret = 0 ;
+   }
+   $ret ;
+}
+
+# get the comments from a version of an element
+# Input is:
+#   $_[0] = element name
+#   $_[1] = version
+#
+# output in:
+#   @CTDeltaComments
+sub CTDeltaGetComments {
+   local( *CMDFILE ) ;
+   local( $done ) = 0 ;
+   local( $end ) = "  element type:" ;
+   local( $tmp ) = "cleartool describe $_[0]" . "@@" . "$_[1] |" ;
+   open( CMDFILE, $tmp ) ;
+   $_ = <CMDFILE> ;
+   $_ = <CMDFILE> ;
+   while ( ! $done ) {
+      $_ = <CMDFILE> ;
+      if ( $_ =~ /^$end/ ) {
+	 $done = 1 ;
+      } else {
+	 s/^  // ;
+	 s/^ // ;
+	 s/^\"// ;
+	 s/\n$// ;
+	 s/\"$// ;
+	 push( @CTDeltaComments, $_ ) ;
+      }
+   }
+   close( CMDFILE ) ;
+}
+
+# try automatic merge.  If it fails, use xmerge
+# Input is:
+#   $_[0] = element name
+#   $_[1] = source version
+#   $_[2] = target version
+sub CTDeltaSafeMerge {
+   @CTDeltaComments = ();
+   &CTDeltaGetComments($_[0], $_[1]);
+   local( $ret ) ;
+   $ret = "cleartool checkout -branch $_[2] -nc $_[0] 2> /dev/null > /dev/null" ;
+   $ret = system $ret ;
+   if ( $ret != 0 ) {
+      print STDERR "got return value $ret from checkout on '$_[0]" . "@@" . "$_[2]'\n" ;
+      exit -1;
+   }
+   local( $item ) ;
+   foreach $item ( @CTDeltaComments ) {
+      $ret = "cleartool chevent -append -c \"" . $item . "\" $_[0]" . "@@" . "$_[2]" . "/LATEST 2> /dev/null > /dev/null" ;
+      system $ret ;
+   }
+   print STDERR "merging '$_[0]'...\n" ;
+   $ret = "cleartool merge -abort -to $_[0] -version $_[1] 2> /dev/null > /dev/null" ;
+   $ret = system $ret ;
+   if ( $ret != 0 ) {
+      $ret = system "cleartool xmerge -to $_[0] -version $_[1]" ;
+   }
+   if ( ! -d $_[0] ) {
+      system "rm $_[0]" . ".contrib" ;
+   }
+   $ret ;
+}
+
+# test a branch for 'triviality'
+# Input is:
+#   $_[0] = element name
+#   $_[1] = branch name
+#
+# Output is:
+#   true/false
+sub CTDeltaTestBranch {
+   local( *CTCMD ) ;
+   local( $ret ) ;
+   local( $done ) = 0 ;
+   local( $bfrom ) ;
+   local( @blist ) ;
+   local( $bto ) ;
+   local( $bdiff ) ;
+   local( $blast ) ;
+   @blist = split( /\//, $_[1] ) ;
+   pop( @blist ) ;
+   $ret = join( "/", @blist ) ;
+   $ret = "cleartool describe $_[0]" . "@@" . "$ret |" ;
+   open( CTCMD, $ret ) ;
+   while ( ! $done ) {
+      $_ = <CTCMD> ;
+      if ( $_ =~ /^  branched from version/ ) {
+	 $done = 1 ;
+      }
+   }
+   close( CTCMD ) ;
+   s/^  branched from version: // ;
+   s/\n$// ;
+   $bfrom = $_ ;
+   @blist = split( /\//, $_ ) ;
+   pop( @blist ) ;
+   push( @blist, "LATEST" ) ;
+   $ret = join( "/", @blist ) ;
+   $ret = "cleartool describe $_[0]" . "@@" . "$ret |" ;
+   open( CTCMD, $ret ) ;
+   $_ = <CTCMD> ;
+   close( CTCMD ) ;
+   s/\n$// ;
+   s/^.*@@// ;
+   s/\"$// ;
+   $bto = $_ ;
+   @blist = split( /\//, $bfrom ) ;
+   $bfrom = pop( @blist ) ;
+   @blist = split( /\//, $bto ) ;
+   $bto = pop( @blist ) ;
+   $bdiff = $bto - $bfrom ;
+   $ret = "cleartool describe $_[0]" . "@@" . "$_[1] |" ;
+   open( CTCMD, $ret ) ;
+   $_ = <CTCMD> ;
+   close( CTCMD ) ;
+   s/\n$// ;
+   s/^.*@@// ;
+   s/\"$// ;
+   @blist = split( /\//, $_ ) ;
+   $blast = pop( @blist ) ;
+   if (( $bdiff > 1 ) || ( $blast > 1 )) {
+      $ret = 0 ;
+   } else {
+      $ret = 1 ;
+   }
+}
+
+# check for trivial branch elimination
+# Input is:
+#   $_[0] = element name
+#   $_[1] = last branch version
+#   $_[2] = timestamp string
+sub CTDeltaBranchCheck {
+   local( $test ) = &CTDeltaTestBranch( $_[0], $_[1] ) ;
+   local( $cmd ) ;
+   local( @blist ) ;
+   local( $branch ) ;
+   @blist = split( /\//, $_[1] ) ;
+   if ( $test ) {
+       pop( @blist ) ;
+       $cmd = join( "/", @blist ) ;
+       $branch = join( "/", @blist ) ;
+       $cmd = "cleartool rmbranch -force $_[0]" . "@@" . "$cmd 2> /dev/null > /dev/null" ;
+       print STDERR "deleting branch '$branch'...\n" ;
+       system $cmd ;
+   } else {
+       pop( @blist ) ;
+       $branch = join( "/", @blist ) ;
+       $test = pop( @blist ) ;
+       $test = $test . $_[2] ;
+       $cmd = "cleartool mkbrtype -c \"non-trivial branch\" $test 2> /dev/null > /dev/null" ;
+       system $cmd ;
+       $cmd = "cleartool chtype -c \"renaming non-trivial branch\" $test $_[0]" . "@@" . "$branch 2> /dev/null > /dev/null" ;
+       print STDERR "renaming branch '$branch'...\n" ;
+       system $cmd ;
+   }
+}
+
+# log merge to /var/etc/delta_log
+# Input is:
+#   $_[0] = element name
+#   $_[1] = source version
+#   $_[2] = target version
+sub CTDeltaLog {
+   local( *LOGFILE ) ;
+   local( *CMDFILE ) ;
+   local( $cmd ) ;
+   open( LOGFILE, ">>/var/etc/delta_log" ) ;
+   print LOGFILE $_[0] . ": " . $_[1] . " -> " . $_[2] . " : " ;
+   if ( $ctdebug ne "" ) {
+      print STDERR "CTDeltaLog: outputting '" . $_[0] . ": " . $_[1] . " -> " . $_[2] . " : '\n" ;
+   }
+   $cmd = "ypmatch `whoami` passwd | cut -d: -f5 |" ;
+   open( CMDFILE, $cmd ) ;
+   $_ = <CMDFILE> ;
+   s/\n$//;
+   print LOGFILE $_ . " " ;
+   if ( $ctdebug ne "" ) {
+      print STDERR "CTDeltaLog: outputting '" . $_ . " '\n" ;
+   }
+   close( CMDFILE ) ;
+   $cmd = "/bin/date '+%m/%d/%y %H:%M:%S' |" ;
+   open( CMDFILE, $cmd ) ;
+   $_ = <CMDFILE> ;
+   s/\n$//;
+   print LOGFILE $_ . "\n" ;
+   if ( $ctdebug ne "" ) {
+      print STDERR "CTDeltaLog: outputting '" . $_ . " '\n" ;
+   }
+   close( CMDFILE ) ;
+   close( LOGFILE ) ;
+}
+
+1;

+ 33 - 0
dtool/src/attach/ctihave

@@ -0,0 +1,33 @@
+#!/usr/local/bin/perl
+
+if ($#ARGV != -1) {
+   exit print "Usage: ctihave\n" ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "not configured for using CTtools\n" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+if ( $projname eq "" ) {
+   exit print "Not currently in any project tree\n" ;
+}
+
+$result = &CTCMIHave( $projname, $flav, $spec ) ;
+if ( $result ne "" ) {
+    @splitlist = split( /\n/, $result ) ;
+    foreach $item ( @splitlist ) {
+	print $item . "\n" ;
+    }
+}

+ 23 - 0
dtool/src/attach/ctmake

@@ -0,0 +1,23 @@
+#!/usr/local/bin/perl
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+    die "not configured for using ct-tools\n" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+$line = join( " ", @ARGV ) ;
+
+if ( ! &CTCMMake( $line, $projname, $spec ) ) {
+    print STDERR "Could not make '$line'\n" ;
+}

+ 55 - 0
dtool/src/attach/ctmkdir

@@ -0,0 +1,55 @@
+#!/usr/local/bin/perl
+
+sub CTMkDirUsage {
+    print STDERR "Usage: ctmkdir [-c \"comment\"] [-nc] dir-name [...]\n" ;
+    print STDERR "Options:\n" ;
+    print STDERR "  -c \"comment\" : provide a comment about this action\n" ;
+    print STDERR "  -nc : expect no comment on this action\n" ;
+    exit ;
+}
+
+if ( $#ARGV < 0 ) {
+    &CTMkDirUsage ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured for CTtools" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$comment = "" ;
+if ( $ARGV[0] eq "-nc" ) {
+    shift( @ARGV ) ;
+    &CTUDebug( "-nc processed\n" ) ;
+}
+if ( $ARGV[0] eq "-c" ) {
+    shift( @ARGV ) ;
+    $comment = $ARGV[0] ;
+    shift( @ARGV ) ;
+    &CTUDebug( "setting comment to '" . $comment . "'\n" ) ;
+}
+
+if ( $#ARGV < 0 ) {
+    &CTMkDirUsage ;
+}
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+foreach $item ( @ARGV ) {
+    if ( -e $item ) {
+	print STDERR "Name collision on directory '$item'\n" ;
+    } else {
+	if ( ! &CTCMMkdir( $item, $projname, $spec, $comment ) ) {
+	    print STDERR "Could name make directory '$item'\n" ;
+	}
+    }
+}

+ 78 - 0
dtool/src/attach/ctmkelem

@@ -0,0 +1,78 @@
+#!/usr/local/bin/perl
+
+sub CTMkElemUsage {
+    print STDERR "Usage: ctmkelem [-c \"comment\"] [-nc] [-eltype type] element-name [...]\n" ;
+    print STDERR "Options:\n" ;
+    print STDERR "  -c \"comment\" : provide a comment about this action\n" ;
+    print STDERR "  -nc : expect no comment on this action\n" ;
+    print STDERR "  -eltype type : element type\n" ;
+    exit ;
+}
+
+if ( $#ARGV < 0 ) {
+    &CTMkElemUsage ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured for CTtools" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$comment = "" ;
+$eltype = "" ;
+
+$done = 0 ;
+
+while ( ! $done ) {
+    $done = 1 ;
+    if ( $ARGV[0] eq "-nc" ) {
+	shift( @ARGV ) ;
+	&CTUDebug( "-nc processed\n" ) ;
+	$done = 0 ;
+    }
+    if ( $ARGV[0] eq "-c" ) {
+	shift( @ARGV ) ;
+	$comment = $ARGV[0] ;
+	shift( @ARGV ) ;
+	&CTUDebug( "setting comment to '" . $comment . "'\n" ) ;
+	$done = 0 ;
+    }
+    if ( $ARGV[0] eq "-eltype" ) {
+	shift( @ARGV ) ;
+	$eltype = $ARGV[0] ;
+	shift( @ARGV ) ;
+	&CTUDebug( "setting eltype to '" . $eltype . "'\n" ) ;
+	$done = 0 ;
+    }
+}
+
+if ( $#ARGV < 0 ) {
+    &CTMkElemUsage ;
+}
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+foreach $item ( @ARGV ) {
+    if ( -e $item ) {
+	if ( -d $item ) {
+	    print STDERR "Cannot mkelem on an existing directory." .
+		"  Ctmkdir it first.\n" ;
+	} else {
+	    if ( ! &CTCMMkelem( $item, $projname, $spec, $comment, $eltype )) {
+		print STDERR "Could not make a versioned element of '" .
+		    $item . "'\n" ;
+	    }
+	}
+    } else {
+	print STDERR "No such file '$item'.\n" ;
+    }
+}

+ 35 - 0
dtool/src/attach/ctmv

@@ -0,0 +1,35 @@
+#!/usr/local/bin/perl
+
+if ( $#ARGV != 1 ) {
+	exit print "Usage: ctmv from-element to-element\n" ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured for CTtools" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+$from = $ARGV[0] ;
+$to = $ARGV[1] ;
+
+if ( -e $from ) {
+    if ( -e $to ) {
+	print STDERR "'$to' already exists.\n" ;
+    } else {
+	if ( ! &CTCMMv( $from, $to, $projname, $spec ) ) {
+	}
+    }
+} else {
+    print STDERR "No such element '$from'.\n" ;
+}

+ 258 - 0
dtool/src/attach/ctntool.pl

@@ -0,0 +1,258 @@
+# given a possibly empty string, format it into a comment or -nc
+# input is in:
+# $_[0] = possible comment string
+#
+# output is:
+# string for use by neartool functions
+sub CTNtoolFormatComment {
+    local( $ret ) = "" ;
+    if ( $_[0] eq "" ) {
+	$ret = "-nc" ;
+    } else {
+	$ret = "-c " . $_[0] ;
+    }
+    $ret ;
+}
+
+# make a versioned directory
+# input is in:
+# $_[0] = directory to create
+# $_[1] = curr dir
+# $_[2] = possible comment
+#
+# output:
+# return success or failure
+sub CTNtoolMkdir {
+    &CTUDebug( "in CTNtoolMkdir\n" ) ;
+    local( $ret ) = 0 ;
+    local( $dir ) = $_[0] ;
+    if ( ! ( $dir =~ /^\// )) {
+	$dir = $_[1] . "/" . $dir ;
+    }
+    local( $comment ) = &CTNtoolFormatComment( $_[2] ) ;
+    # first we have to check out the parent directory
+    local( @alist ) = split( /\//, $dir ) ;
+    pop( @alist ) ;
+    local( $parent ) = join( "/", @alist ) ;
+    &CTUDebug( "parent directory of '" . $dir . "' is '" . $parent . "'\n" ) ;
+    $ret = system( "neartool co -nc $parent\n" ) ;
+    if ( $ret == 0 ) {
+	# now make the dir
+	$ret = &CTURetCode( system( "neartool mkdir " . $comment .
+				    " $dir\n" )) ;
+    } else {
+	$ret = 0 ;
+    }
+    &CTUDebug( "out of CTNtoolMkdir\n" ) ;
+    $ret ;
+}
+
+# make a versioned element
+# input is in:
+# $_[0] = element to version
+# $_[1] = curr dir
+# $_[2] = possible comment
+# $_[3] = possible eltype
+#
+# output:
+# return success or failure
+sub CTNtoolMkelem {
+    &CTUDebug( "in CTNtoolMkelem\n" ) ;
+    local( $ret ) = 0 ;
+    local( $elem ) = $_[0] ;
+    if ( ! ( $elem =~ /^\// )) {
+	$elem = $_[1] . "/" . $elem ;
+    }
+    local( $comment ) = &CTNtoolFormatComment( $_[2] ) ;
+    local( $eltype ) = $_[3] ;
+    if ( $eltype ne "" ) {
+	$eltype = "-eltype " . $eltype ;
+    }
+    local( $line ) = "neartool mkelem " . $comment . " " . $eltype . " " .
+	$elem . "\n" ;
+    &CTUDebug( $line ) ;
+    $ret = &CTURetCode( system( $line )) ;
+    &CTUDebug( "out of CTNtoolMkelem\n" ) ;
+    $ret ;
+}
+
+# delta an element
+# input is in:
+# $_[0] = element to delta
+#
+# output:
+# return success or failure
+sub CTNtoolDelta {
+    &CTUDebug( "in CTNtoolDelta\n" ) ;
+    local( $ret ) = 0 ;
+    # as Dave points out, when working off-line, delta is the same as checkin
+    $ret = &CTURetCode( system( "neartool ci " . $_[0] )) ;
+    &CTUDebug( "out of CTNtoolDelta\n" ) ;
+    $ret ;
+}
+
+# checkout an element
+# input is in:
+# $_[0] = element to checkout
+# $_[1] = possible comment
+#
+# output:
+# return success or failure
+sub CTNtoolCheckout {
+    &CTUDebug( "in CTNtoolCheckout\n" ) ;
+    local( $ret ) = 0 ;
+    local( $comment ) = &CTNtoolFormatComment( $_[1] ) ;
+    if ( ! -d $_[0] ) {
+	$ret = &CTURetCode( system( "neartool co " . $comment . " " .
+				    $_[0] )) ;
+    } else {
+	# neartool doesn't do anything about checking out directories
+	$ret = 1 ;
+    }
+    &CTUDebug( "out of CTNtoolCheckout\n" ) ;
+    $ret ;
+}
+
+# checkin an element
+# input is in:
+# $_[0] = element to checkin
+# $_[1] = possible comment
+#
+# output:
+# return success or failure
+sub CTNtoolCheckin {
+    &CTUDebug( "in CTNtoolCheckin\n" ) ;
+    local( $ret ) = 0 ;
+    local( $comment ) = &CTNtoolFormatComment( $_[1] ) ;
+    $ret = &CTURetCode( system( "neartool ci " . $comment . " " . $_[0] )) ;
+    &CTUDebug( "out of CTNtoolCheckin\n" ) ;
+    $ret ;
+}
+
+# uncheckout an element
+# input is in:
+# $_[0] = element to uncheckout
+#
+# output:
+# return success or failure
+sub CTNtoolUncheckout {
+    &CTUDebug( "in CTNtoolUncheckout\n" ) ;
+    local( $ret ) = 0 ;
+    $ret = &CTURetCode( system( "neartool unco " . $_[0] )) ;
+    &CTUDebug( "out of CTNtoolUncheckout\n" ) ;
+    $ret ;
+}
+
+# figure out what all I have checked out
+# input is in:
+# $_[0] = project
+# $_[1] = flavor
+# $_[2] = spec line
+#
+# output:
+# return a \n serperated list of elements checked out
+sub CTNtoolIHave {
+    &CTUDebug( "in CTNtoolIHave\n" ) ;
+    local( $ret ) = "" ;
+    local( $root ) = &CTProjRoot( $_[0] ) ;
+    local( *OUTPUT ) ;
+    open( OUTPUT, "neartool find " . $root . " |" ) ;
+    while ( <OUTPUT> ) {
+	$ret = $ret . $_ ;
+    }
+    close( OUTPUT ) ;
+    &CTUDebug( "out of CTNToolIHave\n" ) ;
+    $ret ;
+}
+
+# remove a versioned element
+# input is in:
+# $_[0] = element to remove
+# $_[1] = curr dir
+#
+# output:
+# return success or failure
+sub CTNtoolRmElem {
+    &CTUDebug( "in CTNtoolRmElem\n" ) ;
+    local( $ret ) = 0 ;
+    local( $elem ) = $_[0] ;
+    if ( ! ( $elem =~ /^\// )) {
+	$elem = $_[1] . "/" . $elem ;
+    }
+    # first we have to check out the parent directory
+    local( @alist ) = split( /\//, $elem ) ;
+    pop( @alist ) ;
+    local( $parent ) = join( "/", @alist ) ;
+    &CTUDebug( "parent directory of '" . $elem . "' is '" . $parent . "'\n" ) ;
+    $ret = system( "neartool co -nc $parent\n" ) ;
+    if ( $ret == 0 ) {
+	# now nuke the element
+	$ret = &CTURetCode( system( "neartool rmname $elem\n" )) ;
+    } else {
+	$ret = 0 ;
+    }
+    &CTUDebug( "out of CTNtoolRmElem\n" ) ;
+    $ret ;
+}
+
+# mv a versioned element from one name to another
+# input is in:
+# $_[0] = from element
+# $_[1] = to element
+# $_[2] = current directory
+#
+# output:
+# return success or failure
+sub CTCcaseMv {
+    &CTUDebug( "in CTNtoolMv\n" ) ;
+    local( $ret ) = 0 ;
+    local( $elem ) = $_[0] ;
+    if ( ! ( $elem =~ /^\// )) {
+	$elem = $_[2] . "/" . $elem ;
+    }
+    # first we have to check out the parent directory
+    local( @alist ) = split( /\//, $elem ) ;
+    pop( @alist ) ;
+    local( $parent ) = join( "/", @alist ) ;
+    &CTUDebug( "parent directory of '" . $elem . "' is '" . $parent . "'\n" ) ;
+    local( $elem2 ) = $_[1] ;
+    if ( ! ( $elem2 =~ /^\// )) {
+	$elem2 = $_[2] . "/" . $elem2 ;
+    }
+    @alist = split( /\//, $elem2 ) ;
+    pop( @alist ) ;
+    local( $parent2 ) = join( "/", @alist ) ;
+    &CTUDebug( "parent directory of '" . $elem2 . "' is '" . $parent2 .
+	       "'\n" ) ;
+    $ret = system( "neartool co -nc $parent\n" ) ;
+    if ( $ret == 0 ) {
+	$ret = system( "neartool co -nc $parent2\n" ) ;
+	if ( $ret == 0 ) {
+	    # now move the element
+	    $ret = &CTURetCode( system( "neartool mv $elem $elem2\n" )) ;
+	} else {
+	    $ret = 0 ;
+	}
+    } else {
+	$ret = 0 ;
+    }
+    &CTUDebug( "out of CTNtoolMv\n" ) ;
+    $ret ;
+}
+
+# build a list of targets
+# input is in:
+# $_[0] = targets
+#
+# output:
+# return success or failure
+sub CTNtoolMake {
+    &CTUDebug( "in CTNtoolMake\n" ) ;
+    local( $ret ) = 0 ;
+    local( $line ) = "make " . $_[0] . "\n" ;
+    $ret = &CTURetCode( system( $line )) ;
+    &CTUDebug( "out of CTNtoolMake\n" ) ;
+    $ret ;
+}
+
+1;

+ 42 - 0
dtool/src/attach/ctquery

@@ -0,0 +1,42 @@
+#!/usr/local/bin/perl
+
+# acceptable forms:
+#    ctquery            - list all attached projects and flavors
+#    ctquery project    - list the attached flavor of the named project
+#    ctquery - flavor   - list all attached projects who are attached with a
+#                         given flavor
+
+$projs = $ENV{"CTPROJS"} ;
+@projlist = split( / +/, $projs ) ;
+
+if ( $#ARGV == -1 ) {
+   # list all projects and flavors
+   print "Currently attached projects (and flavors):\n" ;
+   foreach $pair ( @projlist ) {
+      @pairlist = split( /:/, $pair ) ;
+      ( $pairtmp = $pairlist[0] ) =~ tr/A-Z/a-z/ ;
+      print "   $pairtmp ($pairlist[1])\n" ;
+   }
+} elsif (( $#ARGV == 0 ) && !($ARGV[0] =~ /^\-/)) {
+   # list the attached flavor of the named project
+   foreach $pair ( @projlist ) {
+      @pairlist = split( /:/, $pair ) ;
+      ( $pairtmp = $pairlist[0] ) =~ tr/A-Z/a-z/ ;
+      if ( $pairtmp eq $ARGV[0] ) {
+	 print "$pairlist[1]\n" ;
+      }
+   }
+} elsif (( $#ARGV == 1 ) && ( $ARGV[0] eq "-" )){
+   # list all attached projects who are attached with a given flavor
+   foreach $pair ( @projlist ) {
+      @pairlist = split( /:/, $pair ) ;
+      if ( $pairlist[1] eq $ARGV[1] ) {
+	 $pairlist[0] =~ tr/A-Z/a-z/ ;
+	 print "$pairlist[0]\n" ;
+      }
+   }
+} else {
+   print "Usage: ctquery [project]  -or-\n" ;
+   print "       ctquery - flavor\n" ;
+   exit ;
+}

+ 37 - 0
dtool/src/attach/ctquery.pl

@@ -0,0 +1,37 @@
+# return the attached flavor of given project (or empty string)
+sub CTQueryProj {
+   local( $projs ) = $ENV{"CTPROJS"} ;
+   local( @projlist ) ;
+   @projlist = split( / +/, $projs ) ;
+   local( $pair ) ;
+   local( @pairlist ) ;
+   local( $ret ) = "" ;
+   foreach $pair ( @projlist ) {
+      @pairlist = split( /:/, $pair ) ;
+      $pairlist[0] =~ tr/A-Z/a-z/ ;
+      if ( $pairlist[0] eq $_[0] ) {
+	 $ret = $pairlist[1] ;
+      }
+   }
+   $ret ;
+}
+
+# return all projects attached with a given flavor
+sub CTQueryFlav {
+   local( $projs ) = $ENV{"CTPROJS"} ;
+   local( @projlist ) ;
+   @projlist = split( / +/, $projs ) ;
+   local( $pair ) ;
+   local( @pairlist ) ;
+   local( $ret ) = "" ;
+   foreach $pair ( @projlist ) {
+      @pairlist = split( /:/, $pair ) ;
+      if ( $pairlist[1] eq $_[0] ) {
+	 $pairlist[0] =~ tr/A-Z/a-z/ ;
+	 $ret = $ret . " $pairlist[0]" ;
+      }
+   }
+   $ret ;
+}
+
+1;

+ 31 - 0
dtool/src/attach/ctrm

@@ -0,0 +1,31 @@
+#!/usr/local/bin/perl
+
+if ( $#ARGV < 0 ) {
+	exit print "Usage: ctrmelem element-name [...]\n" ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured for CTtools" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+foreach $item ( @ARGV ) {
+    if ( -e $item ) {
+	if ( ! &CTCMRmElem( $item, $projname, $spec ) ) {
+	    print STDERR "Could not rmname '$item'\n" ;
+	}
+    } else {
+	print STDERR "No such file '$item'.\n" ;
+    }
+}

+ 43 - 0
dtool/src/attach/ctsanity

@@ -0,0 +1,43 @@
+#!/usr/local/bin/perl
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+    die "Environment not configured to run CTtools" ;
+}
+
+sub CTSanityUsage {
+    print STDERR "Usage: ctsanity [-v]\n" ;
+    print STDERR "Options:\n" ;
+    print STDERR "  -v : sanity check the .vspec files \n" ;
+    exit ;
+}
+
+if ( $#ARGV == -1 ) {
+    &CTSanityUsage ;
+}
+
+$check_vspecs = 0 ;
+
+foreach $item ( @ARGV ) {
+    if ( $item eq "-v" ) {
+	$check_vspecs = 1 ;
+    } else {
+	print STDERR "unknown option '" . $item . "'\n" ;
+	$CTSanityUsage ;
+    }
+}
+
+require "$tool/inc/ctvspec.pl" ;
+
+if ( $check_vspecs ) {
+    local( $projs ) = &CTListAllProjects ;
+    local( @projlist ) = split( / +/, $projs ) ;
+    local( $item ) ;
+    foreach $item ( @projlist ) {
+	print STDERR "checking " . $item . ".vspec:\n" ;
+	local( $ctsavedebug ) = $ctdebug ;
+	$ctdebug = 1 ;
+	&CTReadVSpec( $item ) ;
+	$ctdebug = $ctsavedebug ;
+    }
+}

+ 43 - 0
dtool/src/attach/cttimewarp

@@ -0,0 +1,43 @@
+#!/usr/local/bin/perl
+
+if ($#ARGV < 0) {
+    exit print "Usage: cttimewarp [-clear] label [time]\n" ;
+}
+
+@arglist = @ARGV ;
+
+$clear = 0 ;
+
+if ( $arglist[0] =~ /^-c/ ) {
+    $clear = 1 ;
+    shift( @arglist ) ;
+}
+
+if ( @arglist == () ) {
+    if ( $clear ) {
+	exit print "Usage: cttimewarp -clear label\n" ;
+    } else {
+	exit print "Usage: cttimewarp label time\n" ;
+    }
+}
+
+$label = $arglist[0] ;
+shift( @arglist ) ;
+
+if (( ! $clear ) && ( @arglist == () )) {
+    exit print "Usage: cttimewarp label time\n" ;
+}
+
+$time = $arglist[0] ;
+
+if ( $clear ) {
+    $cmd = "cleartool find . -version \"lbtype(" . $label .
+           ")\" -exec 'cleartool rmlabel -c \"untimewarping\" " . $label .
+           ' $CLEARCASE_XPN' . "'\n" ;
+    system( $cmd ) ;
+} else {
+    $cmd = "cleartool mklabel -replace -recurse -c \"rolling time back to " .
+           $time . "\" -version /main/'{\!created_since(" . $time . ")}' " .
+           $label . " .\n" ;
+    system( $cmd ) ;
+}

+ 48 - 0
dtool/src/attach/ctunattach.drv

@@ -0,0 +1,48 @@
+#!/usr/local/bin/perl
+
+# acceptable forms:
+#   ctunattach project      - attach to the personal flavor of the project
+
+sub CTUnattachUsage {
+   print STDERR "Usage: ctattach project(s)\n" ;
+   &CTAttachWriteNullScript( $tmpname ) ;
+   print $tmpname . "\n" ;
+   exit;
+}
+
+$tool = $ENV{"DTOOL"} ;
+
+require "$tool/inc/ctattch.pl" ;
+require "$tool/inc/ctunattach.pl" ;
+require "$tool/inc/ctquery.pl" ;
+
+$tmpname = "/tmp/script.$$" ;
+
+if ( $#ARGV == -1 ) {
+   &CTUnattachUsage ;
+}
+
+foreach $proj ( @ARGV ) {
+   &CTUDebug( "project is '$proj'\n" ) ;
+
+   $curflav = &CTQueryProj( $proj ) ;
+   if ( $curflav ne "" ) {
+      $envsep{"PATH"} = ":" ;
+      $envsep{"LD_LIBRARY_PATH"} = ":" ;
+      $envsep{"PFPATH"} = ":" ;
+      $envsep{"SSPATH"} = ":" ;
+      $envsep{"STKPATH"} = ":" ;
+      $envsep{"DC_PATH"} = ":" ;
+      $spec = &CTUnattachCompute( $proj, $curflav ) ;
+      if ( $spec eq "" ) {
+	 &CTAttachWriteNullScript( $tmpname ) ;
+	 print $tmpname . "\n" ;
+      } else {
+	 &CTUnattachWriteScript( $tmpname ) ;
+	 print $tmpname . "\n" ;
+      }
+   } else {
+      &CTAttachWriteNullScript( $tmpname ) ;
+      print $tmpname . "\n" ;
+   }
+}

+ 250 - 0
dtool/src/attach/ctunattach.pl

@@ -0,0 +1,250 @@
+require "$tool/inc/ctquery.pl" ;
+
+$shell_type = "csh" ;
+if ( $ENV{"SHELL_TYPE"} ne "" ) {
+    if ( $ENV{"SHELL_TYPE"} eq "sh" ) {
+	$shell_type = "sh" ;
+    }
+}
+
+# remove a value from a variable.  If it is the only thing remaining in the
+# variable, add it to the unset list.
+# input is in:
+# $_[0] = variable
+# $_[1] = value
+#
+# output is in:
+# %newenv = an image of how we want the environment to be
+# @unset = a list of variables to unset
+sub CTUnattachMod {
+    &CTUDebug( "in CTUnattachMod\n" ) ;
+    local( $done ) = 0 ;
+    # if we didn't get any data, nothing really to do
+    if ( $_[0] eq "" ) { $done = 1 ; }
+    if ( $_[1] eq "" ) { $done = 1 ; }
+    # if the variable is already set to be unset, nothing really to do
+    if ( join( " ", @unset ) =~ /$_[0]/ ) { $done = 1 ; }
+    # if the variable isn't in newenv, move it there, if it's empty mark it
+    # for unsetting
+    if ( $newenv{$_[0]} eq "" ) {
+	$newenv{$_[0]} = &CTSpoolEnv( $_[0] ) ;
+	if ( $newenv{$_[0]} eq "" ) {
+	    push( @unset, $_[0] ) ;
+	    delete $newenv{$_[0]} ;
+	    $done = 1 ;
+	}
+    }
+    # if the value does not appear in the variable, nothing really to do
+    if ( ! ( $newenv{$_[0]} =~ /$_[1]/ ) ) { $done = 1 ; }
+    # now down to the real work
+    if ( ! $done ) {
+	# if the variable is exactly the value, mark it for unsetting
+	if ( $newenv{$_[0]} eq $_[1] ) {
+	    push( @unset, $_[0] ) ;
+	    delete $newenv{$_[0]} ;
+	} elsif ( $newenv{$_[0]} =~ / $_[1]/ ) {
+	    local( $tmp ) = $newenv{$_[0]} ;
+	    $tmp =~ s/ $_[1]// ;
+	    $newenv{$_[0]} = $tmp ;
+	} elsif ( $newenv{$_[0]} =~ /$_[1] / ) {
+	    local( $tmp ) = $newenv{$_[0]} ;
+	    $tmp =~ s/$_[1] // ;
+	    $newenv{$_[0]} = $tmp ;
+	} else {
+	    print STDERR "ERROR: variable '" . $_[0] . "' contains '" .
+		$_[1] . "' (in '" . $newenv{$_[0]} .
+	        "'), but I am too stupid to figure out how to remove it.\n" ;
+	}
+    }
+}
+
+# given the project and flavor, build the lists of variables to set/modify
+# input is in:
+# $_[0] = project
+# $_[1] = flavor
+#
+# output is in:
+# return value is config line
+# %newenv      = an image of what we want the environment to look like
+# @unset       = list of variables to be unset
+# %envsep      = seperator
+# %envcmd      = set or setenv
+# %envpostpend = flag that variable should be postpended
+sub CTUnattachCompute {
+   &CTUDebug( "in CTUnattachCompute\n" ) ;
+   local( $flav ) = $_[1] ;
+   local( $spec ) = &CTResolveSpec( $_[0], $flav ) ;
+   local( $root ) = &CTComputeRoot( $_[0], $flav, $spec ) ;
+
+   if ( $spec ne "" ) {
+      local( $proj ) = $_[0] ;
+      $proj =~ tr/a-z/A-Z/ ;
+      local( $item ) ;
+
+      # since we don't have to worry about sub-attaches, it doesn't matter
+      # if we scan the .init file first or not.  So we won't.
+      &CTUDebug( "extending paths\n" ) ;
+
+      $item = $root . "/bin" ;
+      &CTUnattachMod( "PATH", $item ) ;
+      $item = $root . "/lib" ;
+      if ( $ENV{"PENV"} eq "WIN32" ) {
+	  &CTUnattachMod( "PATH", $item ) ;
+      }
+      &CTUnattachMod( "LD_LIBRARY_PATH", $item ) ;
+      $item = $root . "/src/all" ;
+      &CTUnattachMod( "CDPATH", $item ) ;
+      $item = $root . "/inc" ;
+      &CTUnattachMod( "CT_INCLUDE_PATH", $item ) ;
+      $item = $root . "/etc" ;
+      &CTUnattachMod( "ETC_PATH", $item ) ;
+      $item = $proj . ":" . $flav ;
+      &CTUnattachMod( "CTPROJS", $item ) ;
+      push( @unset, $proj ) ;
+
+      if ( -e "$root/etc/$_[0].init" ) {
+	 &CTUDebug( "scanning $_[0].init file\n" ) ;
+	 local( @linesplit ) ;
+	 local( $linetmp ) ;
+	 local( $loop );
+	 local( *INITFILE ) ;
+	 if ( -x "$root/etc/$_[0].init" ) {
+	    open( INITFILE, "$root/etc/$_[0].init $_[0] $_[1] $root |" ) ;
+	 } else {
+	    open( INITFILE, "< $root/etc/$_[0].init" ) ;
+	 }
+	 while ( <INITFILE> ) {
+	    s/\n$// ;
+	    @linesplit = split( /\#/ ) ;
+	    $_ = $linesplit[0] ;
+	    if ( $_ =~ /^MODABS/ ) {
+	       @linesplit = split ;
+	       $linetmp = $linesplit[1] ;
+	       shift( @linesplit ) ;
+	       shift( @linesplit ) ;
+	       foreach $loop ( @linesplit ) {
+		   &CTUnattachMod( $linetmp, $loop ) ;
+	       }
+	    } elsif ( $_ =~ /^MODREL/ ) {
+	       @linesplit = split ;
+	       $linetmp = $linesplit[1] ;
+	       shift( @linesplit ) ;
+	       shift( @linesplit ) ;
+	       foreach $loop ( @linesplit ) {
+		   &CTUnattachMod( $linetmp, $root . "/" . $loop ) ;
+	       }
+	    } elsif ( $_ =~ /^SETABS/ ) {
+	       @linesplit = split ;
+	       $linetmp = $linesplit[1] ;
+	       push( @unset, $linetmp ) ;
+	    } elsif ( $_ =~ /^SETREL/ ) {
+	       @linesplit = split ;
+	       $linetmp = $linesplit[1] ;
+	       push( @unset, $linetmp ) ;
+	    } elsif ( $_ =~ /^SEP/ ) {
+	       @linesplit = split ;
+	       $envsep{$linesplit[1]} = $linesplit[2] ;
+	    } elsif ( $_ =~ /^CMD/ ) {
+	       @linesplit = split ;
+	       $envcmd{$linesplit[1]} = $linesplit[2] ;
+	    } elsif ( $_ =~ /^DOCSH/ ) {
+	       &CTUDebug( "ignoring DO command in .init file\n" ) ;
+	    } elsif ( $_ =~ /^DOSH/ ) {
+	       &CTUDebug( "ignoring DO command in .init file\n" ) ;
+	    } elsif ( $_ =~ /^DO/ ) {
+	       &CTUDebug( "ignoring DO command in .init file\n" ) ;
+	    } elsif ( $_ =~ /^POSTPEND/ ) {
+	       @linesplit = split ;
+	       $envpospend{$linesplit[1]} = 1 ;
+	    } elsif ( $_ =~ /^ATTACH/ ) {
+	       &CTUDebug( "ignoring ATTACH command in .init file\n" ) ;
+	    } else {
+	       print STDERR "Unknown .init directive '$_'\n" ;
+	    }
+	 }
+	 close( INITFILE ) ;
+      }
+   }
+   &CTUDebug( "out of CTUnattachCompute\n" ) ;
+   $spec ;
+}
+
+# write a script to setup the environment
+# Input is:
+# $_[0] = filename
+sub CTUnattachWriteScript {
+   &CTUDebug( "in CTAttachWriteScript\n" ) ;
+   local( *OUTFILE ) ;
+   open( OUTFILE, ">$_[0]" ) ;
+   print OUTFILE "#!/bin/" . $shell_type . " -f\n" ;
+   local( $item ) ;
+   local( $unsetcdpath ) = 0 ;
+   local( $modcdpath ) = 0 ;
+
+   foreach $item ( @unset ) {
+       if ( $item eq "CDPATH" ) { $unsetcdpath = 1 ; }
+
+       if ( $shell_type eq "sh" ) {
+	   print OUTFILE "$item=\n" ;
+	   if ( $envcmd{$item} ne "set" ) {
+	       print OUTFILE "export $item\n" ;
+	   }
+       } else {
+	   if ( $envcmd{$item} ne "" ) {
+	       print OUTFILE "un" . $envcmd{$item} . " $item\n" ;
+	   } else {
+	       print OUTFILE "unsetenv $item\n" ;
+	   }
+       }
+   }
+   foreach $item ( keys %newenv ) {
+       if ( $item eq "CDPATH" ) { $modcdpath = 1 ; }
+
+       local( $sep ) = " " ;
+       if ( $envsep{$item} ne "" ) {
+	   $sep = $envsep{$item} ;
+       }
+       local( @splitlist ) = split( / +/, $newenv{$item} ) ;
+       local( $outval ) = join( $sep, @splitlist ) ;
+
+       if ( $shell_type eq "sh" ) {
+	   print OUTFILE "$item=\"" . $outval . "\"\n" ;
+	   if ( $envcmd{$item} ne "set" ) {
+	       print OUTFILE "export $item\n" ;
+	   }
+       } else {
+	   if ( $envcmd{$item} ne "" ) {
+	       PRINT OUTFILE $envcmd{$item} . " $item " ;
+	       if ( $envcmd{$item} eq "set" ) {
+		   print OUTFILE " = ( " ;
+	       }
+	       print OUTFILE $outval ;
+	       if ( $envcmd{$item} eq "set" ) {
+		   print OUTFILE ")" ;
+	       }
+	       print OUTFILE "\n" ;
+	   } else {
+	       print OUTFILE "setenv $item \"$outval\"\n" ;
+	   }
+       }
+   }
+   if ( $unsetcdpath ) {
+       if ( $shell_type ne "sh" ) {
+	   print OUTFILE "unset cdpath\n" ;
+       }
+   } elsif ( $modcdpath ) {
+       if ( $shell_type ne "sh" ) {
+	   print OUTFILE "set cdpath = ( \$" . "CDPATH )\n" ;
+       }
+   }
+
+   if (! $ctdebug) {
+      print OUTFILE "rm -f $_[0]\n" ;
+   } else {
+      print STDERR "no self-destruct script '" . $_[0] . "'\n" ;
+   }
+   close( OUTFILE ) ;
+   &CTUDebug( "out of CTUnattachWriteScript\n" ) ;
+}
+
+1;

+ 31 - 0
dtool/src/attach/ctunco

@@ -0,0 +1,31 @@
+#!/usr/local/bin/perl
+
+if ( $#ARGV < 0 ) {
+    exit print "Usage ctunco element-name [...]\n" ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+    die "not configured for using CTtools" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctcm.pl" ;
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+foreach $item ( @ARGV ) {
+    if ( -e $item ) {
+	if ( ! &CTCMUncheckout( $item, $projname, $spec ) ) {
+	    print STDERR "Could not uncheckout '$item'\n" ;
+	}
+    } else {
+	print STDERR "No such file '$item'.\n" ;
+    }
+}

+ 359 - 0
dtool/src/attach/ctvspec.pl

@@ -0,0 +1,359 @@
+require "$tool/inc/ctutils.pl" ;
+
+# read a .vspec file into a map
+# $_[0] = project
+# on exit $ctvspecs{} will contain the data
+#
+# vspec format:
+#   tag:type:other data
+#
+#   type: ref, root, vroot, croot
+#   other data:
+#     ref: name=_____ - required, take to refference
+#     root: path=_____ - required, path of tree root
+#     vroot: name=_____ - optional, name of view to use (if not tag)
+#     croot: path=_____ - required, local path of tree root
+#            server=_____ - required, CVS server string, ',' for ':'
+
+sub CTReadVSpec {
+    &CTUDebug( "reading vspec file for project " . $_[0] . "\n" ) ;
+    local( $ret ) = "" ;
+    local( $thisproj ) = $_[0] ;
+    if ( -e "$ctvspec_path/$thisproj.vspec" ) {
+	%ctvspecs = () ;
+	local( *SPECFILE ) ;
+	open( SPECFILE, "<$ctvspec_path/$thisproj.vspec" ) ;
+	local( @partlist ) ;
+	while ( $_ = <SPECFILE> ) {
+	    s/\n$// ;
+	    @partlist = split( /\#/ ) ;
+	    $_ = $partlist[0] ;
+	    if ( $_ ne "" ) {
+		@partlist = split( /:/ );
+		local( $tag ) = $partlist[0] ;
+		shift( @partlist ) ;
+		local( $spec ) = join( ":", @partlist ) ;
+		if ( &CTValidateSpec( $spec ) ) {
+		    $ctvspecs{$tag} = $spec ;
+		    if ( $ctdebug ) {
+			print STDERR "tag(" . $tag . ") = " . $spec . "\n" ;
+		    }
+		}
+	    }
+	}
+	close( SPECFILE ) ;
+	$ctvspec_read = $_[0] ;
+    } else {
+	print STDERR "CTReadVSpec: cannot locate '$ctvspec_path/$thisproj.vspec'\n" ;
+    }
+}
+
+# given a spec line return it's type
+# $_[0] = spec line
+
+sub CTSpecType {
+    local( @speclist ) = split( /:/, $_[0] ) ;
+    $speclist[0] ;
+}
+
+# given a spec line return it's options if any
+# $_[0] = spec line
+
+sub CTSpecOptions {
+    local( @speclist ) = split( /:/, $_[0] ) ;
+    shift( @speclist ) ;
+    join( ":", @speclist ) ;
+}
+
+# given the options part of a spec line, find a given option
+# $_[0] = options line
+# $_[1] = desired option
+
+sub CTSpecFindOption {
+    local( $ret ) = "" ;
+    local( @options ) = split( /:/, $_[0] ) ;
+    local( $item ) ;
+    local( @itemlist ) ;
+    foreach $item ( @options ) {
+	@itemlist = split( /=/, $item ) ;
+	if ( $itemlist[0] eq $_[1] ) {
+	    $ret = $itemlist[1] ;
+	}
+    }
+    $ret ;
+}
+
+# resolve a final spec line for a given flavor
+# $_[0] = project
+# $_[1] = flavor
+
+sub CTResolveSpec {
+    &CTUDebug( "in CTResolveSpec\n" ) ;
+    local( $proj ) = $_[0] ;
+    $proj =~ tr/A-Z/a-z/ ;
+    if ( $ctvspec_read ne $proj ) {
+	&CTReadVSpec( $proj ) ;
+    }
+    local( $spec ) = $ctvspecs{$_[1]} ;
+    local( $ret ) = "" ;
+    if ( $spec ne "" ) {
+	local( $type ) = &CTSpecType( $spec ) ;
+	local( @speclist ) = split( /:/, &CTSpecOptions( $spec ) ) ;
+	if ( $type eq "ref" ) {
+	    local( @optionlist ) = split( /=/, $speclist[0] ) ;
+	    if ( $optionlist[0] ne "name" ) {
+		print STDERR "bad data attached to flavor " . $_[1] .
+		    " of project " . $proj . "\n" ;
+	    } else {
+		local( $tmp ) = &CTUShellEval( $optionlist[1] ) ;
+		if ( $ctdebug ) {
+		    print STDERR "resolved a 'ref' to " . $tmp .
+			", recuring\n" ;
+		}
+		$ret = &CTResolveSpec( $proj, $tmp ) ;
+	    }
+	} else {
+	    $ret = $spec ;
+	}
+    }
+    if ( $ret eq "" ) {
+	print STDERR "unknown flavor " . $_[1] . " of project " . $proj .
+	    "\n" ;
+    }
+    &CTUDebug( "out of CTResolveSpec\n" ) ;
+    $ret ;
+}
+
+# resolve the final name for a given flavor
+# $_[0] = project
+# $_[1] = flavor
+
+sub CTResolveSpecName {
+    &CTUDebug( "in CTResolveSpecName\n" ) ;
+    local( $proj ) = $_[0] ;
+    $proj =~ tr/A-Z/a-z/ ;
+    if ( $ctvspec_read ne $proj ) {
+	&CTReadVSpec( $proj ) ;
+    }
+    local( $spec ) = $ctvspecs{$_[1]} ;
+    local( $ret ) = $_[1] ;
+    if ( $spec ne "" ) {
+	local( $type ) = &CTSpecType( $spec ) ;
+	local( @speclist ) = split( /:/, &CTSpecOptions( $spec ) ) ;
+	if ( $type eq "ref" ) {
+	    local( @optionlist ) = split( /=/, $speclist[0] ) ;
+	    if ( $optionlist[0] ne "name" ) {
+		print STDERR "bad data attached to flavor " . $_[1] .
+		    " of project " . $proj . "\n" ;
+	    } else {
+		local( $tmp ) = &CTUShellEval( $optionlist[1] ) ;
+		if ( $ctdebug ) {
+		    print STDERR "resolved a 'ref' to " . $tmp .
+			", recuring\n" ;
+		}
+		$ret = &CTResolveSpecName( $proj, $tmp ) ;
+	    }
+	}
+    }
+    if ( $ret eq "" ) {
+	print STDERR "unknown flavor " . $_[1] . " of project " . $proj .
+	    "\n" ;
+    }
+    &CTUDebug( "out of CTResolveSpecName\n" ) ;
+    $ret ;
+}
+
+# validate a spec line
+# $_[0] = spec line
+
+sub CTValidateSpec {
+    local( $ret ) = 0 ;
+    local( $type ) = &CTSpecType( $_[0] ) ;
+    local( @speclist ) = split( /:/, &CTSpecOptions( $_[0] ) ) ;
+    local( $have_error ) = 0 ;
+    local( $item ) ;
+    local( @itemlist ) ;
+    if ( $type eq "ref" ) {
+	local( $have_name ) = 0 ;
+	foreach $item ( @speclist ) {
+	    @itemlist = split( /=/, $item ) ;
+	    if ( $itemlist[0] eq "name" ) {
+		if ( $have_name ) {
+		    $have_error = 1;
+		    &CTUDebug( "multiple name options on 'ref'\n" ) ;
+		}
+		$have_name = 1;
+	    } else {
+		&CTUDebug( "invalid option on 'ref' = " . $item . "\n" ) ;
+		$have_error = 1 ;
+	    }
+  	}
+	if ( ! $have_error ) {
+	    if ( $have_name ) {
+		$ret = 1 ;
+	    }
+	}
+    } elsif ( $type eq "root" ) {
+	local( $have_path ) = 0 ;
+	foreach $item ( @speclist ) {
+	    @itemlist = split( /=/, $item ) ;
+	    if ( $itemlist[0] eq "path" ) {
+		if ( $have_path ) {
+		    $have_error = 1 ;
+		    &CTUDebug( "multiple path options on 'root'\n" ) ;
+		}
+		$have_path = 1 ;
+	    } else {
+		&CTUDebug( "invalid option on 'root' = " . $item . "\n" ) ;
+		$have_error = 1 ;
+	    }
+	}
+	if ( ! $have_error ) {
+	    if ( $have_path ) {
+		$ret = 1 ;
+	    }
+	}
+    } elsif ( $type eq "vroot" ) {
+	local( $have_name ) = 0 ;
+	foreach $item ( @speclist ) {
+	    @itemlist = split( /=/, $item ) ;
+	    if ( $itemlist[0] eq "name" ) {
+		if ( $have_name ) {
+		    $have_error = 1 ;
+		    &CTUDebug( "multiple name options on 'vroot'\n" ) ;
+		}
+		$have_name = 1 ;
+	    } else {
+		&CTUDebug( "invalid option on 'vroot' = " . $item . "\n" ) ;
+		$have_error = 1 ;
+	    }
+	}
+	if ( ! $have_error ) {
+	    $ret = 1 ;
+	}
+    } elsif ( $type eq "croot" ) {
+	local( $have_path ) = 0 ;
+	local( $have_server ) = 0 ;
+	foreach $item ( @speclist ) {
+	    @itemlist = split( /=/, $item ) ;
+	    if ( $itemlist[0] eq "path" ) {
+		if ( $have_path ) {
+		    $have_error = 1 ;
+		    &CTUDebug( "multiple path options on 'croot'\n" ) ;
+		}
+		$have_path = 1 ;
+	    } elsif ( $itemlist[0] eq "server" ) {
+		if ( $have_server ) {
+		    $have_error = 1 ;
+		    &CTUDebug( "multiple server options on 'croot'\n" ) ;
+		}
+		$have_server = 1 ;
+	    } else {
+		&CTUDebug( "invalid option on 'croot' = " . $item . "\n" ) ;
+		$have_error = 1 ;
+	    }
+	}
+	if ( ! $have_error ) {
+	    if ( $have_path && $have_server ) {
+		$ret = 1 ;
+	    }
+	}
+    } else {
+	&CTUDebug( "unknow spec type '" . $speclist[0] . "'\n" ) ;
+    }
+    $ret ;
+}
+
+# get a list of all projects
+
+sub CTListAllProjects {
+    &CTUDebug( "in CTListAllProjects\n" ) ;
+    local( $ret ) = "" ;
+    local( $done ) = 0 ;
+    local( *DIRFILES ) ;
+    open( DIRFILES, "(cd $ctvspec_path ; /bin/ls -1 *.vspec ; echo blahblah) |" ) ;
+    while ( ! $done ) {
+	$_ = <DIRFILES> ;
+	s/\n$// ;
+	if ( $_ eq "blahblah" ) {
+	    $done = 1 ;
+	} else {
+	    s/.vspec$// ;
+	    if ( $_ ne "" ) {
+		if ( $ret eq "" ) {
+		    $ret = $_ ;
+		} else {
+		    $ret = $ret . " " . $_ ;
+		}
+	    }
+	}
+    }
+    close( DIRFILES ) ;
+    &CTUDebug( "final list of projects '" . $ret . "'\n" .
+	       "out of CTListAllProjects\n" ) ;
+    $ret ;
+}
+
+# list all flavors of a project
+# $_[0] = project
+
+sub CTListAllFlavors {
+    &CTUDebug( "in CTListAllFlavors\n" ) ;
+    local( $proj ) = $_[0] ;
+    $proj =~ tr/A-Z/a-z/ ;
+    if ( $ctvspec_read ne $proj ) {
+	&CTReadVSpec( $proj ) ;
+    }
+    local( $ret ) = "";
+    local( $item ) ;
+    foreach $item ( keys %ctvspecs ) {
+	if ( $ret eq "" ) {
+	    $ret = $item ;
+	} else {
+	    $ret = $ret . " " . $item ;
+	}
+    }
+    &CTUDebug( "out of CTListAllFlavors\n" ) ;
+    $ret ;
+}
+
+# given a project and a spec, determine the local root of the project
+# $_[0] = project
+# $_[1] = flavor
+# $_[2] = spec line
+
+sub CTComputeRoot {
+    &CTUDebug( "in CTComputeRoot\n" ) ;
+    local( $proj ) = $_[0] ;
+    $proj =~ tr/A-Z/a-z/ ;
+    if ( $ctvspec_read ne $proj ) {
+	&CTReadVSpec( $proj ) ;
+    }
+    local( $ret ) = "" ;
+    local( $type ) = &CTSpecType( $_[2] ) ;
+    local( $options ) = &CTSpecOptions( $_[2] ) ;
+    local( $vname ) = &CTResolveSpecName( $proj, $_[1] ) ;
+    &CTUDebug( "type = '" . $type . "' with options '" . $options . "'\n" ) ;
+    if ( $type eq "root" ) {
+	$ret = &CTSpecFindOption( $options, "path" ) ;
+    } elsif ( $type eq "vroot" ) {
+	local( $name ) = &CTSpecFindOption( $options, "name" ) ;
+	if ( $name ne "" ) {
+	    $ret = "/view/$name/vobs/$proj" ;
+	} else {
+	    $ret = "/view/$vname/vobs/$proj" ;
+	}
+    } elsif ( $type eq "croot" ) {
+	$ret = &CTSpecFindOption( $options, "path" ) ;
+    } elsif ( $ctdebug) {
+	print STDERR "unknown flavor type '" . $type . "'\n" ;
+    }
+    &CTUDebug( "returning '" . $ret . "'\n" ) ;
+    &CTUDebug( "out of CTComputeRoot\n" ) ;
+    $ret ;
+}
+
+%ctvspecs = () ;
+$ctvspec_read = "" ;
+
+1;

+ 36 - 0
dtool/src/attach/dtool.alias

@@ -0,0 +1,36 @@
+#!/bin/csh -f
+
+setenv OS `uname`
+setenv USER `whoami`
+
+if ( -e $DTOOL/bin/neartool ) setenv HAVE_NEARTOOL "yes"
+if ( ! $?HAVE_NEARTOOL ) setenv HAVE_NEARTOOL "no"
+if ( ! $?HAVE_ATRIA ) setenv HAVE_ATRIA "no"
+
+set host=$HOST
+if ( $TERM == "iris-ansi" || $TERM == "iris-ansi-net" ) then
+  alias ctshowprojs 'echo -n "\033P1.y"$USER"@"$host" -- "$CTPROJS"\033\\"; echo -n "\033P3.y"`echo $CTPROJS | cut -f1 -d:`\($host\)"\033\\"'
+else if ( $TERM == "xterm" || $TERM == "color-xterm" || $TERM == "cygwin" ) then
+  alias ctshowprojs 'echo -n "\033]2;"$USER"@"$host" -- "$CTPROJS"\007"; echo -n "\033]1;"`echo $CTPROJS | cut -f1 -d:`\($host\)"\007"'
+else
+  alias ctshowprojs 'echo $CTPROJS'
+endif
+
+alias ctattach 'source `ctattach.drv \!*`; ctshowprojs'
+alias cta 'ctattach'
+alias cta-ship 'setenv CTSAVE $CTDEFAULT_FLAV ; setenv CTDEFAULT_FLAV ship ; ctattach \!* ; setenv CTDEFAULT_FLAV $CTSAVE ; unsetenv CTSAVE'
+alias cta-release 'setenv CTSAVE $CTDEFAULT_FLAV ; setenv CTDEFAULT_FLAV release ; ctattach \!* ; setenv CTDEFAULT_FLAV $CTSAVE ; unsetenv CTSAVE'
+alias cta-install 'setenv CTSAVE $CTDEFAULT_FLAV ; setenv CTDEFAULT_FLAV install ; ctattach \!* ; setenv CTDEFAULT_FLAV $CTSAVE ; unsetenv CTSAVE'
+alias ctunattach 'source `ctunattach.drv \!*`; ctshowprojs'
+alias ctuna 'ctunattach'
+
+#Modifications to emacs alias by Jason
+#To allow for NTEmacs to run like emacs on unix boxes
+if (($OS == "CYGWIN_NT-4.0") || ($OS == "CYGWIN_NT-5.0" )) then
+  alias emacs 'emacs -T "`logname`@`uname -n`  $CTPROJS" -xrm "Emacs*iconName: `echo $CTPROJS | cut -f1 -d:`(`uname -n`)" -bg #002040 -fg #00C0FF -cr yellow -ms yellow -l `cygpath -w ~/.emacs` $CTEMACS_OPTS'
+else
+  alias emacs 'emacs -T "`logname`@`uname -n`  $CTPROJS" -xrm "Emacs*iconName: `echo $CTPROJS | cut -f1 -d:`(`uname -n`)" $CTEMACS_OPTS'
+endif
+
+alias rlogin 'rlogin \!*; ctshowprojs'
+alias telnet 'telnet \!*; ctshowprojs'

+ 46 - 0
dtool/src/attach/dtool.alias-sh

@@ -0,0 +1,46 @@
+#! /bin/sh
+
+if [ -e $DTOOL/bin/neartool ]; then HAVE_NEARTOOL="yes"; fi
+if [ -z "$HAVE_NEARTOOL" ]; then HAVE_NEARTOOL="no"; fi
+export HAVE_NEARTOOL
+
+if [ -z "$HAVE_ATRIA" ]; then HAVE_ATRIA="no"; fi
+export HAVE_ATRIA
+
+if [ $HAVE_NEARTOOL = "yes" ]; then
+  alias ct='neartool'
+else
+  alias ct='cleartool'
+fi
+
+alias ctshowprojs='echo -n "\033P1.y"$USER"@"$HOST" -- "$CTPROJS"\033\\"; echo -n "\033P3.y"`echo $CTPROJS | cut -f1 -d:`\(`uname -n`\)"\033\\"'
+alias ctattach='source `ctattach.drv $*`; ctshowprojs'
+alias cta='ctattach'
+alias cta-ship='setenv CTSAVE $CTDEFAULT_FLAV ; setenv CTDEFAULT_FLAV ship ; ctattach $* ; setenv CTDEFAULT_FLAV $CTSAVE ; unsetenv CTSAVE'
+alias cta-release='setenv CTSAVE $CTDEFAULT_FLAV ; setenv CTDEFAULT_FLAV release ; ctattach $* ; setenv CTDEFAULT_FLAV $CTSAVE ; unsetenv CTSAVE'
+alias cta-install='setenv CTSAVE $CTDEFAULT_FLAV ; setenv CTDEFAULT_FLAV install ; ctattach $* ; setenv CTDEFAULT_FLAV $CTSAVE ; unsetenv CTSAVE'
+alias ctunattach='source `ctunattach.drv $*`; ctshowprojs'
+alias ctuna='ctunattach'
+
+if [ "$PENV" = "WIN32_DREAMCAST" ]; then
+  alias ctci='neartool ci'
+  alias ctco='neartool co'
+  alias ctmake='gmake'
+  alias emacs='/emacs/bin/runemacs'
+  alias emacs='/emacs/bin/runemacs -T "`logname`@`uname -n`  $CTPROJS" -xrm "Emacs*iconName: `echo $CTPROJS | cut -f1 -d:`(`uname -n`)" $CTEMACS_OPTS'
+
+elif [ "$HAVE_NEARTOOL" = "yes" ]; then
+  alias ctci='neartool ci'
+  alias ctco='neartool co'
+  alias ctmake='make'
+  alias emacs='emacs -T "`logname`@`uname -n`  $CTPROJS" -xrm "Emacs*iconName: `echo $CTPROJS | cut -f1 -d:`(`uname -n`)" $CTEMACS_OPTS'
+
+elif [ "$HAVE_ATRIA" = "yes" ]; then
+  alias ctci='cleartool ci'
+  alias ctco='cleartool co'
+  alias ctmake 'clearmake -C gnu $* |& grep -v "^clearmake: Warning: Config"'
+  alias emacs='emacs -T "`logname`@`uname -n`  $CTPROJS" -xrm "Emacs*iconName: `echo $CTPROJS | cut -f1 -d:`(`uname -n`)" $CTEMACS_OPTS'
+fi
+
+alias rlogin='rlogin $*; ctshowprojs'
+alias telnet='telnet $*; ctshowprojs'

+ 85 - 0
dtool/src/attach/dtool.cshrc

@@ -0,0 +1,85 @@
+#!/bin/csh -f
+
+setenv OS `uname`
+
+setenv LD_LIBRARY_PATH "."
+
+# Setup the initial path
+if ( $OS == "Linux" ) then
+  set path = ( /var/local/bin ~/bin . /usr/sbin /sbin /usr/bin /bin \
+             /usr/bin/X11 /usr/etc /usr/local/bin )
+else if ( $OS == "IRIX64" ) then
+  set path = ( /var/local/bin /usr/local/bin/ptools ~/bin /usr/local/prman/bin \
+             . /usr/sbin /usr/bsd /sbin /usr/bin /bin /usr/bin/X11 /usr/etc  \
+             /usr/demos/bin /usr/local/bin )
+  setenv LD_LIBRARY_PATH ".:/usr/local/lib"
+else if (( $OS == "CYGWIN_NT-4.0" ) || ( $OS == "WINNT" ) || ($OS == "CYGWIN_NT-5.0")) then
+  set path = ( /usr/local/bin /contrib/bin . /usr/lib $path )
+  if ( $?LIB ) then
+    setenv LIB "$LIB;"`cygpath -w /usr/lib`
+  else 
+    setenv LIB `cygpath -w /usr/lib`
+  endif
+else if (( $OS == "CYGWIN_98-4.10" ) || ( $OS == "WIN95" )) then
+  set path = ( /bin /usr/local/bin /contrib/bin /msvc98/Bin \
+	/mscommon/MSDev98/Bin /mscommon/Tools . /usr/lib $path )
+  setenv LIB `cygpath -w /msvc98/mfc/lib`\;`cygpath -w /msvc98/lib`\;`cygpath -w /usr/lib`
+  setenv INCLUDE `cygpath -w /msvc98/Include`
+else
+  set path = ( /var/local/bin /usr/local/bin/ptools ~/bin /usr/local/prman/bin \
+             . /usr/sbin /usr/bsd /sbin /usr/bin /bin /usr/bin/X11 /usr/etc  \
+             /usr/demos/bin /usr/local/bin )
+endif
+
+# Setup the initial manpath
+if ( $OS == "Linux" ) then
+setenv MANPATH "/usr/local/man:/usr/man/preformat:/usr/man:/usr/X11R6/man"
+else if ( $OS == "IRIX64" ) then
+setenv MANPATH "/usr/share/catman:/usr/catman:/usr/local/share/catman:/usr/local/share/man:/usr/local/man"
+else if (( $OS == "CYGWIN_NT-4.0" ) || ( $OS == "CYGWIN_98-4.10" ) || ( $OS == "WIN95" ) || ( $OS == "WINNT" ) || ( $OS == "CYGWIN_NT-5.0")) then
+setenv MANPATH "/usr/man:/contrib/man"
+else
+setenv MANPATH "/usr/share/catman:/usr/catman:/usr/local/share/catman:/usr/local/share/man:/usr/local/man"
+endif
+
+setenv CT_INCLUDE_PATH "."
+set cdpath = ( . )
+setenv CDPATH "."
+setenv DC_PATH "."
+setenv SSPATH "."
+setenv STKPATH "."
+
+if ( ! $?HAVE_ATRIA ) then
+   if ( -e /usr/atria ) then
+      /usr/atria/bin/cleartool mount -all >& /dev/null
+      if ( $status == 0 ) setenv HAVE_ATRIA "yes"
+   endif
+endif
+
+if ( ! $?CTDEFAULT_FLAV ) setenv CTDEFAULT_FLAV "default"
+if ( ! $?CTEMACS_OPTS ) setenv CTEMACS_OPTS ""
+
+if ( -e /usr/atria/bin ) set path = ( /usr/atria/bin $path )
+rehash
+
+if ( ! $?DTOOL ) setenv DTOOL /beta/player/bootstrap/dtool
+if ( $#argv == 0 ) then
+   source `$DTOOL/bin/ctattach.drv dtool default`
+else
+   source `$DTOOL/bin/ctattach.drv dtool $argv[1]`
+endif
+
+if ( ! $?PENV ) then
+   if ( $OS == "Linux" ) then
+      setenv PENV "Linux"
+   else if ( $OS == "IRIX64" ) then
+      setenv PENV "SGI"
+   else if (( $OS == "CYGWIN_NT-4.0" ) || ( $OS == "CYGWIN_98-4.10" ) || ( $OS == "WIN95" ) || ( $OS == "CYGWIN_NT-5.0")) then
+      setenv PENV "WIN32"
+   else
+      setenv PENV "SGI"
+   endif
+endif
+
+setenv CTEMACS_FOREHIGHLIGHT white
+setenv CTEMACS_BACKHIGHLIGHT blue

+ 286 - 0
dtool/src/attach/dtool.emacs

@@ -0,0 +1,286 @@
+;; make the mouse pointer avoid the text point
+(cond (window-system
+       (require 'avoid)
+       (mouse-avoidance-mode 'cat-and-mouse)))
+
+;; make sure we have the compile library available to us
+(load-library "compile")
+;; Comment given for last checkout command
+(setq last-co-comment "")
+;; Comment given for last checkin command
+(setq last-ci-comment "")
+;; Target given for the last local make
+(setq last-lm-target "realinstall")
+;; Target given for the last global make
+(setq last-gm-target "install")
+;; Host given for the last ctrelease
+(setq last-rel-host "")
+;; Host given for the last ctship
+(setq last-ship-host "")
+
+;; check the environment
+(setq ct-tool (getenv "DTOOL"))
+(setq have-atria (let ((h-a (getenv "HAVE_ATRIA")))
+		   (if (string= h-a "yes") t '())))
+;; (setq have-neartool (let ((h-n (getenv "HAVE_NEARTOOL")))
+;;                          (if (string= h-n "yes") t '())))
+(setq is-cygwin (string= (getenv "OS") "CYGWIN_NT-4.0"))
+
+;; (setq ct-command (cond
+;; 		  (is-cygwin "bash /install/tool/bin/neartool")
+;; 		  (have-atria "cleartool")
+;; 		  (have-neartool "neartool")
+;; 		  t nil))
+
+;; Load the Hightlight coloring scheme
+(if is-cygwin
+;;    (let ((filename (concat (getenv "CYGWIN_ROOT") "install\\tool\\etc\\color.emacs")))
+    (let ((filename (concat (getenv "CYGWIN_ROOT") ct-tool "\\etc\\color.emacs")))
+      (if (file-readable-p filename) (load filename))))
+
+;; Checkout element in the current buffer
+(defun ct-checkout-curr (comment)
+  "Checkout version in current buffer with COMMENT."
+  (interactive (list (read-string "Comment: " last-co-comment)))
+  (setq last-co-comment comment)
+  (setq pname (file-name-nondirectory (buffer-file-name)))
+  (ct-shell-command-verbose
+   (concat "ctco -c " (ct-quote-string comment) " " pname))
+  (ct-find-curr-file-again nil)
+)
+
+;; Uncheckout element in the current buffer
+(defun ct-uncheckout-curr ()
+  "Uncheckout version in current buffer and remove private data."
+  (interactive)
+  (if (y-or-n-p "Ok to un-checkout? ")
+      (progn
+	(setq pname (file-name-nondirectory (buffer-file-name)))
+	(ct-shell-command-verbose (concat "ctunco " pname))
+	(ct-find-curr-file-again t)
+	)
+      (progn
+	(message "Uncheckout canceled.")
+	)
+    )
+)
+
+;; Checkin element in the current buffer
+(defun ct-checkin-curr ()
+  "Checkin version in current buffer."
+  (interactive)
+  (setq pname (file-name-nondirectory (buffer-file-name)))
+  (setq option nil)
+  (while (not option)
+    (setq choice (read-string "Comment: s (same), n (new), l (list): " "s"))
+    (cond
+      ((equal choice "s")
+         (setq option "-nc"))
+      ((equal choice "n")
+         (setq comment (read-string "Comment: " last-ci-comment))
+	 (setq last-ci-comment comment)
+	 (setq option (concat "-c " (ct-quote-string comment))))
+      ((equal choice "l")
+       (ct-shell-command-verbose (concat "ctihave " pname)))
+      (t
+       (message (concat "Unrecognized choice: " choice "."))
+       (sleep-for 2))))
+
+  (ct-shell-command-verbose (concat "ctci " option " " pname))
+  (ct-find-curr-file-again t)
+)
+
+;; Delta element in the current buffer
+(defun ct-delta-curr ()
+  "Delta element in current buffer."
+  (interactive)
+  (if (y-or-n-p "Ok to delta? ")
+      (progn
+	(setq pname (file-name-nondirectory (buffer-file-name)))
+	(ct-shell-command-verbose (concat "ctdelta " pname))
+	(ct-find-curr-file-again t)
+	)
+      (progn
+	(message "Delta canceled.")
+	)
+      )
+)
+
+;; List element checkout data for the current buffer
+(defun ct-lscheckout-curr ()
+  "List checkout for the current buffer."
+  (interactive)
+  (setq pname (file-name-nondirectory (buffer-file-name)))
+  (ct-shell-command-verbose (concat "ctihave &"))
+)
+
+;; List elements in the current directory that are checked out
+(defun ct-lscheckout-curr-dir ()
+  "List checkouts for the current directory."
+  (ct-shell-command-verbose (concat "ctihave &"))
+)
+
+;; call clearmake in the local directory
+(defun ct-local-make ()
+  "Build TARGET from the current directory."
+  (interactive)
+  (setq target (read-string "Local build target: " last-lm-target))
+  (setq last-lm-target target)
+  (if have-atria
+      (compile-internal
+        (concat "clearmake -C gnu " target
+	        " |& grep -v \"clearmake: Warning: Config\"")
+        "No more errors.")
+      (compile-internal
+        (concat "make " target) "No more errors."))
+)
+
+;; call clearmake in the project root directory
+(defun ct-global-make ()
+  "Build TARGET from the project root."
+  (interactive)
+  (setq target (read-string "Global build target: " last-gm-target))
+  (setq last-gm-target target)
+  (cond
+   (have-atria
+    (compile-internal
+     (concat "cd `ctproj -r` ; clearmake -C gnu " target
+	     " |& grep -v \"clearmake: Warning: Config\"")
+     "No more errors."))
+   (is-cygwin
+    (compile-internal
+     (concat "bash -f 'cd `ctproj -r` ; make " target "'") "No more errors."))
+   (t
+    (compile-internal
+     (concat "cd `ctproj -r` ; make " target) "No more errors."))
+   )
+  )
+
+;; Do an xdiff on the current buffer to see what is different about this
+;; file from the previous version.
+(defun ct-xdiff-curr ()
+  "Show changes to element in current buffer from the previous version."
+  (interactive)
+  (setq pname (file-name-nondirectory (buffer-file-name)))
+  (if is-cygwin
+      (ct-shell-command-verbose (concat ct-command " xdiff -pre " pname))
+  
+    ; The is a hack to deal with the fact that diff returns 1 if the
+    ; two files do not match.
+    (ct-shell-command-verbose (concat ct-command " xdiff -pre " pname ";:&")))
+  )
+
+
+;; Make a new element for the current buffer
+(defun ct-mk-elem ()
+  (interactive)
+  (if (y-or-n-p (format "Make new element for %s? "
+                        (file-name-nondirectory (buffer-name))))
+      (progn
+	(write-file (buffer-file-name))
+	(ct-shell-command-verbose
+	 (concat "ctmkelem -eltype text_file -c '' "
+		 (file-name-nondirectory (buffer-name))))
+        )
+    (progn
+      (message "Make element canceled.")
+      )
+    )
+  )
+
+;; utility functions
+(defun ct-shell-command-verbose (command)
+  "Execute COMMAND in shell with message."
+  (interactive "Shell command: \n")
+  (message (concat "Executing: " command " ..."))
+  (shell-command command)
+  (message "Done.")
+)
+
+(defun ct-find-curr-file-again (read-only)
+  "Read in the currect file again, READONLY (t) or not (nil)."
+  (setq pname (buffer-file-name))
+  (setq linenum (1+ (count-lines 1 (point))))
+  (kill-buffer (buffer-name))
+  (if read-only
+      (find-file-read-only pname)
+      (find-file pname))
+  (goto-line linenum)
+)
+
+(defun ct-quote-string (string)
+  "Enclose STRING in single or double quotes."
+  (setq has-double (string-match "\"" string))
+  (setq has-single (string-match "'" string))
+  (cond
+    ((or (and (not has-single) (not has-double))
+	 (and has-double (not has-single)))
+       (concat "'" string "'"))
+    ((and has-single (not has-double))
+       (concat "\"" string "\""))
+    (t
+       (message (concat "Can't quote string correctly: " string))
+       (sleep-for 3)
+       (concat "\"" string "\"")))
+)
+
+;; default key bindings
+(global-set-key "\C-xco" 'ct-checkout-curr)
+(global-set-key "\C-xcu" 'ct-uncheckout-curr)
+(global-set-key "\C-xci" 'ct-checkin-curr)
+(global-set-key "\C-xcd" 'ct-delta-curr)
+(global-set-key "\C-xcl" 'ct-lscheckout-curr)
+(global-set-key "\C-xcL" 'ct-lscheckout-curr-dir)
+(global-set-key "\C-xcm" 'ct-local-make)
+(global-set-key "\C-xcM" 'ct-global-make)
+(global-set-key "\C-xcx" 'ct-xdiff-curr)
+(global-set-key "\C-xce" 'ct-mk-elem)
+
+;; ok, lets make sure we load all other .emacs files we might need.  This is
+;; attach related code.
+
+(defun ct-load-project-emacs-file (proj-name)
+  (if (string= proj-name "DTOOL") nil
+    (let ((pre-name (getenv proj-name)))
+      (if pre-name
+          (let ((filename (concat pre-name "/etc/" 
+                                  (downcase proj-name) ".emacs")))
+            (if (file-readable-p filename)
+                (load filename))
+            )))
+    )
+  )
+
+(defun ct-break-space-colon-str (string)
+  (if (string= string "")
+      '()
+    (let ((substr-end (string-match ":" string 0)))
+      (cons (substring string 0 substr-end)
+            (let ((new-string-start (string-match " " string 0)))
+              (if (eq nil new-string-start)
+                  '()
+                (ct-break-space-colon-str 
+                 (strip-spaces (substring string (match-end 0)))))
+              )))
+    )
+  )
+
+(defun strip-spaces (string)
+  (if (= (string-to-char string) 32)
+      (if (= (length string) 1) ""
+        (strip-spaces (substring string 1)))
+    string)
+  )
+
+(defun ct-load-project-emacs-files ()
+  "Load project specific .emacs files"
+  (let ((ctprojs (getenv "CTPROJS")))
+    (if ctprojs
+      (mapcar 'ct-load-project-emacs-file
+              (reverse (ct-break-space-colon-str ctprojs)))
+      ))
+  )
+
+;; get all of the project specific .emacs files
+(ct-load-project-emacs-files)
+

+ 10 - 0
dtool/src/attach/dtool.init

@@ -0,0 +1,10 @@
+MODREL ETC_PATH etc
+DOCSH source $DTOOL/etc/dtool.alias
+DOCSH unsetenv LASTLOGIN
+DOCSH setenv OS_VER `uname -r`
+DOCSH ctshowprojs
+DOSH source $DTOOL/etc/dtool.alias-sh
+DOSH LASTLOGIN=
+DOSH export LASTLOGIN
+DOSH OS_VER=`uname -r`
+DOSH export OS_VER

+ 79 - 0
dtool/src/attach/dtool.sh

@@ -0,0 +1,79 @@
+#! /bin/sh
+
+OS=`uname`
+export OS
+
+# Setup the initial path
+if [ $OS = "Linux" ]; then
+  PATH=/var/local/bin:~/bin:.:/usr/sbin:/sbin:/usr/bin:/bin:/usr/bin/X11:/usr/etc:/usr/local/bin
+elif [ $OS = "IRIX64" ]; then
+  PATH=/var/local/bin:/usr/local/bin/ptools:~/bin:/usr/local/prman/bin:.:/usr/sbin:/usr/bsd:/sbin:/usr/bin:/bin:/usr/bin/X11:/usr/etc:/usr/demos/bin:/usr/local/bin
+elif [ $OS = "CYGWIN_98-4.10" ]; then
+  PATH=/usr/local/bin:/CYGNUS/CYGWIN~1/H-I586~1/BIN:/WINDOWS:/WINDOWS:/WINDOWS/COMMAND:/DMI/BIN:/KATANA/UTL/DEV/MAKE:/KATANA/UTL/DEV/HITACHI
+else
+  PATH=/var/local/bin:/usr/local/bin/ptools:~/bin:/usr/local/prman/bin:.:/usr/sbin:/usr/bsd:/sbin:/usr/bin:/bin:/usr/bin/X11:/usr/etc:/usr/demos/bin:/usr/local/bin
+fi
+
+# Setup the initial manpath
+if [ $OS = "Linux" ]; then
+  MANPATH=/usr/local/man:/usr/man/preformat:/usr/man:/usr/X11R6/man
+elif [ $OS = "IRIX64" ]; then
+  MANPATH=/usr/share/catman:/usr/catman:/usr/local/share/catman:/usr/local/share/man:/usr/local/man
+elif [ $OS = "CYGWIN_98-4.10" ]; then
+  MANPATH=/usr/local/man
+else
+  MANPATH=/usr/share/catman:/usr/catman:/usr/local/share/catman:/usr/local/share/man:/usr/local/man
+fi
+export MANPATH
+
+LD_LIBRARY_PATH="."
+export LD_LIBRARY_PATH
+CT_INCLUDE_PATH="."
+export CT_INCLUDE_PATH
+cdpath=.
+CDPATH="."
+export CDPATH
+DC_PATH="."
+export DC_PATH
+SSPATH="."
+export SSPATH
+STKPATH="."
+export STKPATH
+SHELL_TYPE="sh"
+export SHELL_TYPE
+
+if [ -e /usr/atria ]; then
+  if /usr/atria/bin/cleartool mount -all > /dev/null 2>&1; then
+    HAVE_ATRIA=yes
+    export HAVE_ATRIA
+  fi
+fi
+
+if [ -z "$CTDEFAULT_FLAV" ]; then
+  CTDEFAULT_FLAV="default"
+  export CTDEFAULT_FLAV
+fi
+
+if [ -z "$DTOOL" ]; then
+  DTOOL=/beta/player/bootstrap/tool
+  export DTOOL
+fi
+
+if [ -z "$1" ]; then
+  source `$DTOOL/bin/ctattach.drv dtool default`
+else
+  source `$DTOOL/bin/ctattach.drv dtool $1`
+fi
+
+if [ -z "$PENV" ]; then
+  if [ $OS = "Linux" ]; then
+    PENV="Linux"
+  elif [ $OS = "IRIX64" ]; then
+    PENV="SGI"
+  elif [ $OS = "CYGWIN_98-4.10" ]; then
+    PENV="WIN32_DREAMCAST"
+  else
+    PENV="SGI"
+  fi
+fi
+export PENV

+ 104 - 0
dtool/src/attach/get-cttree

@@ -0,0 +1,104 @@
+#! /bin/sh
+#
+# get-cttree.sh
+#
+# Usage:
+#
+# get-cttree.sh [opts] output-file.tgz
+#
+# This script must be executed from within a project tree.
+#
+# Options:
+#
+#   None at present.
+#
+#ENDCOMMENT
+
+while getopts "h" flag; do
+  case $flag in
+    h) sed '/#ENDCOMMENT/,$d' <$0 >&2
+       exit 1;;
+    \?) exit 1;
+  esac
+done
+
+shift `expr $OPTIND - 1`
+output=$1
+projroot=`ctproj -r`
+
+if [ -z "$projroot" ]; then
+  echo ""
+  echo "You must execute this script in a project tree."
+  echo ""
+  exit 1
+fi
+
+if [ -z "$output" ]; then
+  sed '/#ENDCOMMENT/,$d' <$0 >&2
+  exit 1
+fi
+
+
+# Perform some sanity checks on input parameters.
+
+if [ ! -d "$projroot" ]; then
+  echo ""
+  echo "$projroot is not a directory!"
+  echo ""
+  exit 1
+fi
+
+if [ `basename $output .tgz` = `basename $output` ]; then
+  echo ""
+  echo "$output should end in .tgz"
+  echo ""
+  exit 1
+fi
+
+if [ ! -d /usr/atria ]; then
+  echo ""
+  echo "This script is intended to be run on an actual ClearCase vobs."
+  echo ""
+  exit 1
+fi
+
+projname=`basename $projroot`
+projtop=`dirname $projroot`
+
+if [ "$projname" = "tool" ]; then
+  echo ""
+  echo "This script should not be used on the tool tree."
+  echo ""
+  exit 1
+fi
+
+if [ -f "$output" ]; then
+  if rm -i $output; then
+    echo ""
+  else
+    echo "Not overwriting $output"
+    exit 1
+  fi
+elif [ -r "$output" -o -w "$output" ]; then
+  echo "Cannot overwrite $output"
+  exit 1
+else
+  echo ""
+fi
+
+# Check to make sure the local machine doesn't have anything checked out.
+cd $projroot
+outfile=/tmp/gc.$username.$projname.out
+cleartool lsco -s -me -recurse >$outfile
+if [ -s $outfile ]; then
+  echo ""
+  echo "Cannot build tarball; files still checked out in vobs:"
+  sed 's/^/  /;s/\.ct0\.//' $outfile
+  rm -f $outfile
+  echo ""
+  exit 1
+fi
+rm -f $outfile
+
+(cd $projtop; cleartool find $projname -nxn -print | grep -v '/lost+found' | cpio -H tar -v -o | gzip) >$output
+

+ 481 - 0
dtool/src/attach/get-delta

@@ -0,0 +1,481 @@
+#! /usr/local/bin/bash
+#
+# get-delta.sh
+#
+# Usage:
+# 
+# get-delta.sh [opts] output-file.sh [file ...]
+#
+# This script must be executed from within a project tree.  It
+# examines the set of files that have been checked out (via neartool)
+# and modified, and generates a script file that can be used to apply
+# the changes made back to the main ClearCase vobs.
+#
+# By default, it generates a script for all checked-out files.  You
+# can restrict its operation to certain files and/or directories by
+# listing them on the command line.
+#
+# Options:
+#
+#   -c  collapse versioning information on local copy after completion.
+#       Use this option with caution, as it is irreversible (and
+#       noninterruptible).  Once the versioning information has been
+#       collapsed, it will be impossible to regenerate a script
+#       representing the changes that have been made locally; you
+#       should only do this when you are sure that your changes have
+#       been successfully applied to the other end.
+#
+#       On the other hand, if you forget to run get-delta with -c after
+#       you have successfully applied your changes, you may
+#       inadvertently attempt to apply them again if you subsequently
+#       try to apply more changes.
+#
+#ENDCOMMENT
+
+function usage {
+  sed '/#ENDCOMMENT/,$d' <$0 >&2
+  exit 1
+}
+
+#
+# list_comments ( dirname basename )
+#
+# Writes to stdout any comments associated with checked-out versions of
+# the indicated file, in order.
+#
+function list_comments {
+  local dirname=$1
+  local basename=$2
+  local filename=$dirname/$basename
+  local file comment version
+
+  if [ -f $dirname/.ct0.$basename ]; then
+    # Now look for comments, in version-number order.
+
+    # We use a series of ls commands so we don't try to sort the
+    # filenames between the one-, two-, and three-digit version
+    # numbers.
+
+    for file in `(cd $dirname; ls .ct[0-9].$basename; ls .ct[0-9][0-9].$basename; ls .ct[0-9][0-9][0-9].$basename) 2>/dev/null`; do
+      version=`echo $file | sed "s/^\.ct\([0-9]*\).*$/\1/"`
+      comment=$dirname/.ct${version}comment.$basename
+      if [ -f $comment ]; then
+	cat $comment 
+      fi
+    done
+  fi
+}
+
+#
+# get_fullpath ( local_dir )
+#
+# Sets $fullpath to the fully-qualified pathname associated with $local_dir.
+#
+function get_fullpath {
+  local local_dir=$1
+
+  if [ -z "$local_dir" ]; then
+    fullpath=`pwd`
+  else
+    if [ ! -d "$local_dir" ]; then
+      echo "Invalid directory: $local_dir" 1>&2
+      exit 1
+    fi
+    # If we use pwd instead of /bin/pwd, $PWD will be used, which will give
+    # the wrong answer
+    fullpath=`(cd $local_dir; /bin/pwd)`
+  fi
+}
+
+
+#
+# get_rel_dir ( root_dir local_dir )
+#
+# Sets $rel_dir to the string which represents $local_dir relative to
+# $root_dir.  This is a simple string-prefix operation, and could fail
+# in some obscure cases.
+#
+function get_rel_dir {
+  get_fullpath $1
+  local root_dir=$fullpath
+
+  get_fullpath $2
+  local local_dir=$fullpath
+
+  # Now remove the initial prefix.
+  if [ "$root_dir" = "$local_dir" ]; then
+    rel_dir="."
+  else
+    rel_dir=`echo $local_dir | sed 's:^'$root_dir/'::'`
+
+    if [ "$rel_dir" = "$local_dir" ]; then
+      echo "$local_dir is not a directory within $root_dir." 1>&2
+      exit 1
+    fi
+  fi
+}
+
+
+collapse=
+while getopts "ch" flag; do
+  case $flag in
+    c) collapse=y;;
+    h) usage;;
+    \?) exit 1;
+  esac
+done
+
+shift `expr $OPTIND - 1`
+output=$1
+shift
+projroot=`ctproj -r`
+
+if [ -z "$projroot" ]; then
+  echo "You must execute this script in a project tree."
+  exit 1
+fi
+
+if [ -z "$output" ]; then
+  usage
+fi
+
+
+# Perform some sanity checks on input parameters.
+
+if [ ! -d "$projroot" ]; then
+  echo "$projroot is not a directory!"
+  exit 1
+fi
+
+if [ `basename $output .sh` = `basename $output` ]; then
+  echo "$output should end in .sh"
+  exit 1
+fi
+
+if [ -f "$output" ]; then
+  rm -i $output
+  if [ -f "$output" ]; then
+    echo "Not overwriting $output"
+    exit 1
+  fi
+elif [ -e "$output" ]; then
+  echo "Cannot overwrite $output"
+  exit 1
+fi  
+
+echo ""
+
+# Temporary files we'll build up as we process the files.
+
+base=`basename $output`
+temp_ct0=/tmp/gd.ct0.$base
+temp_checkout=/tmp/gd.checkout.$base
+temp_dirs=/tmp/gd.dirs.$base
+temp_files=/tmp/gd.files.$base
+temp_diffs=/tmp/gd.diffs.$base
+
+rm -f $temp_ct0 $temp_checkout $temp_dirs $temp_files $temp_diffs
+touch $temp_ct0 $temp_dirs $temp_files
+
+
+# Get the list of files we'll want to delta in.
+
+if [ $# -eq 0 ]; then
+  # No explicit files, get all of them.
+  (cd $projroot; find . -name .ct0.\* -print) >>$temp_ct0
+else
+  # An explicit list of files.
+  for filename in $*; do
+    if [ -f $filename ]; then
+      dirname=`dirname $filename`
+      basename=`basename $filename`
+
+      if [ -f $dirname/.ct0.$basename ]; then
+        get_rel_dir $projroot $dirname
+	echo ./$rel_dir/.ct0.$basename >>$temp_ct0
+      else
+        echo $filename has no versions.
+      fi
+
+    elif [ -d $filename ]; then
+      get_rel_dir $projroot $filename
+
+      (cd $projroot; find ./$rel_dir -name .ct0.\* -print) >>$temp_ct0
+    
+    else
+      echo $filename not found.
+    fi
+  done
+fi
+
+
+# Now start to build up the script.
+
+echo "#! /bin/sh" >$output
+chmod 755 $output
+
+if [ ! -w $output ]; then
+  echo "Cannot write to $output!"
+  exit 1
+fi
+
+projname=`basename $projroot`
+
+# This part we cat in quoted, verbatim.
+cat << 'EOF' >>$output
+
+any_opts=
+list=
+checkout=
+patch=
+cleanup=
+checkin=
+delta=
+help=
+while getopts "lopcidfh" flag; do
+  any_opts=y
+  only_list=y
+  case $flag in
+    l) list=y;;
+    o) checkout=y; only_list=;;
+    p) patch=y; only_list=;;
+    c) cleanup=y; only_list=;;
+    i) checkin=y; only_list=;;
+    d) delta=y; only_list=;;
+    f) checkout=y
+       patch=y
+       cleanup=y
+       checkin=y
+       delta=y
+       only_list=;;
+    h) help=y;;
+    \?) exit 1;
+  esac
+done
+
+EOF
+
+# This part we cat in unquoted, so we can substitute the projname
+# variable.
+
+cat << EOFOUTER >>$output
+if [ \$help ]; then
+cat << 'EOF'
+
+This patch file was generated using get-delta on a remote $projname tree.
+It's designed to be run one time to apply the changes made remotely
+back to the main branch of the tree.
+
+It should be run from within your own view, somewhere within the
+$projname hierarchy on the ClearCase system.
+
+Options:
+
+  -l   List information about the patch file, including the creation
+       date and the list of modified files.
+
+  -o   Checkout all the relevant files and perform other ClearCase
+       operations (like renaming, creating, and removing files).
+
+  -p   Apply the relevant patches to all files after they have been
+       checked out.  If this operation fails, the rest of the script
+       will not continue.
+
+  -c   Cleanup after successfully patching by removing .orig and .rej
+       files.
+
+  -i   Checkin modified files after successfully patching.
+
+  -d   Perform final merge by executing ctdelta on modified files.
+
+  -f   Perform full checkout/patch/merge cycle.  This is equivalent to
+       specifying -opcid.
+
+  -h   This help page.
+
+If no options are specified, the default is -opc.
+
+EOF
+exit 0
+fi
+
+if [ -z "\$any_opts" ]; then
+  checkout=y
+  patch=y
+  cleanup=y
+fi
+EOFOUTER
+
+any_merged=
+
+# We start with the commands given in the project's .ctcmds file.
+ctcmds=$projroot/.ctcmds
+if [ -f $ctcmds ]; then
+  any_merged=y
+  cat $ctcmds >>$temp_checkout
+  if [ $collapse ]; then
+    rm $ctcmds
+  fi
+fi
+  
+
+for ct0 in `cat $temp_ct0`; do
+  dir=`dirname $ct0`
+  base=`basename $ct0 | sed 's/^\.ct0\.//'`
+  file=$dir/$base
+  ctnew=$projroot/$dir/.ctnew.$base
+
+  if (cd $projroot; diff -u $ct0 $file >>$temp_diffs); then
+    # If diff returned success, it means the files were identical.  In
+    # this case, don't bother checking it out.
+    echo "$file is unchanged."
+
+  else
+    # Otherwise, the files were genuinely different.  Check it out on
+    # the remote end.
+    echo $file
+
+    if [ -f $ctnew ]; then
+      # This file is newly created.  We need to create an element for
+      # it on the remote end.
+      eltype=`cat $ctnew`
+      if grep -x $dir $temp_dirs >/dev/null; then 
+        echo directory already checked out >/dev/null
+      else
+        echo "ctco -nc $dir" >>$temp_checkout
+        echo $dir >> $temp_dirs
+      fi
+      echo "touch $file" >>$temp_checkout
+      echo "ctmkelem -eltype $eltype $file << 'EOF' 2>/dev/null" >>$temp_checkout
+      list_comments $projroot/$dir $base >>$temp_checkout
+      echo EOF >>$temp_checkout
+
+      echo $file >> $temp_files
+    else
+      echo "ctco $file << 'EOF' 2>/dev/null" >>$temp_checkout
+      list_comments $projroot/$dir $base >>$temp_checkout
+      echo EOF >>$temp_checkout
+
+      echo $file >> $temp_files
+    fi
+  fi
+
+  if [ $collapse ]; then
+    echo Collapsing $file
+    neartool collapse $projroot/$file
+  fi
+done
+echo ""
+
+# Handle -l, list files modified
+echo "" >>$output
+echo 'if [ $list ]; then' >>$output
+echo '  echo ""' >>$output
+echo '  echo Patch file for '$projname' tree, built on '`date` >> $output
+echo '  echo File was built by '`whoami` on `hostname` >>$output
+echo '  echo ""' >>$output
+echo '  echo Affected files are:' >>$output
+echo '  cat <<EOF' >>$output
+sed "s/^\./  $projname/" $temp_files >>$output
+echo 'EOF' >>$output
+echo '  echo ""' >>$output
+echo 'fi' >>$output
+
+# Everything else depends on being in the proper tree.
+
+cat <<EOF >>$output
+if [ \$only_list ]; then
+  exit 0
+fi
+
+projroot=\`ctproj -r\`
+if [ -z "\$projroot" ]; then
+  echo ""
+  echo "You must execute this script within the $projname tree."
+  echo ""
+  exit 1
+fi
+if [ \`basename \$projroot\` != "$projname" ]; then
+  echo ""
+  echo "This script is intended for the $projname tree."
+  echo ""
+  exit 1
+fi
+if [ ! -d /usr/atria ]; then
+  echo ""
+  echo "This script is intended to be run on an actual ClearCase vobs."
+  echo ""
+  exit 1
+fi
+tmpfile=\`whoami\`-merge-$projname.tmp
+cd \$projroot
+touch \$tmpfile
+EOF
+
+
+# Handle -o, checkout stuff (and perform general ClearCase changes)
+echo "" >>$output
+echo 'if [ $checkout ]; then' >>$output
+if [ -f $temp_checkout ]; then
+  cat $temp_checkout >> $output
+else
+  echo 'echo Nothing to checkout.' >>$output
+fi
+echo 'fi' >>$output
+
+# Handle -p, apply patch
+echo "" >>$output
+echo 'if [ $patch ]; then' >>$output
+if [ -f $temp_diffs ]; then
+  any_merged=y;
+
+  echo "  echo ''" >> $output
+  echo "  echo Applying patches." >> $output
+  echo "  if sed 's/^X//' << 'EOF' | patch -fsu; then" >>$output
+
+  sed 's/^/X/' < $temp_diffs >>$output
+  echo EOF >>$output
+
+  echo "    echo All patches applied successfully." >>$output
+  echo "    echo ''" >>$output
+  echo "  else" >>$output
+  echo "    echo Some conflicts detected:" >>$output
+  echo "    find . -name '*.rej' -newer \$tmpfile -print" >>$output
+  echo "    rm -f \$tmpfile" >>$output
+  echo "    exit 1" >>$output
+  echo "  fi" >>$output
+else
+  echo '  echo No patches to apply.' >>$output
+fi
+echo 'fi' >>$output
+echo "rm -f \$tmpfile" >>$output
+
+# Handle -c, cleanup
+echo "" >>$output
+echo 'if [ $cleanup ]; then' >>$output
+sed 's/^\(.*\)$/  rm -f \1.orig \1.rej/' <$temp_files >>$output
+echo 'fi' >>$output
+
+# Handle -i, checkin
+echo "" >>$output
+echo 'if [ $checkin ]; then' >>$output
+sed 's/^\(.*\)$/  ctci -nc \1/' <$temp_files >>$output
+sed 's/^\(.*\)$/  ctci -nc \1/' <$temp_dirs >>$output
+echo 'fi' >>$output
+
+# Handle -d, delta
+echo "" >>$output
+echo 'if [ $delta ]; then' >>$output
+sed 's/^\(.*\)$/  ctdelta \1/' <$temp_files >>$output
+sed 's/^\(.*\)$/  ctdelta \1/' <$temp_dirs >>$output
+echo 'fi' >>$output
+
+rm -f $temp_ct0 $temp_checkout $temp_dirs $temp_files $temp_diffs
+
+if [ -z "$any_merged" ]; then
+  echo "Nothing to do!"
+  echo ""
+  rm -f $output
+  exit 1
+fi
+

+ 1055 - 0
dtool/src/attach/neartool

@@ -0,0 +1,1055 @@
+#! /usr/local/bin/bash
+#
+# neartool - a Clearcase emulator for working off-line.
+#
+# Usage:
+#
+# neartool mkelem [-c "comment"] [-nc] [-eltype type] filename
+#   Marks a new file as a versioned element and checks it out.
+#
+# neartool mkdir [-c "comment"] [-nc] new_dir
+#   Creates a new Clearcase directory.
+#
+# neartool mv old-file new-file
+#   Renames or moves a versioned element.
+#
+# neartool mv file1 file2 file3 ... to-dir
+#   Moves a number of versioned elements into a new directory.
+#
+# neartool (co|checkout) [-c "comment"] [-nc] filename
+#   "checks out" a file by saving its current version and making a new
+#   version writable.  The file is also marked as "checked-out".
+#
+# neartool (unco|uncheckout) filename
+#   Reverses the effect of the previous checkout.
+#
+# neartool (ci|checkin) [-c "comment"] [-nc] filename
+#   Marks the file as "checked in" and finalizes its most recent
+#   version, making it read-only.
+#
+# neartool revert filename
+#   Backs up a version on a checked-in filename.
+#
+# neartool revertall filename
+#   Reverts a filename all the way to its original state as extracted
+#   from the Clearcase vobs.
+#
+# neartool collapse filename
+#   Collapse all versioning information and mark the file as
+#   "checked-in" and merged as is.  Presumably this should only be
+#   done after merging the changes back into the actual clearcase
+#   vobs.
+#
+# neartool rmname filename
+#   Removes a filename from a Clearcase directory.
+#
+# neartool find root [opts]
+#   Finds all elements with versions at root or below.  The options
+#   are ignored.  This is just a hack to support ctihave.
+#
+# neartool (lsco|lscheckout) [-l] file1 file2 file3...
+#   Lists which of the files are currently checked out, if any.  If no
+#   filenames are given, lists all of the checked out files in the
+#   current directory.  The -l option is ignored.
+#
+# neartool diff [-pre] filename
+#   Performs a diff between the indicated filename and its previous
+#   version.  The option -pre is ignored.
+#
+# neartool xdiff [-pre] filename
+#   Performs an xdiff between the indicated filename and its previous
+#   version.  The option -pre is ignored.
+#
+#ENDCOMMENT
+
+
+#
+# get_nth_param ( param-no param1 param2 param3 ... )
+#
+# Sets the variable nth_param to the value of the parameter
+# corresponding to param-no.
+#
+function get_nth_param {
+  local param_no=$1
+  shift $param_no
+  nth_param=$1
+}
+
+#
+# get_last_param ( param1 param2 param3 ... )
+#
+# Sets the variable last_param to the value of the last non-blank
+# parameter.
+#
+function get_last_param {
+  last_param="$1"
+  shift
+  while [ ! -z "$*" ]; do
+    last_param="$1"
+    shift
+  done
+}
+
+#
+# format_comment ( comment_str )
+#
+# Writes the parameter -c '$comment_str', or -nc if the comment is
+# empty, to the standard output.  Handles nested quotes appropriately.
+#
+function format_comment {
+  local comment="$*"
+
+  if [ -z "$comment" ]; then
+    echo "-nc"
+  else
+    # Escaping single quotes inside a single-quoted string doesn't
+    # seem to work too reliably.  Instead, we'll just remove single
+    # quotes.  So there.
+
+      # This absurd number of backslashes is needed to output a single
+      # backslash through all this nesting.
+      #    echo "-c '"`echo $comment | sed "s/'/\\\\\\\\'/g"`"'"
+    echo "-c '"`echo $comment | sed "s/'//g"`"'"
+  fi
+}
+
+#
+# list_comments ( dirname basename )
+#
+# Writes to stdout any comments associated with checked-out versions of
+# the indicated file, in order.
+#
+function list_comments {
+  local dirname=$1
+  local basename=$2
+  local filename=$dirname/$basename
+  local file comment version
+
+  if [ -f $dirname/.ct0.$basename ]; then
+    # Now look for comments, in version-number order.
+
+    # We use a series of ls commands so we don't try to sort the
+    # filenames between the one-, two-, and three-digit version
+    # numbers.
+
+    for file in `(cd $dirname; ls .ct[0-9].$basename; ls .ct[0-9][0-9].$basename; ls .ct[0-9][0-9][0-9].$basename) 2>/dev/null`; do
+      version=`echo $file | sed "s/^\.ct\([0-9]*\).*$/\1/"`
+      comment=$dirname/.ct${version}comment.$basename
+      if [ -f $comment ]; then
+	sed s'/^/  /' <$comment 
+      fi
+    done
+  fi
+}
+
+#
+# get_highest_version ( dirname basename )
+#
+# Sets the variable $version to the numeric value that is the highest
+# existing version number defined for the given filename.  If the
+# filename has no previous version numbers, sets $version to -1.
+#
+function get_highest_version {
+  local dirname=$1
+  local basename=$2
+  local filename=$dirname/$basename
+  local last
+
+  if [ -f $dirname/.ct0.$basename ]; then
+    # If there are any versions at all, get the highest-numbered one
+    # and return it.
+
+    # We use a series of ls commands so we don't try to sort the
+    # filenames between the one-, two-, and three-digit version
+    # numbers.
+
+    last=`(cd $dirname; ls .ct[0-9].$basename; ls .ct[0-9][0-9].$basename; ls .ct[0-9][0-9][0-9].$basename) 2>/dev/null | tail -1`
+    version=`echo $last | sed "s/^\.ct\([0-9]*\).*$/\1/"`
+  else
+    # If there aren't any versions yet, the highest-numbered existing
+    # version number is -1.
+    version=-1
+  fi
+}
+ 
+#
+# is_ctinternal ( basename )
+#
+# Returns success if the filename matches one of the internal filenames
+# generated by this script, failure if it is a perfectly ordinary
+# non-ct file.
+#
+function is_ctinternal {
+  local basename=$1
+
+  case $basename in
+    .ct[0-9].*|ct[0-9][0-9].*|ct[0-9][0-9][0-9].*|\
+    .ct[0-9]comment.*|.ct[0-9][0-9]comment.*|.ct[0-9][0-9][0-9]comment*|\
+    .ctco.*|.ctnew.*)
+      return 0;;
+  esac
+  return 1
+}
+ 
+#
+# is_install_dir ( dirname )
+#
+# Returns success if the directory is any of the directories known to
+# be install directories, such as inc, lib, lib/ss, etc.
+#
+function is_install_dir {
+  local dirname=$1
+
+  get_rel_dir $projroot $dirname
+
+  case $rel_dir in
+    inc) return 0;;
+    inc/*) return 0;;
+    lib) return 0;;
+    lib/*) return 0;;
+  esac
+  return 1
+}
+
+#
+# rm_all_ctinternals ( dirname basename )
+#
+# Removes all the ctinternal files associated with the indicated file.
+#
+function rm_all_ctinternals {
+  local dirname=$1
+  local basename=$2
+ 
+  rm -f $dirname/.ct[0-9].$basename
+  rm -f $dirname/.ct[0-9][0-9].$basename
+  rm -f $dirname/.ct[0-9][0-9][0-9].$basename
+  rm -f $dirname/.ct[0-9]comment.$basename
+  rm -f $dirname/.ct[0-9][0-9]comment.$basename
+  rm -f $dirname/.ct[0-9][0-9][0-9]comment.$basename
+  rm -f $dirname/.ctnew.$basename
+  rm -f $dirname/.ctco.$basename
+}
+
+#
+# sane_filename ( dirname basename )
+#
+# Performs some sanity checks on the filename.  If the file is
+# unusable, exits the script with a status of 1.
+#
+function sane_filename {
+  local dirname=$1
+  local basename=$2
+  local filename=$dirname/$basename
+
+  if [ -z "$basename" ]; then
+    echo "Filename unspecified." 1>&2
+    exit 1
+  fi
+
+  if is_ctinternal $basename; then
+    echo "$filename is an internal filename and should not be checked out." 1>&2
+    exit 1
+  fi
+
+  # It's easy to accidentally attempt to check something out from the
+  # inc directory.  Let's detect this.
+
+  if is_install_dir $dirname; then
+    echo "$basename is in an install directory." 1>&2
+    echo "It should probably not be checked out." 1>&2
+    exit 1
+  fi
+
+  if [ -d $filename ]; then
+    # Let's just quietly ignore directories.  If we issue the warning
+    # statement, it makes ctaddtgt and ctaddpkg seem like they're
+    # failing.
+    #    echo "Cannot operate on directories." 1>&2
+    exit 0
+  fi
+} 
+
+#
+# get_fullpath ( local_dir )
+#
+# Sets $fullpath to the fully-qualified pathname associated with $local_dir.
+#
+function get_fullpath {
+  local local_dir=$1
+
+  if [ -z "$local_dir" ]; then
+    fullpath=`pwd`
+  else
+    if [ ! -d "$local_dir" ]; then
+      echo "Invalid directory: $local_dir" 1>&2
+      exit 1
+    fi
+    # If we use pwd instead of /bin/pwd, $PWD will be used, which will give
+    # the wrong answer
+    fullpath=`(cd $local_dir; /bin/pwd)`
+  fi
+}
+
+
+#
+# get_rel_dir ( root_dir local_dir )
+#
+# Sets $rel_dir to the string which represents $local_dir relative to
+# $root_dir.  This is a simple string-prefix operation, and could fail
+# in some obscure cases.
+#
+function get_rel_dir {
+  get_fullpath $1
+  local root_dir=$fullpath
+
+  get_fullpath $2
+  local local_dir=$fullpath
+
+  # Now remove the initial prefix.
+  if [ "$root_dir" = "$local_dir" ]; then
+    rel_dir="."
+  else
+    rel_dir=`echo $local_dir | sed 's:^'$root_dir/'::'`
+
+    if [ "$rel_dir" = "$local_dir" ]; then
+      echo "$local_dir is not a directory within $root_dir." 1>&2
+      exit 1
+    fi
+  fi
+}
+
+function ctmkelem {
+  local filename dirname basename
+  local comment eltype
+
+  eltype=text_file
+  while getopts c:n:e: flag; do
+    case $flag in
+      c) comment="$OPTARG";;
+      n) comment="";;
+      e) case $OPTARG in
+         ltype) get_nth_param $OPTIND "$@"
+                eltype=$nth_param
+                OPTIND=`expr $OPTIND + 1`;;
+         *) echo Invalid switch -e$OPTARG
+            exit 1;
+         esac;;
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+
+    sane_filename $dirname $basename
+
+    ctco=$dirname/.ctco.$basename
+    if [ -f $ctco ]; then
+      echo "$filename is already checked out." 1>&2
+      exit 1
+    fi
+
+    if [ ! -f $filename ]; then
+      # If the file doesn't exist, create it.
+      echo -n "" >$filename
+    fi
+
+    get_highest_version $dirname $basename
+  
+    if [ $version -ne -1 ]; then
+      echo "$filename already has versions." 1>&2
+      exit 1
+    fi
+  
+    if [ ! -w $filename ]; then
+      echo "$filename has no write permission, it's probably already a versioned element." 1>&2
+      exit 1
+    fi
+  
+    # Create a ctnew file to indicate the file is newly created.
+    ctnew=$dirname/.ctnew.$basename
+    echo $eltype >$ctnew
+    chmod uga-w $ctnew
+  
+    # Now "check out" the new filename by creating an empty first version.
+  
+    next=$dirname/.ct0.$basename
+    nextcomment=$dirname/.ct0comment.$basename
+  
+    if [ ! -z "$comment" ]; then
+      echo $comment >$nextcomment
+      chmod uga-w $nextcomment
+    fi
+    echo -n "" > $next
+  
+    date >$ctco
+  done
+}
+
+function ctmkdir {
+  local filename dirname basename
+  local comment
+
+  while getopts c:n: flag; do
+    case $flag in
+      c) comment="$OPTARG";;
+      n) comment="";;
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+
+    if [ -z "$basename" ]; then
+      echo "Filename unspecified." 1>&2
+      exit 1
+    fi
+
+    if is_ctinternal $basename; then
+      echo "$filename is an internal filename and should not be checked out." 1>&2
+      exit 1
+    fi
+
+    if mkdir $filename; then 
+      # The directory is successfully made; record this in the
+      # Clearcase instructions.
+      get_rel_dir $projroot $dirname
+      echo "ctco -nc $rel_dir" >>$projroot/.ctcmds
+      echo "ctmkdir `format_comment $comment` $rel_dir/$basename" >>$projroot/.ctcmds
+    else
+      echo "Unable to create directory $filename." 1>&2
+    fi
+  done
+}
+
+#
+# do_ctmv ( oldname newname )
+#
+# The implementation of ctmv.  This renames a single file, possibly
+# placing it in a new directory.
+#
+function do_ctmv {
+  local oldfilename olddirname oldbasename
+  local newfilename newdirname newbasename
+
+  oldfilename=$1
+  olddirname=`dirname $oldfilename`
+  oldbasename=`basename $oldfilename`
+
+  newfilename=$2
+  newdirname=`dirname $newfilename`
+  newbasename=`basename $newfilename`
+
+  sane_filename $olddirname $oldbasename
+  sane_filename $newdirname $newbasename
+
+  if [ ! -f $oldfilename ]; then
+    echo "$oldfilename does not exist." 1>&2
+    exit 1
+  fi
+
+  if [ -f $newfilename ]; then
+    echo "$newfilename already exists--remove it first." 1>&2
+    exit 1
+  fi
+
+  oldctnew=$olddirname/.ctnew.$oldfilename
+
+  if [ ! -f $oldctnew ]; then
+    # The filename exists on the actual Clearcase vobs.  We need to
+    # record the renaming.
+
+    get_rel_dir $projroot $olddirname
+    local oldroot=$rel_dir
+    get_rel_dir $projroot $newdirname
+    local newroot=$rel_dir
+
+    echo "ctco -nc $oldroot" >> $projroot/.ctcmds
+    if [ "$oldroot" != "$newroot" ]; then
+      echo "ctco -nc $newroot" >> $projroot/.ctcmds
+    fi
+    echo "ctmv $oldroot/$oldbasename $newroot/$newbasename" >> $projroot/.ctcmds
+  fi
+
+  # Now rename our local copy, and all of its version tracking stuff.
+  get_fullpath $newdirname
+  local newroot=$fullpath
+
+  (cd $olddirname;
+    for file in \
+      `ls .ct[0-9].$oldbasename \
+          .ct[0-9][0-9].$oldbasename \
+          .ct[0-9][0-9][0-9].$oldbasename \
+          .ct[0-9]comment.$oldbasename \
+          .ct[0-9][0-9]comment.$oldbasename \
+          .ct[0-9][0-9][0-9]comment.$oldbasename \
+          .ctnew.$oldbasename \
+          .ctco.$oldbasename \
+          $oldbasename 2>/dev/null`; do
+      ctprefix=`echo $file | sed 's:'$oldbasename'$::'`
+      mv -i $file $newroot/$ctprefix$newbasename
+    done)
+}
+
+function ctmv {
+  local source destination
+
+  while getopts "" flag; do
+    case $flag in
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  get_last_param "$@"
+  destination=$last_param;
+
+  if [ ! -d "$destination" ]; then
+    # If we're not moving to a directory, we are renaming a file--and
+    # thus we can only allow two parameters.
+    source=$1
+    shift 2
+    if [ ! -z "$*" ]; then
+      echo Last filename must be a directory.
+      exit 1
+    fi
+
+    do_ctmv $source $destination
+  else
+
+    # Otherwise, we're moving a slew of files to a directory.  Get
+    # each filename and move it.
+    for source in "$@"; do
+      if [ "$source" != "$destination" ]; then
+        do_ctmv $source $destination/$source
+      fi
+    done
+  fi
+}
+
+function ctco {
+  local filename dirname basename
+
+  while getopts c:n: flag; do
+    case $flag in
+      c) comment="$OPTARG";;
+      n) comment="";;
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+  
+    sane_filename $dirname $basename
+    okflag=y
+  
+    if [ ! -f $filename ]; then
+      echo "$filename does not exist." 1>&2
+      okflag=
+    else
+      ctco=$dirname/.ctco.$basename
+      if [ -f $ctco ]; then
+        echo "$filename is already checked out." 1>&2
+        okflag=
+      else
+        if [ -w $filename ]; then
+          echo "$filename has write permission, it's probably not a versioned element." 1>&2
+          echo "Try neartool mkelem $filename." 1>&2
+	  okflag=
+        fi
+      fi
+    fi
+
+    if [ ! -z "$okflag" ]; then
+      get_highest_version $dirname $basename
+      next=$dirname/.ct`expr $version + 1`.$basename
+      nextcomment=$dirname/.ct`expr $version + 1`comment.$basename
+  
+      if [ ! -z "$comment" ]; then
+        echo $comment >$nextcomment
+        chmod uga-w $nextcomment
+      fi
+    
+      mv $filename $next
+      cp $next $filename
+      chmod ug+w $filename
+  
+      date >$ctco
+    fi
+  done
+}
+
+
+function ctunco {
+  local ignore filename dirname basename
+
+  while getopts "r:" flag; do
+    case $flag in
+      r) ignore=;;
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+  
+    sane_filename $dirname $basename
+  
+    if [ ! -f $filename ]; then
+      echo "$filename does not exist." 1>&2
+      exit 1
+    fi
+  
+    ctco=$dirname/.ctco.$basename
+    if [ ! -f $ctco ]; then
+      echo "$filename is not checked out." 1>&2
+      exit 1
+    fi
+  
+    get_highest_version $dirname $basename
+    last=$dirname/.ct$version.$basename
+    lastcomment=$dirname/.ct${version}comment.$basename
+  
+    mv -f $last $filename
+    rm -f $lastcomment
+    rm $ctco
+    touch $filename  # For emacs, and correct make behavior.
+  done
+}
+
+
+function ctci {
+  local filename dirname basename
+  local comment
+
+  while getopts c:n: flag; do
+    case $flag in
+      c) comment="$OPTARG";;
+      n) comment="";;
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+  
+    sane_filename $dirname $basename
+  
+    if [ ! -f $filename ]; then
+      echo "$filename does not exist." 1>&2
+      exit 1
+    fi
+  
+  
+    ctco=$dirname/.ctco.$basename
+    if [ ! -f $ctco ]; then
+      echo "$filename is not checked out." 1>&2
+      exit 1
+    fi
+  
+    # We touch the file, so emacs will note that it has changed.
+    touch $filename
+    chmod uga-w $filename
+  
+    rm $ctco
+  done
+}
+
+
+function ctrevert {
+  local filename dirname basename
+
+  while getopts "" flag; do
+    case $flag in
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+  
+    sane_filename $dirname $basename
+  
+    if [ ! -f $filename ]; then
+      echo "$filename does not exist." 1>&2
+      exit 1
+    fi
+  
+    ctco=$dirname/.ctco.$basename
+    if [ -f $ctco ]; then
+      echo "$filename is currently checked out.  Use neartool unco $filename." 1>&2
+      exit 1
+    fi
+  
+    get_highest_version $dirname $basename
+  
+    if [ $version -eq -1 ]; then
+      echo "$filename has no versions." 1>&2
+      exit 1
+    fi
+  
+    last=$dirname/.ct$version.$basename
+    lastcomment=$dirname/.ct${version}comment.$basename
+  
+    mv -f $last $filename
+    rm -f $lastcomment
+  
+    if [ $version -eq 0 ]; then
+      ctnew=$dirname/.ctnew.$basename
+      if [ -f $ctnew ]; then
+        echo "Removing newly created element $filename." 1>&2
+        rm -f $ctnew $filename
+      fi
+    fi
+  done
+}
+
+function ctrevertall {
+  local filename dirname basename
+
+  while getopts "" flag; do
+    case $flag in
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+  
+    sane_filename $dirname $basename
+  
+    if [ ! -f $filename ]; then
+      echo "$filename does not exist." 1>&2
+      exit 1
+    fi
+  
+    ct0=$dirname/.ct0.$basename
+    if [ ! -f $ct0 ]; then
+      echo "$filename has no versions." 1>&2
+    else
+      ctnew=$dirname/.ctnew.$basename
+      if [ ! -f $ctnew ]; then
+        # If we didn't newly create this file, preserve its original version.
+        mv -f $ct0 $filename
+      fi
+      rm_all_ctinternals $dirname $basename
+    fi
+  done
+}
+
+function ctcollapse {
+  local filename dirname basename
+
+  while getopts "" flag; do
+    case $flag in
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+  
+    sane_filename $dirname $basename
+  
+    if [ ! -f $filename ]; then
+      echo "$filename does not exist." 1>&2
+      exit 1
+    fi
+
+    rm_all_ctinternals $dirname $basename
+  
+    chmod uga-w $filename
+    touch $filename  # For Emacs' benefit.
+  done
+}
+
+function ctrmname {
+  local filename dirname basename
+  while getopts "" flag; do
+    case $flag in
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+  
+    sane_filename $dirname $basename
+  
+    if [ ! -f $filename ]; then
+      echo "$filename does not exist." 1>&2
+      exit 1
+    fi
+  
+    ctnew=$dirname/.ctnew.$basename
+  
+    if [ ! -f $ctnew ]; then
+      # The filename exists on the actual Clearcase vobs.  We need to
+      # record the removing.
+  
+      get_rel_dir $projroot $dirname
+      local root=$rel_dir
+  
+      echo "ctco -nc $root" >> $projroot/.ctcmds
+      echo "ctrm $root/$basename" >> $projroot/.ctcmds
+    fi
+
+    # Now remove all of the versioned stuff.
+    ctcollapse $filename
+
+    # And remove the file itself.
+    rm -f $filename
+  done
+}
+
+
+function ctfind {
+  local root=$1
+
+  if [ -z "$root" ]; then
+    echo "Specify a starting point of the find." 1>&2
+    exit 1
+  fi
+
+  find $root -name .ct0.\* -print | sed 's/\.ct0\.//'
+}
+
+function ctdescribe {
+  local filename dirname basename
+
+  while getopts "" flag; do
+    case $flag in
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in `ls "$@"`; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+
+    ctco=$dirname/.ctco.$basename
+    get_highest_version $dirname $basename
+    version=`expr $version + 1`
+
+    if [ -f $ctco ]; then
+      if [ $version -eq 0 ]; then
+        echo "$filename is checked out with no versions."
+      else
+        echo "$filename is checked out as version $version."
+	list_comments $dirname $basename
+      fi
+    else
+      if [ $version -eq 0 ]; then
+        echo "$filename has not been checked out and has no versions."
+      else
+        echo "$filename is checked in as version $version."
+	list_comments $dirname $basename
+      fi
+    fi
+  done
+}
+
+function ctlsco {
+  local filename dirname basename
+  local ignore
+  while getopts "l" flag; do
+    case $flag in
+      l) ignore=;;
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  for filename in `ls "$@"`; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+
+    ctco=$dirname/.ctco.$basename
+    if [ -f $ctco ]; then
+      ctdescribe $filename
+    fi
+  done
+}
+
+function ctdiff {
+  local filename dirname basename
+  local graphical
+  local ignore
+  local diff
+
+  while getopts "gp:" flag; do
+    case $flag in
+      g) graphical=y;;
+      p) ignore=;;
+      \?) exit 1;
+    esac
+  done
+  shift `expr $OPTIND - 1`
+
+  diff=diff
+  if [ $graphical ]; then
+    # The user requested a graphical difference; use gdiff if we can
+    # find it.  Otherwise, fall back to diff.
+    if which gdiff 2>/dev/null >/dev/null; then
+      diff=gdiff
+    fi
+  fi
+
+  if [ -z "$1" ]; then
+    echo "No filenames given."
+    exit 1
+  fi
+
+  for filename in "$@"; do
+    dirname=`dirname $filename`
+    basename=`basename $filename`
+  
+    sane_filename $dirname $basename
+  
+    if [ ! -f $filename ]; then
+      echo "$filename does not exist." 1>&2
+      exit 1
+    fi
+  
+    get_highest_version $dirname $basename
+  
+    if [ $version -eq -1 ]; then
+      echo "$filename has no versions." 1>&2
+      exit 1
+    fi
+  
+    last=$dirname/.ct$version.$basename
+
+    # First, call diff (the real diff) just to see if the files are
+    # different at all.
+
+    if diff $last $filename >/dev/null; then
+      echo Files are identical.
+
+    else
+      # If the files ARE different, then invoke diff again (which
+      # might be gdiff, this time) to actually report the differences.
+      # We must do it twice like this because gdiff might not return
+      # non-zero if the files are different.
+
+      $diff $last $filename
+    fi
+  done
+}
+
+
+function usage {
+  sed '/#ENDCOMMENT/,$d' <$0 >&2
+  exit 1
+}
+
+
+#
+# Main entry point
+#
+
+command=$1
+if [ -z "$command" ]; then
+  usage
+fi
+
+shift
+
+projroot=`ctproj -r`
+
+if [ -z "$projroot" ]; then
+  echo "Not currently in a project tree." 1>&2
+  exit 1
+fi
+
+case $command in
+  mkelem) ctmkelem "$@";;
+  mkdir) ctmkdir "$@";;
+  mv) ctmv "$@";;
+  co|checkout) ctco "$@";;
+  unco|uncheckout) ctunco "$@";;
+  ci|checkin) ctci "$@";;
+  revert) ctrevert "$@";;
+  revertall) ctrevertall "$@";;
+  collapse) ctcollapse "$@";;
+  rmname) ctrmname "$@";;
+  find) ctfind "$@";;
+  lsco|lscheckout) ctlsco "$@";;
+  describe) ctdescribe "$@";;
+  diff) ctdiff "$@";;
+  xdiff) ctdiff -g "$@";;
+  h|help|-h) usage;;
+  *)  echo "Invalid option: $command" 1>&2
+      exit 1;
+esac

+ 31 - 0
dtool/src/attach/unco.pl

@@ -0,0 +1,31 @@
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctdelta.pl" ;
+
+# Remove a branch for an element if needed
+# input is in:
+# $_[0] = element
+sub CTUncoDoIt {
+   local( $elem ) = $_[0] ;
+   local( $ver ) = &CTDeltaGetVersion( $elem ) ;
+   if ( $ctdebug ne "" ) {
+      print STDERR "Unco script: got version '" . $ver . "'\n" ;
+   }
+   local( @verlist ) ;
+   @verlist = split( /\//, $ver ) ;
+   local( $vlast ) = pop( @verlist ) ;
+   if ( $ctdebug ne "" ) {
+      print STDERR "Unco script: last part of version is '" . $vlast . "'\n" ;
+   }
+   if ( $#verlist > 1 ) {
+      local( $branch ) = join( "/", @verlist ) ;
+      if ( $vlast == 0 ) {
+         local( $cmd ) = "cleartool rmbranch -force -nc $elem" . "@@" . "$branch" ;
+         if ( $ctdebug ne "" ) {
+	    print STDERR "Unco script: command is '" . $cmd . "'\n" ;
+	 }
+	 system $cmd ;
+      }
+   }
+}
+
+1;

+ 189 - 0
dtool/src/attach/update-cttree

@@ -0,0 +1,189 @@
+#! /bin/sh
+#
+# update-cttree.sh
+#
+# Usage:
+# 
+# update-cttree.sh [opts] hostname
+#
+# Uses rsh and rdist to update the indicated host with a fresh copy of the 
+# current project tree.
+#
+# This script must be executed from within a project tree.
+#
+# Options:
+#
+#   -u username  Specify the login name on the remote host.
+#
+#   -d dir       Specify the player install dir on the remote host.  This
+#                the directory above the project-tree-specific directory
+#                like 'panda' or 'tool'.  The default is 'player'.
+#
+#   -t           Touch the build-request timestamp file after updating.
+#                This assumes there's a cron job running on the remote
+#                machine checking the date on this file from time to time.
+#
+#   -f           Assume the user knows what he/she is doing, and don't bother
+#                to check that there are no files checked out in the vobs
+#                before releasing.  This can save considerable time when the
+#                system is extremely slow; however, it can be dangerous
+#                to accidentally release a checked-out file (because the
+#                file will then be write-access on the remote host, and
+#                neartool will not be able to track local changes made to it.)
+#
+#ENDCOMMENT
+
+username=`whoami`
+dirname=player
+touch_request=
+cocky_user=
+
+while getopts "u:d:tfh" flag; do
+  case $flag in
+    u) username=$OPTARG;;
+    d) dirname=$OPTARG;;
+    t) touch_request=y;;
+    f) cocky_user=y;;
+    h) sed '/#ENDCOMMENT/,$d' <$0 >&2
+       exit 1;;
+    \?) exit 1;
+  esac
+done
+
+shift `expr $OPTIND - 1`
+remote_host=$1
+projroot=`ctproj -r`
+
+if [ -z "$projroot" ]; then
+  echo ""
+  echo "You must execute this script in a project tree."
+  echo ""
+  exit 1
+fi
+
+if [ -z "$remote_host" ]; then
+  echo ""
+  echo "You must specify a remote hostname.  -h for help."
+  echo ""
+  exit 1
+fi
+
+if [ ! -d /usr/atria ]; then
+  echo ""
+  echo "This script is intended to be run on an actual ClearCase vobs."
+  echo ""
+  exit 1
+fi
+
+projname=`basename $projroot`
+projtop=`dirname $projroot`
+
+if [ "$projname" = "tool" ]; then
+  echo ""
+  echo "This script should not be used on the tool tree."
+  echo ""
+  exit 1
+fi
+
+outfile=/tmp/uc.$username.$projname.$remote_host.out
+errfile=/tmp/uc.$username.$projname.$remote_host.err
+rm -f $outfile $errfile
+
+# Check to make sure we can run rsh to the remote machine, and that
+# the remote machine doesn't have anything checked out.
+
+if rsh $remote_host -l $username "cd $dirname; find $projname -name .ct0.\* -print" >$outfile 2>$errfile; then
+  if [ ! -f $outfile ]; then
+    echo ""
+    echo "Error in processing; unable to generate $outfile."
+    echo ""
+    rm -f $outfile $errfile
+    exit 1
+  fi
+  if [ ! -f $errfile ]; then
+    echo ""
+    echo "Error in processing; unable to generate $errfile."
+    echo ""
+    rm -f $outfile $errfile
+    exit 1
+  fi
+  if [ -s $errfile ]; then
+    echo ""
+    echo "Unable to scan project tree $dirname/$projname on $remote_host."
+    echo ""
+    rm -f $outfile $errfile
+    exit 1
+  fi
+  if [ -s $outfile ]; then
+    echo ""
+    echo "Cannot update $remote_host; files still checked out on remote:"
+    sed 's/^/  /;s/\.ct0\.//' $outfile
+    rm -f $outfile $errfile
+    echo ""
+    exit 1
+  fi
+else
+  echo ""
+  echo "Cannot rsh to $remote_host as $username."
+  echo ""
+  rm -f $outfile $errfile
+  exit 1
+fi
+
+# Check to make sure the local machine doesn't have anything checked out.
+if [ -z "$cocky_user" ]; then
+  cd $projroot
+  cleartool lsco -s -me -recurse >$outfile
+  if [ -s $outfile ]; then
+    echo ""
+    echo "Cannot update from "`hostname`"; files still checked out in vobs:"
+    sed 's/^/  /;s/\.ct0\.//' $outfile
+    rm -f $outfile $errfile
+    echo ""
+    exit 1
+  fi
+fi
+
+rm -f $outfile $errfile
+
+
+#
+# Get the complete list of files in the tree we need to update.
+#
+cd $projtop
+filelist=${outfile}.files
+rm -f $filelist
+cleartool find $projname -nxn -print | grep -v '/lost+found' > $filelist
+
+#
+# Now build up a number of rdist files, as needed, to update these files.
+# We have to do this in stages because there seems to be a limit of about
+# 2000 files in one rdist file.
+#
+numlines=`wc -l $filelist | awk '{ print $1 }'`
+echo $projname contains $numlines files.
+
+startline=1
+while [ $startline -le $numlines ]; do
+  echo "FILES = (" >> $outfile
+  tail +$startline $filelist | head -2000 >> $outfile
+  echo ")" >> $outfile
+
+  echo '${FILES} -> '$username@$remote_host >>$outfile
+  echo "	install $dirname;" >> $outfile
+
+  if [ $touch_request ]; then
+    echo "  cmdspecial \"touch $dirname/$projname/build-request\" ;" >>$outfile
+  fi
+
+  if rdist -onochkowner,nochkgroup,numchkgroup,whole,nodescend -f $outfile; then
+    rm -f $outfile
+  else
+    echo "Error in rdist."
+    rm -f $outfile $filelist $errfile
+    exit 1
+  fi
+  startline=`expr $startline + 2000`
+done
+
+rm -f $filelist $errfile

+ 50 - 0
dtool/src/build/Makefile.a.rules

@@ -0,0 +1,50 @@
+# Makefile for .a archive libraries
+
+# We *do* need -prelink when making an archive of C++ code.  To
+# facilitate this, we use the C++ compiler to build the archive.  This
+# is only necessary, of course, on SGI.
+
+ALLOFILES := $(ALLOFILES) $(OFILES)
+
+
+ifeq (,$(USE_DEFERRED))
+  DEFERRED_TARGET :=
+endif
+
+ifneq (,$(DEFERRED_TARGET))
+
+  # If the makefile requests a "deferred target", it means that we'll
+  # just write out a mini-makefile that defines the .o files that go
+  # into the target, rather than actually building the target now.
+  # Another Makefile later will presumably do the actual building.
+
+  DEFERRED_MAKEFILE := Deferred.$(DEFERRED_TARGET).$(BASETARGET)
+  THISDIR := $(notdir $(shell pwd))
+
+$(TARGET) : $(DEFERRED_MAKEFILE)
+$(DEFERRED_MAKEFILE):
+	rm -f $@
+	echo ALLOFILES += $(patsubst ./%,../../$(THISDIR)/%,$(ALLOFILES)) > $@
+
+else # DEFERRED_TARGET
+
+  ifneq (,$(strip $(ALLOFILES)))
+  $(TARGET): $(OFILES)   # *not* ALLOFILES
+    ifeq (SGI,$(PENV))
+	$(C++) -ar -o $@ $(ALLOFILES) 
+    else
+	$(AR) $(ARFLAGS) $@ $(ALLOFILES) 
+    endif
+  endif
+
+endif # DEFERRED_TARGET
+
+clean::
+	@rm -f a.out.$(TARGET)
+
+cleanall: clean
+	rm -rf ii_files
+	rm -f $(TARGET)
+
+list:
+	@echo $(TARGET)

+ 23 - 0
dtool/src/build/Makefile.a.template

@@ -0,0 +1,23 @@
+#### Makefile for archive libraries.  Any fields commented out are optional.
+
+#### Target's name:
+#CTTARGET
+
+#CTINCLUDE $DTOOL/lib/Makefile.o.include
+
+#### Pull in standard binary make variables.
+include $(DTOOL)/inc/Makefile.bin.vars
+
+#### Other .o files.
+# OFILES = 
+
+#### Libs and flags for template instantiation.
+# LIBS = 
+# LDFLAGS = 
+
+#### Archiver flags
+# ARFLAGS = 
+
+#### The .a action is here.
+include $(DTOOL)/inc/Makefile.a.rules
+

+ 69 - 0
dtool/src/build/Makefile.bin.rules

@@ -0,0 +1,69 @@
+# Rules to construct a binary from .o files
+
+ALLOFILES := $(ALLOFILES) $(OFILES)
+
+ifeq (,$(USE_DEFERRED))
+  LIBS := $(WHEN_NO_DEFER_LIBS) $(LIBS)
+else
+  LIBS := $(WHEN_DEFER_LIBS) $(LIBS)
+endif
+
+# Eliminate -lm and -ldl on NT because they don't exist
+WINLIBS := $(filter-out -lm -ldl,$(SYSLIBS))
+# On NT -l<library> needs to map to lib<library>.lib
+WINLIBS := $(LIBS:-l%=lib%$(DEBUGNAME).lib) $(WINLIBS:-l%=lib%.lib)
+
+ifeq (PS2,$(PENV))
+  LDFLAGS += -lm -nostartfiles
+endif  # (PS2,$(PENV))
+
+ifneq (,$(strip $(ALLOFILES)))
+$(TARGET): $(OFILES)  # *not* ALLOFILES
+
+# PS2 MODIFICATION ###################
+
+ifeq (PS2, $(PENV))
+	$(LD) $(LDFLAGS) $(ALLOFILES) $(LPATH) $(LIBS) $(SYSLIBS) -T /for/program/sce/ee/lib/app.cmd -o a.out.$@
+	mv a.out.$@ [email protected]
+else
+
+# END PS2 MOD ########################
+
+ifeq (WIN32_VC,$(PENV_COMPILER))
+	$(LD) $(LDFLAGS) $(LPATH) $(LINKFLAGS) $(ALLOFILES) $(WINLIBS) -OUT:a.out.$@
+	mv a.out.$@ $@
+else # NON-WIN32_VC
+	$(LD) $(LDFLAGS) $(LPATH) $(LINKFLAGS) $(ALLOFILES) $(LIBS) $(SYSLIBS) -o a.out.$@
+	mv a.out.$@ $@
+endif # WIN32_VC
+endif # PS2
+
+ifeq (4,$(OPTIMIZE))
+	strip $@
+endif
+endif
+
+EXPBIN =
+ILKBIN =
+PDBBIN =
+LIBBIN =
+VCFILES =
+ifeq (WIN32_VC,$(PENV_COMPILER))
+  EXPBIN := $(BASETARGET:%=a.out.%.exp)
+  ILKBIN := $(BASETARGET:%=a.out.%.ilk)
+  PDBBIN := $(BASETARGET:%=a.out.%.pdb)
+  LIBBIN := $(BASETARGET:%=a.out.%.lib)
+  VCFILES := vc60.idb vc60.pdb
+endif # WIN32_VC
+
+clean::
+	@rm -f a.out.$(TARGET) $(EXPBIN) $(ILKBIN) $(PDBBIN) $(LIBBIN) \
+		$(VCFILES)
+
+cleanall: clean
+	rm -rf ii_files
+	rm -f $(TARGET) $(EXPBIN) $(ILKBIN) $(PDBBIN) $(LIBBIN) \
+		$(VCFILES)
+
+list:
+	@echo $(TARGET)

+ 23 - 0
dtool/src/build/Makefile.bin.template

@@ -0,0 +1,23 @@
+#### Makefile for binaries.  Any fields commented out are optional.
+
+#### Target's name:
+#CTTARGET
+
+#CTINCLUDE $DTOOL/lib/Makefile.o.include
+
+#### Pull in standard binary make variables.
+include $(DTOOL)/inc/Makefile.bin.vars
+
+#### Other files and lib.  Include $(ODIR) in any .o names.
+# OFILES = 
+# LIBS = 
+
+#### Additional search directories for lib:
+# LPATH := $(LPATH) -L/my/directory -L/my/other/directory
+
+#### Other linker flags. 
+# LDFLAGS = 
+
+#### The bin action is here.
+include $(DTOOL)/inc/Makefile.bin.rules
+

+ 121 - 0
dtool/src/build/Makefile.bin.vars

@@ -0,0 +1,121 @@
+# Pull in the .o vars if they haven't been read already
+ifeq (,$(MAKEFILE_O_VARS))
+include $(DTOOL)/inc/Makefile.o.vars
+endif
+
+# Get the project root
+ifeq (,$(CTPROJROOT))
+CTPROJROOT := $(shell $(DTOOL)/bin/ctproj -root)
+export CTPROJROOT
+endif
+
+# Set the SOLOCATIONS file
+SOLOCATIONS := ../../etc/so_locations
+
+# Make sure CT_LIBRARY_PATH is set.
+ifeq (,$(CT_LIBRARY_PATH))
+ifneq (,$(LD_LIBRARY_PATH))
+export CT_LIBRARY_PATH := $(LD_LIBRARY_PATH)
+else
+export CT_LIBRARY_PATH = .
+endif
+endif
+
+LPATH_DIRS := $(strip $(shell ctpathadjust $(subst :, ,$(CT_LIBRARY_PATH)))) $(patsubst -L%,%,$(LPATH))
+
+ifeq (WIN32_VC,$(PENV_COMPILER))
+  lt := $(foreach path,$(LPATH_DIRS),$(shell cygpath -w $(path)))
+  LPATH := $(patsubst %,-LIBPATH:"%",$(lt)) 
+else # NON-WIN32_VC
+  LPATH := $(patsubst %,-L%,$(LPATH_DIRS))
+endif # WIN32_VC
+
+ifeq (SGI,$(PENV))
+  CLDFLAGS = -Wl,-force_load -Wl,-transitive_link
+  C++LDFLAGS = -Wl,-demangle -Wl,-force_load -Wl,-transitive_link
+endif
+
+# Figure out what the linker is.  Start with simple defaults.
+
+ifeq (PS2, $(PENV))
+  AR = ee-ar
+  LD = ee-ld
+else
+  AR = ar
+  LD = ld
+endif
+
+LDFLAGS = 
+LINKFLAGS =
+
+# C files
+ifneq (,$(CFILES))   
+LD := $(CC)
+LDFLAGS := $(CLDFLAGS) $(CFLAGS)
+endif
+
+# C++ files
+ifneq (,$(C++FILES)) # If there are C++ files, make it CC
+LD := $(C++)
+LDFLAGS := $(C++LDFLAGS) $(C++FLAGS)
+endif
+
+# C files in the OFILES list 
+ifneq (,$(findstring .c,$(suffix $(OFILES))))
+LD := $(CC)
+LDFLAGS := $(IPATH) $(CLDFLAGS) $(CFLAGS)
+endif
+
+# C++ files in the OFILES list
+ifneq (,$(findstring .cxx,$(suffix $(OFILES))))
+LD := $(C++)
+LDFLAGS := $(IPATH) $(C++LDFLAGS) $(C++FLAGS)
+endif
+
+# Making a DSO - use C++ for now
+ifeq (.so,$(suffix $(TARGET)))
+LD := $(C++)
+LDFLAGS := $(IPATH) $(C++LDFLAGS) $(C++FLAGS)
+endif
+
+# Making a DLL - use C++ for now
+ifeq (.dll,$(suffix $(TARGET)))
+LD := $(C++)
+LDFLAGS := $(C++LDFLAGS) $(C++FLAGS)
+endif
+
+# Making a WIN binary file
+ifeq (WIN32,$(PENV))
+  LD = link
+  LDFLAGS = -NOLOGO 
+
+  ifeq (4,$(OPTIMIZE))
+      LINKFLAGS += -fixed:no
+  else
+    ifeq (3,$(OPTIMIZE))
+      LINKFLAGS += -fixed:no
+    else
+      LINKFLAGS += -debug -incremental:no
+    endif
+  endif
+endif
+
+ARFLAGS = ruv
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 74 - 0
dtool/src/build/Makefile.foreign.rules

@@ -0,0 +1,74 @@
+##############################################################################
+#
+# Foreign package building rules
+#
+
+# Clear ALLTARGETS
+ALLTARGETS = 
+
+ifneq (,$(COMMAND1))
+ALLTARGETS := $(ALLTARGETS) $(TARGET)_COMMAND1_RULE
+ifeq (,$(DIR1))
+DIR1 = .
+endif
+$(TARGET)_COMMAND1_RULE:
+	@ echo "**** executing subcommand '$(COMMAND1)'"
+	@ cd $(STARTDIR)/$(DIR1) ; $(COMMAND1)
+.PHONY: $(TARGET)_COMMAND1_RULE
+endif
+
+ifneq (,$(COMMAND2))
+ALLTARGETS := $(ALLTARGETS) $(TARGET)_COMMAND2_RULE
+ifeq (,$(DIR2))
+DIR2 = .
+endif
+$(TARGET)_COMMAND2_RULE:
+	@ echo "**** executing subcommand '$(COMMAND2)'"
+	@ cd $(STARTDIR)/$(DIR2) ; $(COMMAND2)
+.PHONY: $(TARGET)_COMMAND2_RULE
+endif
+
+ifneq (,$(COMMAND3))
+ALLTARGETS := $(ALLTARGETS) $(TARGET)_COMMAND3_RULE
+ifeq (,$(DIR3))
+DIR3 = .
+endif
+$(TARGET)_COMMAND3_RULE:
+	@ echo "**** executing subcommand '$(COMMAND3)'"
+	@ cd $(STARTDIR)/$(DIR3) ; $(COMMAND3)
+.PHONY: $(TARGET)_COMMAND3_RULE
+endif
+
+ifneq (,$(COMMAND4))
+ALLTARGETS := $(ALLTARGETS) $(TARGET)_COMMAND4_RULE
+ifeq (,$(DIR4))
+DIR4 = .
+endif
+$(TARGET)_COMMAND4_RULE:
+	@ echo "**** executing subcommand '$(COMMAND4)'"
+	@ cd $(STARTDIR)/$(DIR4) ; $(COMMAND4)
+.PHONY: $(TARGET)_COMMAND4_RULE
+endif
+
+ifneq (,$(COMMAND5))
+ALLTARGETS := $(ALLTARGETS) $(TARGET)_COMMAND5_RULE
+ifeq (,$(DIR5))
+DIR5 = .
+endif
+$(TARGET)_COMMAND5_RULE:
+	@ echo "**** executing subcommand '$(COMMAND5)'"
+	@ cd $(STARTDIR)/$(DIR5) ; $(COMMAND5)
+.PHONY: $(TARGET)_COMMAND5_RULE
+endif
+
+# now if there's anything to do, do it
+ifneq (,$(ALLTARGETS))
+$(TARGET): $(ALLTARGETS)
+endif
+
+clean::
+
+cleanall: clean
+
+list:
+	@ echo $(TARGET)

+ 28 - 0
dtool/src/build/Makefile.foreign.template

@@ -0,0 +1,28 @@
+#### Makefile for foreign packages.  Any fields commented out are optional.
+
+#### Target's name:
+#CTTARGET
+
+#### Pull in standard foreign package make variables
+include $(DTOOL)/inc/Makefile.foreign.vars
+
+#### commands for building a foreign package.  DIR?, if ommitted, defaults to
+#### '.'.  COMMAND?, if ommitted, does nothing.
+# DIR1 = 
+# COMMAND1 = 
+
+# DIR2 = 
+# COMMAND2 = 
+
+# DIR3 = 
+# COMMAND3 = 
+
+# DIR4 = 
+# COMMAND4 = 
+
+# DIR5 = 
+# COMMAND5 = 
+
+
+#### The foreign package build action is here.
+include $(DTOOL)/inc/Makefile.foreign.rules

+ 19 - 0
dtool/src/build/Makefile.foreign.vars

@@ -0,0 +1,19 @@
+# Standard variables for building foreign packages
+
+ifeq (,$(MAKEFILE_FOREIGN_VARS))
+MAKEFILE_FOREIGN_VARS = TRUE
+
+ifeq (,$(MAKEFILE_PENV_VARS))
+include $(DTOOL)/inc/Makefile.penv.vars
+endif
+
+# Delete the default suffixes
+.SUFFIXES:
+
+# get a dir to cd to
+STARTDIR = `ctproj -r`/src/all/$(TARGET)
+
+# Set the default target
+install all : $(TARGET)
+
+endif

+ 891 - 0
dtool/src/build/Makefile.install.rules

@@ -0,0 +1,891 @@
+#### Makefile install rules.  Setup. 
+strip-target = `echo $@ | sed 's/^[^-]*-//'`
+
+# Yank out any whitespace in the package name.
+PACKAGE := $(strip $(PACKAGE))
+
+# Pull in standard install make variables.
+ifeq (,$(MAKEFILE_INSTALL_VARS))
+include $(DTOOL)/inc/Makefile.install.vars
+endif
+
+# We need this one to define DEBUGNAME for us.
+ifeq (,$(MAKEFILE_O_VARS))
+include $(DTOOL)/inc/Makefile.o.vars
+endif
+
+# Infer the package root from the package name, if not already set.
+ifeq (,$(PKGROOT))
+PKGROOT = src/all/$(PACKAGE)
+else
+PKGROOT := $(strip $(PKGROOT))
+endif
+
+
+# First target.  Convenient synonym for install.
+$(PACKAGE): install-$(PACKAGE)
+$(PKGROOT): install-$(PKGROOT)
+
+
+
+#### File install actions
+#
+# This section constructs lists of installed files, and the source files
+# from which they are copied.  Then the user supplied list is cleared.
+# This is because this rules file is included in the project Makefile
+# more than once, and we'd rather not have one package's file list
+# affecting the installation of another package that follows it.
+#
+# Each installed file depends on the existence of a source file from
+# which to copy it.  Each block below is for a different installation
+# directory.  The ALLSRC and ALLINST lists will be used in the next sections 
+# of the rules.  More such blocks may be added by following the pattern.
+#
+
+ALLSRC = 
+ALLINST = 
+
+
+# DEFERRED supplied by package's Makefile.install.  If defined (and
+# not overridden in Makefile.penv.vars), this indicates that a
+# deferred build is requested by the makefiles in this package, and we
+# should install only the output of these deferred builds.  This,
+# therefore, overrides any request to install LIBS.
+
+ifeq (,$(USE_DEFERRED))
+  DEFERRED :=
+endif
+
+ifeq (PS2, $(PENV))
+  SOLIBS := $(filter %.so,$(LIBS))
+  SOLIBS := $(SOLIBS:%.so=%.a)
+  ALIBS := $(filter %.a,$(LIBS))
+  LIBS := $(SOLIBS)
+  LIBS += $(ALIBS)
+endif
+
+SRCDEFERRED := $(addprefix $(PKGROOT)/,$(DEFERRED))
+ALLSRC := $(ALLSRC) $(SRCDEFERRED)
+INSTDEFERRED := $(addprefix deferred/,$(DEFERRED))
+ALLINST := $(ALLINST) $(INSTDEFERRED)
+DEFERRED = 
+
+ifneq (,$(INSTDEFERRED))
+$(INSTDEFERRED): deferred/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+# LIBS supplied by package's Makefile.install.
+ifeq (WIN32,$(PENV))
+  SOLIBS := $(filter %.so,$(LIBS))
+  SOLIBS := $(SOLIBS:%.so=%$(DEBUGNAME).dll)
+  ALIBS := $(filter %.a,$(LIBS))
+  ALIBS := $(ALIBS:%.a=%$(DEBUGNAME).lib)
+  LIBS := $(SOLIBS:%.dll=%.lib)
+  LIBS += $(ALIBS)
+  LIBS += $(SOLIBS)
+endif # WIN32
+ifeq (OSX,$(PENV))
+  SOLIBS := $(filter %.so,$(LIBS))
+  SOLIBS := $(SOLIBS:%.so=%.dylib)
+  ALIBS := $(filter %.a,$(LIBS))
+  LIBS := $(ALIBS)
+  LIBS += $(SOLIBS)
+endif # OSX
+
+SRCLIBS := $(addprefix $(PKGROOT)/,$(LIBS))
+ALLSRC := $(ALLSRC) $(SRCLIBS)
+INSTLIBS := $(addprefix lib/,$(LIBS))
+ALLINST := $(ALLINST) $(INSTLIBS)
+LIBS = 
+
+ifeq (,$(INSTDEFERRED))
+  ifneq (,$(INSTLIBS))
+    $(INSTLIBS): lib/% : $(PKGROOT)/%
+	$(MKINSTALL)
+  endif
+else
+  ifneq (,$(INSTLIBS))
+    $(INSTLIBS):
+  endif
+endif
+  
+
+# INCLUDE supplied by package's Makefile.install.
+INCLUDE := $(strip $(INCLUDE))
+SRCINCLUDE := $(addprefix $(PKGROOT)/,$(INCLUDE))
+ALLSRC := $(ALLSRC) $(SRCINCLUDE)
+INSTINCLUDE := $(addprefix inc/,$(INCLUDE))
+ALLINST := $(ALLINST) $(INSTINCLUDE)
+INCLUDE = 
+
+ifneq (,$(INSTINCLUDE))
+$(INSTINCLUDE): inc/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# BINS supplied by package's Makefile.install.
+BINS := $(strip $(BINS))
+ifeq (WIN32,$(PENV))
+  BINS := $(BINS:%=%.exe)
+endif
+SRCBINS := $(addprefix $(PKGROOT)/,$(BINS))
+ALLSRC := $(ALLSRC) $(SRCBINS)
+INSTBINS := $(addprefix bin/,$(BINS))
+ALLINST := $(ALLINST) $(INSTBINS)
+BINS = 
+
+ifneq (,$(INSTBINS))
+  $(INSTBINS): bin/% : $(PKGROOT)/%
+	$(MKINSTALL)
+	@chmod +x $@
+endif
+
+
+# SCRIPTS supplied by package's Makefile.install.
+SCRIPTS := $(strip $(SCRIPTS))
+SRCSCRIPTS := $(addprefix $(PKGROOT)/,$(SCRIPTS))
+ALLSRC := $(ALLSRC) $(SRCSCRIPTS)
+INSTSCRIPTS := $(addprefix bin/,$(SCRIPTS))
+ALLINST := $(ALLINST) $(INSTSCRIPTS)
+SCRIPTS = 
+
+ifneq (,$(INSTSCRIPTS))
+$(INSTSCRIPTS): bin/% : $(PKGROOT)/%
+	$(MKINSTALL)
+	@chmod +x $@
+endif
+
+
+# SS supplied by package's Makefile.install.
+SS := $(strip $(SS))
+SRCSS := $(addprefix $(PKGROOT)/,$(SS))
+ALLSRC := $(ALLSRC) $(SRCSS)
+INSTSS := $(addprefix lib/ss/,$(SS))
+ALLINST := $(ALLINST) $(INSTSS)
+SS =
+
+ifneq (,$(INSTSS))
+$(INSTSS): lib/ss/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# ST supplied by package's Makefile.install.
+ST := $(strip $(ST))
+SRCST := $(addprefix $(PKGROOT)/,$(ST))
+ALLSRC := $(ALLSRC) $(SRCST)
+INSTST := $(addprefix lib/st/,$(ST))
+ALLINST := $(ALLINST) $(INSTST)
+ST =
+
+ifneq (,$(INSTST))
+$(INSTST): lib/st/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# STK supplied by package's Makefile.install.
+STK := $(strip $(STK))
+SRCSTK := $(addprefix $(PKGROOT)/,$(STK))
+ALLSRC := $(ALLSRC) $(SRCSTK)
+INSTSTK := $(addprefix lib/stk/,$(STK))
+ALLINST := $(ALLINST) $(INSTSTK)
+STK =
+
+ifneq (,$(INSTSTK))
+$(INSTSTK): lib/stk/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# ETC supplied by package's Makefile.install.
+ETC := $(strip $(ETC))
+SRCETC := $(addprefix $(PKGROOT)/,$(ETC))
+ALLSRC := $(ALLSRC) $(SRCETC)
+INSTETC := $(addprefix etc/,$(ETC))
+ALLINST := $(ALLINST) $(INSTETC)
+ETC = 
+
+ifneq (,$(INSTETC))
+$(INSTETC): etc/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# IGATEDB supplied by package's Makefile.install.
+ifeq (,$(NO_INTERROGATE))
+IGATEDB := $(strip $(IGATEDB))
+SRCIGATEDB := $(addprefix $(PKGROOT)/,$(IGATEDB))
+ALLSRC := $(ALLSRC) $(SRCIGATEDB)
+INSTIGATEDB := $(addprefix etc/,$(IGATEDB))
+ALLINST := $(ALLINST) $(INSTIGATEDB)
+IGATEDB = 
+
+ifneq (,$(INSTIGATEDB))
+$(INSTIGATEDB): etc/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+endif
+
+
+# MODELS supplied by package's Makefile.install.
+MODELS := $(strip $(MODELS))
+SRCMODELS := $(addprefix $(PKGROOT)/,$(MODELS))
+ALLSRC := $(ALLSRC) $(SRCMODELS)
+INSTMODELS := $(addprefix etc/models/, $(MODELS))
+ALLINST := $(ALLINST) $(INSTMODELS)
+MODELS = 
+
+ifneq (, $(INSTMODELS))
+$(INSTMODELS): etc/models/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# DOC supplied by package's Makefile.install.
+DOC := $(strip $(DOC))
+SRCDOC := $(addprefix $(PKGROOT)/,$(DOC))
+ALLSRC := $(ALLSRC) $(SRCDOC)
+INSTDOC := $(addprefix doc/,$(DOC))
+ALLINST := $(ALLINST) $(INSTDOC)
+DOC = 
+
+ifneq (,$(INSTDOC))
+$(INSTDOC): doc/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# MAN supplied by package's Makefile.install.
+MAN := $(strip $(MAN))
+SRCMAN := $(addprefix $(PKGROOT)/,$(MAN))
+ALLSRC := $(ALLSRC) $(SRCMAN)
+INSTMAN := $(addprefix doc/man/,$(MAN))
+ALLINST := $(ALLINST) $(INSTMAN)
+MAN = 
+
+ifneq (,$(INSTMAN))
+$(INSTMAN): doc/man/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+# TXT supplied by package's Makefile.install.
+TXT := $(strip $(TXT))
+SRCTXT := $(addprefix $(PKGROOT)/,$(TXT))
+ALLSRC := $(ALLSRC) $(SRCTXT)
+INSTTXT := $(addprefix doc/txt/,$(TXT))
+ALLINST := $(ALLINST) $(INSTTXT)
+TXT = 
+
+ifneq (,$(INSTTXT))
+$(INSTTXT): doc/txt/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+# HTML supplied by package's Makefile.install.
+HTML := $(strip $(HTML))
+SRCHTML := $(addprefix $(PKGROOT)/,$(HTML))
+ALLSRC := $(ALLSRC) $(SRCHTML)
+INSTHTML := $(addprefix doc/html/,$(HTML))
+ALLINST := $(ALLINST) $(INSTHTML)
+HTML = 
+
+ifneq (,$(INSTHTML))
+$(INSTHTML): doc/html/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+# PS supplied by package's Makefile.install.
+PS := $(strip $(PS))
+SRCPS := $(addprefix $(PKGROOT)/,$(PS))
+ALLSRC := $(ALLSRC) $(SRCPS)
+INSTPS := $(addprefix doc/ps/,$(PS))
+ALLINST := $(ALLINST) $(INSTPS)
+PS = 
+
+ifneq (,$(INSTPS))
+$(INSTPS): doc/ps/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+# FONTS supplied by package's Makefile.install.
+FONTS := $(strip $(FONTS))
+SRCFONTS := $(addprefix $(PKGROOT)/,$(FONTS))
+ALLSRC := $(ALLSRC) $(SRCFONTS)
+INSTFONTS := $(addprefix etc/fonts/,$(FONTS))
+ALLINST := $(ALLINST) $(INSTFONTS)
+FONTS = 
+
+ifneq (,$(INSTFONTS))
+$(INSTFONTS): etc/fonts/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# ICONS supplied by package's Makefile.install.
+ICONS := $(strip $(ICONS))
+SRCICONS := $(addprefix $(PKGROOT)/,$(ICONS))
+ALLSRC := $(ALLSRC) $(SRCICONS)
+INSTICONS := $(addprefix etc/icons/,$(ICONS))
+ALLINST := $(ALLINST) $(INSTICONS)
+ICONS = 
+
+ifneq (,$(INSTICONS))
+$(INSTICONS): etc/icons/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# APPDEFAULTS supplied by package's Makefile.install.
+APPDEFAULTS := $(strip $(APPDEFAULTS))
+SRCAPPDEFAULTS := $(addprefix $(PKGROOT)/,$(APPDEFAULTS))
+ALLSRC := $(ALLSRC) $(SRCAPPDEFAULTS)
+INSTAPPDEFAULTS := $(addprefix etc/app-defaults/,$(APPDEFAULTS))
+ALLINST := $(ALLINST) $(INSTAPPDEFAULTS)
+APPDEFAULTS = 
+
+ifneq (,$(INSTAPPDEFAULTS))
+$(INSTAPPDEFAULTS): etc/app-defaults/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# TCL supplied by package's Makefile.install.
+TCL := $(strip $(TCL))
+SRCTCL := $(addprefix $(PKGROOT)/,$(TCL))
+ALLSRC := $(ALLSRC) $(SRCTCL)
+INSTTCL := $(addprefix etc/tcl/,$(TCL))
+ALLINST := $(ALLINST) $(INSTTCL)
+TCL = 
+
+ifneq (,$(INSTTCL))
+$(INSTTCL): etc/tcl/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# TELEUSE supplied by package's Makefile.install.
+TELEUSE := $(strip $(TELEUSE))
+SRCTELEUSE := $(addprefix $(PKGROOT)/,$(TELEUSE))
+ALLSRC := $(ALLSRC) $(SRCTELEUSE)
+INSTTELEUSE := $(addprefix etc/teleuse/,$(TELEUSE))
+ALLINST := $(ALLINST) $(INSTTELEUSE)
+TELEUSE = 
+
+ifneq (,$(INSTTELEUSE))
+$(INSTTELEUSE): etc/teleuse/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# SHADERS supplied by package's Makefile.install.
+SHADERS := $(strip $(SHADERS))
+SRCSHADERS := $(addprefix $(PKGROOT)/,$(SHADERS))
+ALLSRC := $(ALLSRC) $(SRCSHADERS)
+INSTSHADERS := $(addprefix etc/shaders/,$(SHADERS))
+ALLINST := $(ALLINST) $(INSTSHADERS)
+SHADERS = 
+
+ifneq (,$(INSTSHADERS))
+$(INSTSHADERS): etc/shaders/% : $(PKGROOT)/%
+	$(MKINSTALL)
+endif
+
+
+# OTHER supplied by package's Makefile.install.
+OTHER := $(strip $(OTHER))
+SRCOTHER := $(addprefix $(PKGROOT)/,$(notdir $(OTHER)))
+ALLSRC := $(ALLSRC) $(SRCOTHER)
+INSTOTHER := $(OTHER)
+ALLINST := $(ALLINST) $(INSTOTHER)
+OTHER = 
+# Install actions for these files come from package's Makefile.install
+
+
+
+#### Dependencies on files from other packages (same project).
+
+ALLUSES = 
+
+# USESLIBS supplied by package's Makefile.install.
+
+ifeq (PS2, $(PENV))
+  USESLIBS := $(USESLIBS:%.so=%.a)
+endif
+
+ifeq (WIN32,$(PENV))
+  USESLIBS := $(USESLIBS:%.so=%$(DEBUGNAME).dll)
+  USESLIBS := $(USESLIBS:%.a=%$(DEBUGNAME).lib)
+endif # WIN32
+ifeq (OSX,$(PENV))
+  USESLIBS := $(USESLIBS:%.so=%.dylib)
+endif # OSX
+ALLUSES := $(ALLUSES) $(addprefix lib/,$(strip $(USESLIBS)))
+USESLIBS = 
+
+# USESINCLUDE supplied by package's Makefile.install.
+ALLUSES := $(ALLUSES) $(addprefix inc/,$(strip $(USESINCLUDE)))
+USESINCLUDE = 
+
+# USESDEFERREDLIBS supplied by package's Makefile.install, but only
+# respected if USE_DEFERRED is set.
+ifneq (,$(USE_DEFERRED))
+  ifeq (WIN32,$(PENV))
+    USESDEFERREDLIBS := $(USESDEFERREDLIBS:%.so=%$(DEBUGNAME).dll)
+    USESDEFERREDLIBS := $(USESDEFERREDLIBS:%.a=%$(DEBUGNAME).lib)
+  endif # WIN32
+  ifeq (OSX,$(PENV))
+    USESDEFERREDLIBS := $(USESDEFERREDLIBS:%.so=%.dylib)
+  endif # OS X
+  ALLUSES := $(ALLUSES) $(addprefix lib/,$(strip $(USESDEFERREDLIBS)))
+  USESDEFERREDLIBS = 
+endif
+
+# USESOTHER supplied by package's Makefile.install.
+ALLUSES := $(ALLUSES) $(strip $(USESOTHER))
+USESOTHER = 
+
+
+
+#### Action targets
+#
+# The following series of targets all cause some action to take place in
+# the project tree.  All of these actions may be done on a single
+# package or on the entire project.  By default, any action done on a
+# package is also done first on any packages it depends on.  This can be
+# circumvented by setting NODEPEND to true.  
+#
+# One of the tricky things done in all the following rules was to not use 
+# any variables in the build scripts.  This is necessary because this 
+# rules files is read in multiple times in a project build, and the 
+# variable are set multiple times.  However, build scripts are executed
+# at the end of the read process, after dependency resolution.  At that
+# time, variables have the value they were last set to.  Instead, the
+# approach is to place the variables in the dependency lists and target
+# names, since these are resolved as the file is read.
+#
+
+#### Installation and build rules.
+
+# To install project, install all packages.
+install-$(CTPROJECT): install-$(PKGROOT)
+
+# To install package, must build all installed files.
+install-$(PKGROOT):  announce-install-$(PKGROOT) $(ALLINST)
+
+# Synonym for installing a package.
+install-$(PACKAGE): install-$(PKGROOT)
+
+# $(ALLINST) : $(ALLSRC) done in install actions section above.
+
+## Before installing, announce that installation is starting.
+#ifneq (,$(ALLSRC))
+#$(ALLSRC): announce-install-$(PKGROOT)
+#endif
+
+# State that we're installing files from the package.  Build first.
+announce-install-$(PKGROOT): build-$(PKGROOT)
+	@echo '***' Installing from $(strip-target) '...'
+
+# Check for Makefile in package.  If found, make it.
+ifeq (,$(NODEPEND))
+build-$(PKGROOT) : $(addprefix install-,$(ALLUSES))
+else
+build-$(PKGROOT) :
+endif
+	@cd $(CTPROJROOT)/$(strip-target); if [ -r Makefile ]; then echo '***' Building $(strip-target) '...'; \
+	$(MAKE) install; fi
+
+# Convenient synonym for build.
+build-$(PACKAGE): build-$(PKGROOT)
+
+# Provide hooks for other packages to transmit build dependencies.
+ifneq (,$(ALLINST))
+$(addprefix install-,$(ALLINST)): install-$(PKGROOT)
+endif
+
+
+
+#### Clean rules.
+
+# To clean project, clean each package.
+clean-$(CTPROJECT): clean-$(PKGROOT)
+
+# Synonym to clean a particular package.
+clean-$(PACKAGE): clean-$(PKGROOT)
+
+ifneq (,$(ALLINST))
+$(addprefix clean-,$(ALLINST)): clean-$(PKGROOT)
+endif
+
+# To clean package, cd to it and do 'make clean' (if there's a Makefile).
+ifeq (,$(NODEPEND))
+clean-$(PKGROOT) : $(addprefix clean-,$(ALLUSES))
+else
+clean-$(PKGROOT) :
+endif
+	@cd $(CTPROJROOT)/$(strip-target); if [ -r Makefile ]; then echo '***' Cleaning $(strip-target) '...'; \
+	$(MAKE) clean; fi
+
+
+
+#### Cleanall rules.
+
+# To clean project, clean each package.
+cleanall-$(CTPROJECT): cleanall-$(PKGROOT)
+
+# Synonym to cleanall a particular package.
+cleanall-$(PACKAGE): cleanall-$(PKGROOT)
+
+ifneq (,$(ALLINST))
+$(addprefix cleanall-,$(ALLINST)): cleanall-$(PKGROOT)
+endif
+
+# To cleanall package, cd to it and do 'make cleanall' (if there's a Makefile).
+ifeq (,$(NODEPEND))
+cleanall-$(PKGROOT) : $(addprefix cleanall-,$(ALLUSES))
+else
+cleanall-$(PKGROOT) :
+endif
+	@cd $(CTPROJROOT)/$(strip-target); if [ -r Makefile ]; then echo '***' Wiping $(strip-target) '...'; \
+	$(MAKE) cleanall; fi
+
+
+
+#### Uninstall rules.
+
+# To uninstall project, must uninstall each package.
+uninstall-$(CTPROJECT): uninstall-$(PKGROOT)
+
+# To uninstall package, must remove each installed file.
+uninstall-$(PKGROOT): $(addprefix uninstall-,$(ALLINST))
+
+# Synonym for uninstalling a package.
+uninstall-$(PACKAGE): uninstall-$(PKGROOT)
+
+# To remove file, check if it's there and rm it.
+ifneq (,$(ALLINST))
+$(addprefix uninstall-,$(ALLINST)): announce-uninstall-$(PKGROOT)
+	@if [ -r $(strip-target) ]; then echo $(strip-target); rm -rf $(strip-target); fi
+
+$(addprefix touninstall-,$(ALLINST)): uninstall-$(PKGROOT)
+endif
+
+# Announce uninstallation.  First uninstall dependent packages.
+ifeq (,$(NODEPEND))
+announce-uninstall-$(PKGROOT): $(addprefix touninstall-,$(ALLUSES))
+else
+announce-uninstall-$(PKGROOT):
+endif
+	@echo '***' Uninstalling from package $(strip-target) '...'
+
+
+
+#### Touch rules.
+
+# To touch project, must touch each package.
+touch-$(CTPROJECT): touch-$(PKGROOT)
+
+# To touch package, must touch each installed file.
+touch-$(PKGROOT): $(addprefix touch-,$(ALLINST))
+
+# Synonym for touching a package.
+touch-$(PACKAGE): touch-$(PKGROOT)
+
+# To touch file, check if it's there and touch it.  Works on directories.
+ifneq (,$(ALLINST))
+$(addprefix touch-,$(ALLINST)): announce-touch-$(PKGROOT)
+	@if [ -r $(strip-target) ]; then find $(strip-target) -print -exec touch {} \; ; fi
+
+$(addprefix totouch-,$(ALLINST)): touch-$(PKGROOT)
+endif
+
+# Announce touch.  First touch dependent packages.
+ifeq (,$(NODEPEND))
+announce-touch-$(PKGROOT): $(addprefix totouch-,$(ALLUSES))
+else
+announce-touch-$(PKGROOT):
+endif
+	@echo '***' Touching package $(strip-target) '...'
+
+
+
+#### Copy rules.
+
+# To copy project, must copy each package.
+copy-$(CTPROJECT): copy-$(PKGROOT)
+
+# To copy package, must copy each installed file.
+copy-$(PKGROOT): $(addprefix copy-,$(ALLINST))
+
+# Synonym for copying a package.
+copy-$(PACKAGE): copy-$(PKGROOT)
+
+ifneq (,$(ALLINST))
+$(addprefix copy-,$(ALLINST)): announce-copy-$(PKGROOT)
+ifneq (,$(CTFROM))
+	@if [ ! -d $(*D) ]; then mkdir $(*D); fi
+	@cp -r $(CTFROM)/$(strip-target) $(strip-target) && echo $(strip-target)
+else
+	@echo CTFROM variable not set; exit 1
+endif
+
+$(addprefix tocopy-,$(ALLINST)): copy-$(PKGROOT)
+endif
+
+# Announce copy.  First copy dependent packages.
+ifeq (,$(NODEPEND))
+announce-copy-$(PKGROOT): $(addprefix tocopy-,$(ALLUSES))
+else
+announce-copy-$(PKGROOT):
+endif
+	@echo '***' Copying package $(strip-target) '...'
+
+
+
+#### Query targets.
+#
+# The following rules use the project makefile as a database, to which
+# various questions can be put, such as 'what files does this package
+# install?', 'which files are currently installed?', and 'what packages
+# must be built before this package can be built?'.  These targets take
+# no action in the project, they just produce a list of one or more 
+# answers.  As in the action targets, interpackage dependencies are used
+# to automatically propagate the question from a package to its
+# dependency packages (those it needs to build).
+
+#### Query files to be installed by a package.
+
+# To find files installed by project, query each package.
+toinstall-$(CTPROJECT): toinstall-$(PKGROOT)
+
+# Convenient synonym for toinstall.
+toinstall-$(PACKAGE): toinstall-$(PKGROOT)
+
+# To list package, list each file installed by package.
+toinstall-$(PKGROOT): $(addprefix toinstall-,$(ALLINST))
+
+# Echo each installed file's name.  First announce the package.
+ifneq (,$(ALLINST))
+$(addprefix toinstall-,$(ALLINST)): announce-toinstall-$(PKGROOT)
+	@echo $(strip-target)
+
+$(addprefix totoinstall-,$(ALLINST)): toinstall-$(PKGROOT)
+endif
+
+ifeq (,$(NODEPEND))
+announce-toinstall-$(PKGROOT): $(addprefix totoinstall-,$(ALLUSES))
+else
+announce-toinstall-$(PKGROOT):
+endif
+	@echo '***' To be installed from $(strip-target) '...'
+
+
+
+
+#### Query files that have been installed by a package.
+
+isinstalled-$(CTPROJECT): isinstalled-$(PKGROOT)
+
+isinstalled-$(PKGROOT): $(addprefix isinstalled-,$(ALLINST))
+
+isinstalled-$(PACKAGE): isinstalled-$(PKGROOT)
+
+ifneq (,$(ALLINST))
+$(addprefix isinstalled-,$(ALLINST)): announce-isinstalled-$(PKGROOT)
+	@if [ -r $(strip-target) ]; then echo $(strip-target); fi
+
+$(addprefix toisinstalled-,$(ALLINST)): isinstalled-$(PKGROOT)
+endif
+
+ifeq (,$(NODEPEND))
+announce-isinstalled-$(PKGROOT): $(addprefix toisinstalled-,$(ALLUSES))
+else
+announce-isinstalled-$(PKGROOT):
+endif
+	@echo '***' Currently installed from $(strip-target) '...'
+
+
+
+#### Query files that have not been installed by a package.
+
+notinstalled-$(CTPROJECT): notinstalled-$(PKGROOT)
+
+notinstalled-$(PKGROOT): $(addprefix notinstalled-,$(ALLINST))
+
+notinstalled-$(PACKAGE): notinstalled-$(PKGROOT)
+
+ifneq (,$(ALLINST))
+$(addprefix notinstalled-,$(ALLINST)): announce-notinstalled-$(PKGROOT)
+	@if [ ! -r $(strip-target) ]; then echo $(strip-target); fi
+
+$(addprefix tonotinstalled-,$(ALLINST)): notinstalled-$(PKGROOT)
+endif
+
+ifeq (,$(NODEPEND))
+announce-notinstalled-$(PKGROOT): $(addprefix tonotinstalled-,$(ALLUSES))
+else
+announce-notinstalled-$(PKGROOT):
+endif
+	@echo '***' Not currently installed from $(strip-target) '...'
+
+
+
+#### Check that a package is completely installed.
+
+checkinstall-$(CTPROJECT): checkinstall-$(PKGROOT)
+
+checkinstall-$(PACKAGE): checkinstall-$(PKGROOT)
+
+checkinstall-$(PKGROOT): $(addprefix checkinstall-,$(ALLINST))
+
+ifneq (,$(ALLINST))
+$(addprefix checkinstall-,$(ALLINST)): announce-checkinstall-$(PKGROOT)
+	@if [ ! -r $(strip-target) ]; then exit 1; fi
+
+$(addprefix tocheckinstall-,$(ALLINST)): checkinstall-$(PKGROOT)
+endif
+
+ifeq (,$(NODEPEND))
+announce-checkinstall-$(PKGROOT): $(addprefix tocheckinstall-,$(ALLUSES))
+else
+announce-checkinstall-$(PKGROOT):
+endif
+	@echo '***' Checking installation from $(strip-target) '...'
+
+
+
+#### Query files used to build a package.
+
+# To find files needed in project, query each package.
+showuses-$(CTPROJECT): showuses-$(PKGROOT)
+
+# Convenient synonym for showuses.
+showuses-$(PACKAGE): showuses-$(PKGROOT)
+
+showuses-$(PKGROOT): $(addprefix showuses-,$(ALLUSES))
+	@echo '***' Files declared as needed to build $(strip-target) '...'
+	@if expr "$^" != "" > /dev/null; then echo $^ | sed -e 's/showuses-//g' | tr " " "\012"; fi
+
+ifneq (,$(NODEPEND))
+
+ifneq (,$(ALLUSES))
+$(addprefix showuses-,$(ALLUSES)): 
+
+endif
+
+else
+
+ifneq (,$(ALLINST))
+$(addprefix showuses-,$(ALLINST)): showuses-$(PKGROOT)
+
+endif
+
+endif
+
+
+
+#### Find package location given installed file, or package name.
+
+ifneq (,$(ALLINST))
+$(addprefix find-,$(ALLINST)): find-$(PKGROOT)
+endif
+
+find-$(PKGROOT):
+	@echo $(strip-target)
+
+find-$(PACKAGE): find-$(PKGROOT)
+
+
+
+#### List packages that need this package in order to build successfully.
+
+# A package needs this package if it needs any of its files.
+needs-$(PACKAGE): $(addprefix needs-,$(ALLINST))
+
+# Define empty targets for needs-installed-files.  Ensures successful 
+# completion.
+ifneq (,$(ALLINST))
+$(addprefix needs-,$(ALLINST)):
+endif
+
+# Needing the file mean the package has a prerequisite.
+ifneq (,$(ALLUSES))
+$(addprefix needs-,$(ALLUSES)): prereq-$(PKGROOT)
+endif
+
+# Print all packages with prerequisites triggered by original package.
+# Possibly propagate prerequisites on to other packages.
+ifeq (,$(NODEPEND))
+prereq-$(PKGROOT): $(addprefix needs-,$(ALLINST))
+else
+prereq-$(PKGROOT):
+endif
+	@echo $(strip-target)
+
+
+
+#### List packages used to build this package (opposite of above).
+
+depends-$(CTPROJECT): depends-$(PKGROOT)
+
+depends-$(PKGROOT):
+
+ifneq (,$(ALLINST))
+$(addprefix depends-,$(ALLINST)): requires-$(PKGROOT)
+endif
+
+ifneq (,$(ALLUSES))
+
+depends-$(PKGROOT): $(addprefix depends-,$(ALLUSES))
+
+ifeq (,$(NODEPEND))
+requires-$(PKGROOT): $(addprefix depends-,$(ALLUSES))
+else
+requires-$(PKGROOT):
+endif
+	@echo $(strip-target)
+
+endif
+
+depends-$(PACKAGE): depends-$(PKGROOT)
+
+
+
+#### List packages that do not depend on other packages.
+
+nodepends-$(CTPROJECT): nodepends-$(PKGROOT)
+
+ifeq (,$(strip $(ALLUSES)))
+nodepends-$(PKGROOT):
+	@echo $(strip-target)	
+
+else
+nodepends-$(PKGROOT):
+
+endif
+
+
+
+#### List files included by a package.
+
+# To clean project, clean each package.
+includes-$(CTPROJECT): includes-$(PKGROOT)
+
+# Synonym to includes a particular package.
+includes-$(PACKAGE): includes-$(PKGROOT)
+
+ifneq (,$(ALLINST))
+$(addprefix includes-,$(ALLINST)): includes-$(PKGROOT)
+endif
+
+# Call ctshowdep on package
+ifeq (,$(NODEPEND))
+includes-$(PKGROOT) : $(addprefix includes-,$(ALLUSES))
+else
+includes-$(PKGROOT) :
+endif
+	@echo '***' Files included by $(strip-target) '...'
+	-ctshowdep $(CTINC) $(strip-target)

+ 61 - 0
dtool/src/build/Makefile.install.template

@@ -0,0 +1,61 @@
+#### Installation makefile
+# Note: This file is included by the project-wide Makefile so the current
+# directory is the project root.  Also, commented-out fields are optional.
+
+#### Package name and location (if not src/all/$(PACKAGE)):
+#CTPACKAGE
+PKGROOT =                   # Leave this blank if no change needed
+
+ifneq (,$(PACKAGE))
+
+#### Package dependencies (USESOTHER needs relative paths from project root):
+# USESLIBS = 
+# USESINCLUDE = 
+# USESOTHER = 
+
+#### Installed files:
+# LIBS = 
+# INCLUDE = 
+# BINS =
+# SCRIPTS =
+# SS = 
+# ST = 
+# STK = 
+# MODELS = 
+# ETC = 
+# DOC =
+# MAN =
+# TXT =
+# HTML =
+# PS = 
+# FONTS = 
+# ICONS = 
+# APPDEFAULTS = 
+# TCL = 
+# TELEUSE = 
+# SHADERS = 
+
+#### Other files to be installed (use relative pathname from project root):
+# OTHER = 
+
+#### Where the action happens.
+include $(DTOOL)/inc/Makefile.install.rules
+
+#### Install actions for OTHER files (source must be in $(PKGROOT)):
+# [ installed file ] : $(PKGROOT)/[ source file ]  # Files must have same name
+#	$(INSTALL)                      # Copies from source to dest
+#
+# [ installed file ] : $(PKGROOT)/[ source file ]
+#	$(MKINSTALL)			# Also makes directory if needed
+
+#### Other install/uninstall actions:
+# install-$(PKGROOT): #Add dependencies here
+#	Add actions here
+#
+# uninstall-$(PKGROOT): #Add dependencies here
+#	Add actions here
+
+#### Sub-package Makefile.install inclusions:
+# include foo/Makefile.install
+
+endif

+ 25 - 0
dtool/src/build/Makefile.install.vars

@@ -0,0 +1,25 @@
+# Standard variables for installation
+
+ifeq (,$(MAKEFILE_INSTALL_VARS))
+MAKEFILE_INSTALL_VARS = TRUE
+
+# This makes the variables available to sub-Makes.
+ifeq (,$(MAKEFILE_PENV_VARS))
+include $(DTOOL)/inc/Makefile.penv.vars
+endif
+
+ifeq (,$(MAKEFILE_PROJECT_VARS))
+include $(DTOOL)/inc/Makefile.project.vars
+endif
+
+# Delete the standard suffixes
+.SUFFIXES:
+
+# The following macros accomplish single file installation.  The second
+# will also create any necessary subdirectories.
+INSTALL		= @echo $@; rm -rf $@; cp -r $< $@;
+MKINSTALL	= @if [ ! -d $(dir $@) ]; then mkdir $(dir $@); fi; \
+                  echo $@; rm -rf $@; cp -r $< $@;
+LNINSTALL	= @echo $@; rm -rf $@; ln -s ../../$< $@;
+
+endif

+ 103 - 0
dtool/src/build/Makefile.meta.rules

@@ -0,0 +1,103 @@
+# Meta makefile rules.
+
+# Delete the default suffixes
+.SUFFIXES:
+
+# Define macro to strip characters preceding '-' in the target variable ($*)
+strip-target = `echo $@ | sed 's/^[^-]*-//'`
+
+ifeq (,$(CTPROJROOT))
+CTPROJROOT := $(shell $(DTOOL)/bin/ctproj -root)
+endif
+export CTPROJROOT 
+
+# Make sure that CT_INCLUDE_PATH is set.
+ifeq (,$(CT_INCLUDE_PATH))
+export CT_INCLUDE_PATH = .
+endif
+
+# Make sure CT_LIBRARY_PATH is set.
+ifeq (,$(CT_LIBRARY_PATH))
+ifneq (,$(LD_LIBRARY_PATH))
+export CT_LIBRARY_PATH := $(LD_LIBRARY_PATH)
+else
+export CT_LIBRARY_PATH = .
+endif
+endif
+
+# export the OPTIMIZE variable
+ifneq (,$(OPTIMIZE))
+export OPTIMIZE
+endif
+
+ifeq (,$(INSTALL))
+INSTALL := $(SUBMAKES)
+endif
+
+all: $(SUBMAKES)
+
+install: $(INSTALL)
+
+ifeq (yes,$(HAVE_ATRIA))
+realinstall:
+	@cd `ctproj -r` ; clearmake -C gnu install-`ctproj -p`
+else
+realinstall:
+	@proj=`ctproj -p` ; cd `ctproj -r` ; $(MAKE) install-$$proj
+endif
+
+ifneq (,$(SUBMAKES))
+.PHONY: $(SUBMAKES)
+.PHONY: $(addprefix egg-,$(SUBMAKES))
+.PHONY: $(addprefix unopt-,$(SUBMAKES))
+.PHONY: $(addprefix pfb-,$(SUBMAKES))
+endif
+
+ifneq (,$(NUMBER_OF_PROCESSORS))
+# on NT, parallelize using NUMBER_OF_PROCESSORS env-var
+PARALLEL_MAKE = -j $(NUMBER_OF_PROCESSORS)
+endif
+
+$(SUBMAKES):
+	@echo '***' Executing $(MAKE) for sub-target $@...
+	@echo $(MAKE) $(PARALLEL_MAKE) -f $(MAKEDIR)/Makefile.$@
+	@$(MAKE) $(PARALLEL_MAKE) -f $(MAKEDIR)/Makefile.$@
+
+clean: $(addprefix clean-,$(SUBMAKES))
+
+$(addprefix clean-,$(SUBMAKES)):
+	@echo '***' Executing $(MAKE) clean for sub-target $(strip-target)...
+	@$(MAKE) $(PARALLEL_MAKE) -f $(MAKEDIR)/Makefile.$(strip-target) clean
+	@rm -f *~
+
+cleanall: $(addprefix cleanall-,$(SUBMAKES))
+
+$(addprefix cleanall-,$(SUBMAKES)):
+	@echo '***' Executing $(MAKE) cleanall for sub-target $(strip-target)...
+	@$(MAKE) $(PARALLEL_MAKE) -f $(MAKEDIR)/Makefile.$(strip-target) cleanall
+
+list:
+	@echo $(SUBMAKES)
+
+# These are used in src/all/model subdirectories.
+
+egg: $(addprefix egg-,$(SUBMAKES))
+$(addprefix egg-,$(SUBMAKES)):
+	@echo '***' Executing $(MAKE) egg for sub-target $(strip-target)...
+	@$(MAKE) -f $(MAKEDIR)/Makefile.$(strip-target) egg
+
+unopt: $(addprefix unopt-,$(SUBMAKES))
+$(addprefix unopt-,$(SUBMAKES)):
+	@echo '***' Executing $(MAKE) unopt for sub-target $(strip-target)...
+	@$(MAKE) -f $(MAKEDIR)/Makefile.$(strip-target) unopt
+
+pfb: $(addprefix pfb-,$(SUBMAKES))
+$(addprefix pfb-,$(SUBMAKES)):
+	@echo '***' Executing $(MAKE) pfb for sub-target $(strip-target)...
+	@$(MAKE) -f $(MAKEDIR)/Makefile.$(strip-target) pfb
+
+uninstall: $(addprefix uninstall-,$(SUBMAKES))
+$(addprefix uninstall-,$(SUBMAKES)):
+	@echo '***' Executing $(MAKE) uninstall for sub-target $(strip-target)...
+	@$(MAKE) -f $(MAKEDIR)/Makefile.$(strip-target) uninstall
+

+ 16 - 0
dtool/src/build/Makefile.meta.template

@@ -0,0 +1,16 @@
+#### Meta Makefile.
+
+#### Sub make targets (extension of sub Makefile, eg 'foo' for Makefile.foo):
+SUBMAKES = 
+
+#### List the minimal set of sub makes on the list above required to install.
+INSTALL = 
+
+#### Location of sub Makefiles.
+MAKEDIR = .
+
+#### The action is here.
+include $(DTOOL)/inc/Makefile.meta.rules
+
+#### Sub-make build order dependencies:
+# foo: bar

+ 43 - 0
dtool/src/build/Makefile.o.include

@@ -0,0 +1,43 @@
+# Standard .o file conversion information.
+
+#### Pull in standard .o make variables
+include $(DTOOL)/inc/Makefile.o.vars
+
+#### Lex files 
+# LFILES = 
+# LFLAGS = 
+# LEXTENSION = 
+# LSUBST =
+
+#### Yacc files 
+# YFILES = 
+# YFLAGS = 
+# YEXTENSION =
+# YSUBST =
+
+#### C files 
+# CFILES = 
+# CFLAGS =
+
+#### C++ files 
+# C++FILES = 
+# C++FLAGS =
+# USETEMPLATES = TRUE
+# PTREPOSITORY = # Specify only if you want a specific name
+
+#### Interrogate info
+# IGATESCAN  = 
+# IGATEFLAGS = 
+# IGATEFILE  = # Specify only if you want a specific name
+
+#### Additional search directories for C/C++ header files:
+# IPATH := $(IPATH) -I/my/directory -I/my/other/directory
+
+#### Location to put .o files:
+# ODIR = 
+
+#### Source file dependencies (unnecessary with clearmake)
+# foo.c: foo.h
+
+#### The .o action is here.
+include $(DTOOL)/inc/Makefile.o.rules

+ 358 - 0
dtool/src/build/Makefile.o.rules

@@ -0,0 +1,358 @@
+# Makefile rules for making .o files from source files
+
+#############################################################################
+#
+# Yacc conversion rules.
+#
+# Files are converted to source form,  then added to CFILES or C++FILES to
+# be compiled into .o files.  A file foo.y becomes foo.$(YEXTENSION) (see
+# variable list below).  If YEXTENSION contains a 'C' then the file is added
+# to C++FILES, otherwise it goes to CFILES.  A substitution string may be
+# added to all 'yy' and 'YY' symbols in the yacc output so that multiple yacc
+# parsers can be linked into one program.  
+#
+# Variables:
+#   YFILES = list of .y files to be yacc'ed 
+#   YEXTENSION = extension to put on yacc'ed files (default = tab.c)
+#   YFLAGS = command line flags to yacc
+#
+ifneq (,$(YFILES))
+
+# Instead of adding the list of yacc-generated files to the CFILES or
+# C++FILES lists, we must generate a new list that's compiled via a
+# separate rule.  This allows us to use different options (for
+# instance, to eliminate optimization, which seems to trouble some
+# compilers, particularly gcc).
+
+# We must then process YCFILES and YC++FILES before we process CFILES
+# and C++FILES, so yacc will get called before any of the C files are
+# compiled, in case one of the C files wants to include y.tab.h.
+
+ifneq (,$(findstring cxx,$(YEXTENSION)))
+  YC++FILES := $(patsubst %.yxx, %.$(YEXTENSION), $(YFILES))
+else
+  YCFILES := $(patsubst %.yxx, %.$(YEXTENSION), $(YFILES))
+endif
+
+$(YCFILES) $(YC++FILES) : %.$(YEXTENSION) : %.yxx
+	$(YACC) $(YFLAGS) $<
+	mv y.tab.c $@
+	mv y.tab.h $(patsubst %.$(YEXTENSION), %.h, $@)
+
+clean::
+	rm -f $(YCFILES) $(YC++FILES)
+	
+endif
+
+
+
+#############################################################################
+#
+# Lex conversion rules.
+#
+# Files are converted to source form,  then added to CFILES or C++FILES to
+# be compiled into .o files.  A file foo.l becomes foo.$(LEXTENSION) (see
+# variable list below).  If LEXTENSION contains a 'C' then the file is added
+# to C++FILES, otherwise it goes to CFILES.  A substitution string may be
+# added to all 'yy' and 'YY' symbols in the lex output so that multiple lex
+# analyzers can be linked into one program.  
+#
+# Variables:
+#   LFILES = list of .l files to be lex'ed (from user Makefile)
+#   LEXTENSION = extension to put on lex'ed files (default = yy.c)
+#   LFLAGS = command line flags to lex
+#
+ifneq (,$(LFILES))
+
+LCFILES := $(patsubst %.lxx, %.$(LEXTENSION), $(LFILES))
+ifneq (,$(findstring cxx,$(LEXTENSION)))
+C++FILES := $(C++FILES) $(LCFILES)
+else
+CFILES := $(CFILES) $(LCFILES)
+endif
+
+$(LCFILES) : %.$(LEXTENSION) : %.lxx
+	$(LEX) $(LFLAGS) $<
+	mv lex.yy.c $@
+
+clean:: 
+	rm -f $(LCFILES)
+	
+endif
+
+#############################################################################
+#
+# .cpp -> .cxx conversion rules.
+#
+
+ifneq (,$(CPPFILES))
+
+CPPCFILES := $(patsubst %.cpp, %.cxx, $(CPPFILES))
+C++FILES := $(C++FILES) $(CPPCFILES)
+
+$(CPPCFILES) : %.cxx : %.cpp
+	cp $< $@
+	chmod 666 $@
+
+clean::
+	rm -f $(CPPCFILES)
+
+endif
+
+
+
+#############################################################################
+#
+# C/C++ Conversion rules.
+#
+
+# Clear ALLOFILES
+ALLOFILES = 
+SUPERALLOFILES = 
+
+ifneq (,$(YCFILES))
+  SUPERALLOFILES += $(YCFILES:%.c=__%.o_file_find_me)
+endif
+ifneq (,$(YC++FILES))
+  SUPERALLOFILES += $(YC++FILES:%.cxx=__%.o_file_find_me)
+endif
+ifneq (,$(CFILES))
+  SUPERALLOFILES += $(CFILES:%.c=__%.o_file_find_me)
+endif
+ifneq (,$(C++FILES))
+  SUPERALLOFILES += $(C++FILES:%.cxx=__%.o_file_find_me)
+endif
+ifeq (,$(NO_INTERROGATE))
+  ifneq (,$(IGATESCAN))
+    ifeq (,$(IGATEFILE))
+      SUPERALLOFILES += __$(TARGET).o_file_find_me
+    else
+      SUPERALLOFILES += $(IGATEFILE:%.cxx=__%.o_file_find_me)
+    endif
+  endif
+endif
+
+NTCFILETYPE =
+NTC++FILETYPE =
+
+ifneq (,$(YCFILES))
+
+ifeq (WIN32_VC,$(PENV_COMPILER))
+  YCOFILES := $(YCFILES:%.c=$(ODIR)/%.obj)
+  NTCFILETYPE := -Tc
+  $(YCOFILES): $(ODIR)/%.obj : %.c
+else # NON-WIN32_VC
+  YCOFILES := $(YCFILES:%.c=$(ODIR)/%.o)
+  $(YCOFILES): $(ODIR)/%.o : %.c
+endif # WIN32_VC
+	@if [ ! -d $(ODIR) ]; then mkdir $(ODIR); fi
+	$(CC) -c $(IPATH) $(SYS_IPATH) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(CFLAGS) $(NTCFILETYPE) $< -o $@
+
+ALLOFILES := $(ALLOFILES) $(YCOFILES)
+endif
+
+ifneq (,$(YC++FILES))
+
+ifeq (WIN32_VC,$(PENV_COMPILER))
+  YC++OFILES := $(YC++FILES:%.cxx=$(ODIR)/%.obj)
+  NTC++FILETYPE := -Tp
+  $(YC++OFILES): $(ODIR)/%.obj : %.cxx
+else # NON-WIN32_VC
+  YC++OFILES := $(YC++FILES:%.cxx=$(ODIR)/%.o)
+  $(YC++OFILES): $(ODIR)/%.o : %.cxx
+endif # WIN32_VC
+	@if [ ! -d $(ODIR) ]; then mkdir $(ODIR); fi
+	$(C++) -c $(IPATH) $(SYS_IPATH) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(C++FLAGS) $(NTC++FILETYPE) $< -o $@
+
+ALLOFILES := $(ALLOFILES) $(YC++OFILES)
+endif
+
+ifneq (,$(CFILES))
+
+ifeq (WIN32_VC,$(PENV_COMPILER))
+  COFILES := $(CFILES:%.c=$(ODIR)/%.obj)
+  NTCFILETYPE := -Tc
+  $(COFILES): $(ODIR)/%.obj : %.c
+else # NON-WIN32_VC
+  COFILES := $(CFILES:%.c=$(ODIR)/%.o)
+  $(COFILES): $(ODIR)/%.o : %.c
+endif # WIN32_VC
+	@if [ ! -d $(ODIR) ]; then mkdir $(ODIR); fi
+	$(CC) -c $(IPATH) $(SYS_IPATH) $(OPTIMIZE_FLAGS) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(CFLAGS) $(NTCFILETYPE) $< -o $@
+
+ALLOFILES := $(ALLOFILES) $(COFILES)
+endif
+
+
+ifneq (,$(C++FILES))
+
+ifeq (WIN32_VC,$(PENV_COMPILER))
+  C++OFILES := $(C++FILES:%.cxx=$(ODIR)/%.obj)
+  NTC++FILETYPE := -Tp
+  $(C++OFILES): $(ODIR)/%.obj : %.cxx
+else # NON-WIN32_VC
+  C++OFILES := $(C++FILES:%.cxx=$(ODIR)/%.o)
+  $(C++OFILES): $(ODIR)/%.o : %.cxx
+endif # WIN32_VC
+	@if [ ! -d $(ODIR) ]; then mkdir $(ODIR); fi
+ifeq (OSX,$(PENV))
+	$(C++) -c $(IPATH) $(SYS_IPATH) $(OPTIMIZE_FLAGS) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(C++FLAGS) $(NTC++FILETYPE) -DFILE_SYM_NAME=__$(subst .,_,$@)_file_find_me -DALL_FILE_SYMS_NAME="\"$(subst .,_,$(SUPERALLOFILES))\"" $< -o $@
+else  # OSX
+	$(C++) -c $(IPATH) $(SYS_IPATH) $(OPTIMIZE_FLAGS) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(C++FLAGS) $(NTC++FILETYPE) $< -o $@
+endif # OSX
+
+ALLOFILES := $(ALLOFILES) $(C++OFILES)
+endif
+
+ifneq (,$(NO_INTERROGATE))
+  IGATESCAN :=
+  IGATEMSCAN :=
+endif
+
+ifeq (,$(IGATELIBRARY))
+IGATELIBRARY := $(basename $(BASETARGET))
+endif
+
+ifneq (,$(IGATESCAN))
+
+ifeq (,$(IGATEFILE))
+IGATEFILE := $(BASETARGET).cxx
+endif
+
+ifeq (,$(IGATEMODULE))
+IGATEMODULE := $(DEFERRED_TARGET)
+endif
+ifeq (,$(IGATEMODULE))
+IGATEMODULE := $(IGATELIBRARY)
+endif
+
+ifeq (,$(IGATEDBFILE))
+IGATEDBFILE := $(basename $(BASETARGET)).in
+endif
+
+ifeq (WIN32_VC,$(PENV_COMPILER))
+  IGATEOFILE := $(IGATEFILE:%.cxx=$(ODIR)/%.obj)
+  NTC++FILETYPE := -Tp
+else # NON-WIN32_VC
+  IGATEOFILE := $(IGATEFILE:%.cxx=$(ODIR)/%.o)
+endif
+
+IGATENFILES := $(wildcard $(IGATESCAN:%.h=%.N))
+$(IGATEFILE): $(IGATESCAN) $(IGATENFILES)
+	$(INTERROGATE) $(IGATESYSPATH) $(IPATH) $(IGATEFLAGS) $(COMPILE_DEFS) -module "$(IGATEMODULE)" -library "$(IGATELIBRARY)" -oc $@ -od $(IGATEDBFILE) -fnames -string -refcount -assert -promiscuous -python $(IGATESCAN)
+$(IGATEOFILE): $(IGATEFILE)
+	@if [ ! -d $(ODIR) ]; then mkdir $(ODIR); fi
+ifeq (OSX,$(PENV))
+	$(C++) -c $(IPATH) $(SYS_IPATH) $(OPTIMIZE_FLAGS) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(C++FLAGS) $(NTC++FILETYPE) -DFILE_SYM_NAME=__$(subst .,_,$@)_file_find_me -DALL_FILE_SYMS_NAME="\"$(subst .,_,$(SUPERALLOFILES))\"" $< -o $@
+else  # OSX
+	$(C++) -c $(IPATH) $(SYS_IPATH) $(OPTIMIZE_FLAGS) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(C++FLAGS) $(NTC++FILETYPE) $< -o $@
+endif # OSX
+ALLOFILES := $(ALLOFILES) $(IGATEOFILE)
+
+clean::
+	rm -f $(IGATEOFILE) $(IGATEFILE) $(IGATEDBFILE)
+
+endif
+
+ifneq (,$(IGATEMSCAN))
+IGATEMC := $(basename $(BASETARGET)).module.cxx
+ifeq (WIN32_VC,$(PENV_COMPILER))
+  IGATEMO := $(IGATEMC:%.cxx=%.obj)
+else
+  IGATEMO := $(IGATEMC:%.cxx=%.o)
+endif
+$(IGATEMC): $(wildcard $(CTPROJROOT)/etc/*.in)
+	interrogate_module -oc $@ -module "$(IGATEMSCAN)" -library "$(IGATELIBRARY)" -python $(CTPROJROOT)/etc/*.in
+
+$(IGATEMO): $(IGATEMC)
+	@if [ ! -d $(ODIR) ]; then mkdir $(ODIR); fi
+ifeq (OSX,$(PENV))
+	$(C++) -c $(IPATH) $(SYS_IPATH) $(OPTIMIZE_FLAGS) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(C++FLAGS) $(NTC++FILETYPE) -DFILE_SYM_NAME=__$(subst .,_,$@)_file_find_me -DALL_FILE_SYMS_NAME="\"$(subst .,_,$(SUPERALLOFILES))\"" $< -o $@
+else  # OSX
+	$(C++) -c $(IPATH) $(SYS_IPATH) $(OPTIMIZE_FLAGS) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(C++FLAGS) $(NTC++FILETYPE) $< -o $@
+endif # OSX
+ALLOFILES := $(ALLOFILES) $(IGATEMO)
+
+clean::
+	rm -f $(IGATEMO) $(IGATEMC)
+endif # IGATEMSCAN
+
+ifeq (,$(USE_DEFERRED))
+  DEFERRED_FILES :=
+endif
+
+ifneq (,$(DEFERRED_FILES))
+include $(wildcard $(patsubst %,$(CTPROJROOT)/deferred/Deferred.%.*,$(DEFERRED_FILES)))
+endif
+
+
+ifneq (,$(ALLOFILES))
+clean::
+	rm -f $(ALLOFILES)
+endif
+
+
+$(TARGET): $(ALLOFILES)
+
+ifeq (Linux,$(PENV))
+DO_GNU_AUTO_DEP = yes
+endif
+
+ifneq (,$(DO_GNU_AUTO_DEP))
+
+#############################################################################
+#
+# GNU Auto-dependency rules.
+#
+
+%.d: %.c
+	$(SHELL) -ec '$(CC) -M $(IPATH) $(SYS_IPATH) $(OPTIMIZE_FLAGS) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(CFLAGS) $< \
+	  | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
+	  [ -s $@ ] || rm -f $@'
+
+%.d: %.cxx
+	$(SHELL) -ec '$(C++) -M $(IPATH) $(SYS_IPATH) $(OPTIMIZE_FLAGS) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(C++FLAGS) $< \
+	  | sed '\''s/\($*\)\.o[ :]*/\1.o $@ : /g'\'' > $@; \
+	  [ -s $@ ] || rm -f $@'
+
+ifneq (,$(IGATEOFILE))
+include $(IGATEOFILE:.o=.d)
+
+$(IGATEOFILE:.o=.d) : $(IGATEOFILE:.o=.cxx)
+	$(SHELL) -ec '$(C++) -M $(IPATH) $(SYS_IPATH) $(COMPILE_FLAGS) $(COMPILE_DEFS) $(C++FLAGS) $< \
+	  | sed '\''s/\($*\)\.o[ :]*$</\1.o $@ $< : /g'\'' > $@; \
+	  [ -s $@ ] || rm -f $@'
+
+clean::
+	rm -f $(IGATEOFILE:.o=.d)
+endif
+
+ifneq (,$(YCFILES))
+include $(YCFILES:.c=.d)
+
+clean::
+	rm -f $(YCFILES:.c=.d)
+endif
+
+ifneq (,$(YC++FILES))
+include $(YC++FILES:.cxx=.d)
+
+clean::
+	rm -f $(YC++FILES:.cxx=.d)
+endif
+
+ifneq (,$(CFILES))
+include $(CFILES:.c=.d)
+
+clean::
+	rm -f $(CFILES:.c=.d)
+endif
+
+ifneq (,$(C++FILES))
+include $(C++FILES:.cxx=.d)
+
+clean::
+	rm -f $(C++FILES:.cxx=.d)
+endif
+
+endif  # (,$(DO_GNU_AUTO_DEP))

+ 11 - 0
dtool/src/build/Makefile.o.template

@@ -0,0 +1,11 @@
+# Makefile for a collection of .o files
+
+#### State the target.  No need to change this.
+#TARGET = ofiles
+#CTTARGET
+
+#CTINCLUDE $DTOOL/lib/Makefile.o.include
+
+#### Add a cleanall target
+cleanall: clean
+	rm -rf $(PTREPOSITORY)

+ 354 - 0
dtool/src/build/Makefile.o.vars

@@ -0,0 +1,354 @@
+# Standard variable for creation of .o files and things that use .o
+# files (lib, bin).
+
+ifeq (,$(MAKEFILE_O_VARS))
+MAKEFILE_O_VARS = TRUE
+
+ifeq (,$(MAKEFILE_PENV_VARS))
+  include $(DTOOL)/inc/Makefile.penv.vars
+endif
+
+# First, examine the OPTIMIZE variable.  Make sure it is set to one
+# of the allowed values.
+ifeq (1,$(OPTIMIZE))
+  # Optimize 1 : no compiler optimizations, full debugging symbols.
+  DEBUGSYMBOLS = yes
+else
+  ifeq (2,$(OPTIMIZE))
+    # Optimize 2 : full compiler optimizations, full debugging symbols.
+    DEBUGSYMBOLS = yes
+  else
+    ifeq (3,$(OPTIMIZE))
+      # Optimize 3 : full compiler optimizations, no debugging symbols.
+    else
+      ifeq (4,$(OPTIMIZE))
+        # Optimize 4 : full compiler optimizations, no debugging symbols,
+        #              and assertion tests eliminated via NDEBUG.
+      else
+        ifeq (,$(OPTIMIZE))
+          # OPTIMIZE unspecified: assume Optimize 1.
+          OPTIMIZE = 1
+          DEBUGSYMBOLS = yes
+        else
+          # OPTIMIZE is none of the above: assume Optimize 4.
+          OPTIMIZE = 4
+        endif # old opt
+      endif # opt4
+    endif # opt3
+  endif # opt2
+endif # opt1
+
+BASETARGET := $(TARGET)
+DEBUGNAME :=
+
+ifeq (WIN32,$(PENV))
+  # If we are compiling with symbols, we rename the target to target_d.
+  # This helps us keep debug vs. nondebug libraries separate, and also
+  # helps us play along with Python's importing conventions.  But it's
+  # a big mess here in the makefiles.
+
+  ifeq (yes,$(DEBUGSYMBOLS))
+    DEBUGNAME := _d
+  endif
+
+  ifneq (,$(findstring .so,$(suffix $(TARGET))))
+    TARGET := $(TARGET:%.so=%$(DEBUGNAME).dll)
+  else
+    ifneq (,$(findstring .a,$(suffix $(TARGET))))
+      TARGET := $(TARGET:%.a=%$(DEBUGNAME).lib)
+    else
+      TARGET := $(TARGET:%=%.exe)
+    endif # .a
+  endif # .so
+endif # WIN32
+ifeq (OSX,$(PENV))
+  ifneq (,$(findstring .so,$(suffix $(TARGET))))
+    TARGET := $(TARGET:%.so=%.dylib)
+  endif # .so
+endif # OSX
+
+IGATESYSPATH = -S$(DTOOL)/inc/parser-inc -DCPPPARSER -D__cplusplus $(SYSTEM_IGATE_FLAGS)
+
+# Delete the default suffixes
+.SUFFIXES:
+
+# Make sure that CT_INCLUDE_PATH is set.
+ifeq (,$(CT_INCLUDE_PATH))
+  export CT_INCLUDE_PATH = .
+endif
+
+IPATH_DIRS := $(strip $(shell ctpathadjust $(CT_INCLUDE_PATH))) $(patsubst -I%,%,$(IPATH))
+
+# Add one more for dtool_config.h
+IPATH_DIRS += $(DTOOL)
+
+# Convert CT_INCLUDE_PATH to cc/CC compatible flag string
+ifeq (WIN32_VC,$(PENV_COMPILER))
+  IPATH_DIRS := $(foreach path,$(IPATH_DIRS),$(shell cygpath -w $(path)))
+  SYS_IPATH := -I"$(shell cygpath -w /msvc98/Include)"
+endif
+
+IPATH := $(patsubst %,-I"%",$(IPATH_DIRS))
+
+##### Playstation2 can't handle .so's.  The rename to .a's is handled here
+##### and acted upon in Makefile.so.rules.  (CSN)
+
+ifeq (PS2, $(PENV))
+  IPATH += -I/for/program/sce/ee/include
+
+  # Uncommenting this line will make the ps2 look for files on the dvd
+  # instead of on the host dev machine.
+
+  PS2_FILE_PREFIX := #### PS2_DVD_FILES
+
+  ifneq (,$(findstring .so,$(suffix $(TARGET))))
+    TARGET := $(TARGET:%.so=%.a)
+  endif
+endif
+
+##### End ps2
+
+COMPILE_FLAGS =
+COMPILE_DEFS =
+OPTIMIZE_FLAGS =
+
+ifeq (SGI,$(PENV))
+  # Standard applications and flags.
+  CC            = cc $(SGI_BINFORMAT_CC)
+  C++FLAGS      = -fullwarn $(WOFF_LIST)
+
+  # MIPSPro compiler cannot simultaneously optimize and encode
+  # debugging symbols.
+
+  ifeq (1,$(OPTIMIZE))
+    COMPILE_FLAGS = -g
+  else
+    ifeq (2,$(OPTIMIZE))
+      COMPILE_FLAGS =
+      OPTIMIZE_FLAGS = -O2 -OPT:Olimit=2500
+    else
+      ifeq (3,$(OPTIMIZE))
+        COMPILE_DEFS = -DOPTIMIZE
+        OPTIMIZE_FLAGS = -O2 -OPT:Olimit=2500
+      else
+        ifeq (4,$(OPTIMIZE))
+          COMPILE_DEFS = -DOPTIMIZE -DNDEBUG
+          OPTIMIZE_FLAGS = -O2 -OPT:Olimit=2500
+        endif # opt4
+      endif # opt3
+    endif # opt2
+  endif # opt1
+  
+  C++           = CC $(SGI_BINFORMAT_CC)
+
+  ifeq ($(SGI_BINFORMAT),o32)
+    
+    # These are the warning numbers according to the o32 compiler
+    # 3317 - controlling expression is constant, e.g. if (0) { ... }
+    # 3262 - function 'blah' was declared but never used
+    WOFF_LIST   = -woff 3317,3262
+    
+  else  # ($(SGI_BINFORMAT),n32)
+    
+    # These are the warning numbers according to the n32 compiler
+    # 1174 - function 'blah' was declared but never used
+    # 1201 - trailing comma is nonstandard.
+    # 1209 - controlling expression is constant, e.g. if (0) { ... }
+    # 1234 - access control not specified, 'public' by default
+    # 1355 - extra ";" ignored
+    # 1375 - destructor for base class is not virtual.
+    #    this one actually is bad.  But we got alot of them from the classes
+    #    that we've derived from STL collections.  Beware of this.
+    # 3322 - omission of explicit type is nonstandard ("int" assumed)
+    WOFF_LIST   = -woff 1174,1201,1209,1234,1355,1375,3322
+
+    # Linker warnings
+    # 85 - definition of SOMESYMBOL in SOMELIB preempts that of definition in
+    #      SOMEOTHERLIB.
+    WOFF_LIST   += -Wl,-LD_MSG:off=85
+    
+    # We'll also woff this one if we are compiling DELIVERY_PLAYER, which
+    # leaves out large chunks of code.
+    # 3201 - parameter was never referenced.
+    ifneq (,$(DELIVERY_PLAYER))
+      WOFF_LIST += -woff 3201
+    endif
+  endif   # $(SGI_BINFORMAT)
+
+  CFLAGS += -DPENV_SGI
+  C++FLAGS += -DPENV_SGI
+endif     # (SGI,$(PENV))
+
+ifeq (OSX,$(PENV))
+  # Standard applications and flags
+  CC = cc
+
+  ifeq (1,$(OPTIMIZE))
+    COMPILE_FLAGS = -g
+  else
+    ifeq (2,$(OPTIMIZE))
+      COMPILE_FLAGS = -g
+      OPTIMIZE_FLAGS = -O2
+    else
+      ifeq (3,$(OPTIMIZE))
+        COMPILE_FLAGS = -g
+        COMPILE_DEFS = -DOPTIMIZE
+        OPTIMIZE_FLAGS = -O2
+      else
+        ifeq (4,$(OPTIMIZE))
+          COMPILE_DEFS = -DOPTIMIZE -DNDEBUG
+          OPTIMIZE_FLAGS = -O2
+        endif # (4,$(OPTIMIZE))
+      endif # (3,$(OPTIMIZE))
+    endif # (2,$(OTPIMIZE))
+  endif  # (1,$(OPTIMIZE))
+
+  C++ = cc
+  TMPTARGETTHING := __$(BASETARGET:%.so=%_so)_find_me__
+  CFLAGS += -DPENV_OSX -DLIB_SYMBOL_NAME=$(TMPTARGETTHING)
+  C++FLAGS += -DPENV_OSX -DLIB_SYMBOL_NAME=$(TMPTARGETTHING) -ftemplate-depth-30
+endif     # (OSX,$(PENV))
+
+ifeq (Linux,$(PENV))
+  # Standard applications and flags.
+  CC            = gcc
+
+  ifeq (1,$(OPTIMIZE))
+    COMPILE_FLAGS = -g
+  else
+    ifeq (2,$(OPTIMIZE))
+      COMPILE_FLAGS = -g
+      OPTIMIZE_FLAGS = -O2
+    else
+      ifeq (3,$(OPTIMIZE))
+        COMPILE_FLAGS = -g
+        COMPILE_DEFS = -DOPTIMIZE
+        OPTIMIZE_FLAGS = -O2
+      else
+        ifeq (4,$(OPTIMIZE))
+          COMPILE_DEFS = -DOPTIMIZE -DNDEBUG
+          OPTIMIZE_FLAGS = -O2
+        endif # opt4
+      endif # opt3
+    endif # opt2
+  endif # opt1
+  
+  C++           = g++
+
+  CFLAGS += -DPENV_LINUX
+  C++FLAGS += -DPENV_LINUX -ftemplate-depth-30
+endif     # $(Linux,$(PENV))
+
+ifeq (PS2,$(PENV))
+  # Playstation2 apps and flags.
+
+  CC = ee-gcc
+  C++ = ee-g++
+
+  ifeq (1,$(OPTIMIZE))
+    COMPILE_FLAGS = -g
+  else
+    ifeq (2,$(OPTIMIZE))
+      COMPILE_FLAGS = -g
+      OPTIMIZE_FLAGS = -O2
+    else
+      ifeq (3,$(OPTIMIZE))
+        COMPILE_FLAGS = -g
+        COMPILE_DEFS = -DOPTIMIZE
+        OPTIMIZE_FLAGS = -O2
+      else
+        ifeq (4,$(OPTIMIZE))
+          COMPILE_DEFS = -DOPTIMIZE -DNDEBUG
+          OPTIMIZE_FLAGS = -O2
+        endif # opt4
+      endif # opt3
+    endif # opt2
+  endif # opt1
+
+  CFLAGS += -DPENV_PS2
+  C++FLAGS += -DPENV_PS2 -ftemplate-depth-30
+
+endif	# $(PS2,$(PENV))
+
+ifeq (WIN32,$(PENV))
+  # Standard applications and flags.
+  # Note:  You must also set LDFLAGS and LINKFLAGS in Makefile.bin.vars
+  CC 	  = cl
+  C++     = cl
+
+  # tell cl.exe to generate .sbr files, which bscmake can compile into Msdev source browser info
+  ifeq (1,$(CL_MAKE_BROWSE_INFO))
+      BROWSEINFO_FLAG := -Fr 
+  endif
+
+  ifeq (1,$(OPTIMIZE))
+    # -Fd is change to write out per-obj .pdb, to allow parallelization
+    COMPILE_FLAGS = -MDd -GZ -Zi $(BROWSEINFO_FLAG) -Fd$(basename $@) 
+    COMPILE_DEFS = -D_DEBUG
+    LDTYPE := -DLL -DEBUG
+  else
+    ifeq (2,$(OPTIMIZE))
+      COMPILE_FLAGS = -MDd -Zi -Fd$(basename $@)
+      COMPILE_DEFS = -D_DEBUG
+      OPTIMIZE_FLAGS = -O2 -Ob1 -Ogity -G6
+      LDTYPE := -DLL -DEBUG
+    else
+      ifeq (3,$(OPTIMIZE))
+        COMPILE_FLAGS = -MD
+        COMPILE_DEFS = -DOPTIMIZE
+        OPTIMIZE_FLAGS = -O2 -Ob1 -Ogity -G6 -Gi-
+	LDTYPE := -DLL
+      else
+        ifeq (4,$(OPTIMIZE))
+          COMPILE_FLAGS = -MD
+          COMPILE_DEFS = -DOPTIMIZE -DNDEBUG
+          OPTIMIZE_FLAGS = -O2 -Ob1 -Ogity -G6 -Gi-
+          LDTYPE := -DLL
+        endif # opt4
+      endif # opt3
+    endif # opt2
+  endif # opt1
+
+   # removed -FD (generate file-depedency vc60.idb files) to allow parallelization
+   CFLAGS += -nologo -W3 -EHsc -Zm250 -D_WINDOWS -DWIN32 -D_WINDLL -DSTRICT -DPENV_WIN32 -DWIN32_VC
+   C++FLAGS += -nologo -W3 -EHsc -Zm250  -D_WINDOWS -DWIN32 -D_WINDLL -DSTRICT -DPENV_WIN32 -DWIN32_VC
+
+endif     # $(WIN32,$(PENV))
+
+ifeq (SunOS,$(PENV))
+  # Standard applications and flags.
+  CC            = egcc
+
+  ifeq (1,$(OPTIMIZE))
+    OPTIMIZE_FLAGS = -g
+  else
+    ifeq (2,$(OPTIMIZE))
+      OPTIMIZE_FLAGS = -O2 -g
+    else
+      ifeq (3,$(OPTIMIZE))
+        OPTIMIZE_FLAGS = -O2 -g -DOPTIMIZE -DNDEBUG
+      else
+        ifeq (4,$(OPTIMIZE))
+          OPTIMIZE_FLAGS = -O2 -DOPTIMIZE -DNDEBUG
+        endif # opt4
+      endif # opt3
+    endif # opt2
+  endif # opt1
+  
+  C++           = eg++-new -DUsePthreads
+
+  CFLAGS += -DPENV_SunOS
+  C++FLAGS += -DPENV_SunOS
+endif     # $(SunOS,$(PENV))
+
+INTERROGATE	= interrogate
+IGATEFLAGS	=
+
+
+ODIR            = .
+
+# Set the default target
+install all: $(TARGET)
+
+endif   # MAKEFILE_O_VARS
+

+ 57 - 0
dtool/src/build/Makefile.penv.vars

@@ -0,0 +1,57 @@
+# Variable(s) to declare the project compilation and execution environment.
+
+ifeq (,$(MAKEFILE_PENV_VARS))
+MAKEFILE_PENV_VARS = TRUE
+
+ifeq (,$(PENV))
+PENV = SGI
+endif
+
+ifeq (SGI,$(PENV))
+  # Defines the binary format (o32 vs. n32) for compiling.
+  
+  # This is the default binformat if it is not overridden in a sub-Makefile.
+  DEFAULT_BINFORMAT = n32
+   
+  ifeq ($(SGI_BINFORMAT),)
+    SGI_BINFORMAT = $(DEFAULT_BINFORMAT)
+  endif
+  
+  ifeq ($(SGI_BINFORMAT),o32)
+    SGI_BINFORMAT_CC = -mips2 -o32
+    SGI_BINFORMAT_SALIVATE = -o32
+    SGI_BINFORMAT_LIB = lib
+  else
+    SGI_BINFORMAT_CC = -mips3 -n32
+    SGI_BINFORMAT_SALIVATE = -n32
+    SGI_BINFORMAT_LIB = lib32
+  endif
+
+  SYSTEM_IGATE_FLAGS = -D__mips__ -D__MIPSEB__ -DPENV_SGI
+endif
+
+ifeq (OSX,$(PENV))
+  SYSTEM_IGATE_FLAGS =
+endif
+
+ifeq (Linux,$(PENV))
+
+  SYSTEM_IGATE_FLAGS = -D__i386__ -DPENV_LINUX
+
+endif
+
+ifeq (WIN32,$(PENV))
+
+  # Guarantee that PENV_COMPILER gets set to default to VC
+  PENV_COMPILER = WIN32_VC
+
+  SYSTEM_IGATE_FLAGS = -longlong __int64 -D_X86_ -DPENV_WIN32 -DWIN32_VC -D"_declspec(param)="
+
+  # Windows is always a deferred build.
+  USE_DEFERRED := yes
+
+endif # WIN32 
+
+
+endif   # MAKEFILE_PENV_VARS
+

+ 18 - 0
dtool/src/build/Makefile.project.template

@@ -0,0 +1,18 @@
+# Makefile for project.
+# Should live at project root directory, and be called Makefile.
+
+# Do not delete the line below.  It tells ctaddpkg to automatically
+# append install Makefiles when packages are created.
+# CT-STANDARD-PROJECT-MAKEFILE
+
+# Specify project name and project root directory.
+#CTPROJECT
+#CTPROJROOT
+
+include $(DTOOL)/inc/Makefile.project.vars
+
+# Add packages to end of file as follows:
+# 	include src/all/PACKAGE/Makefile.install
+# ... or whatever path to install Makefile
+
+#CTINSTPKG

+ 68 - 0
dtool/src/build/Makefile.project.vars

@@ -0,0 +1,68 @@
+# Standard variables and targets for projects.
+
+ifeq (,$(MAKEFILE_PROJECT_VARS))
+MAKEFILE_PROJECT_VARS = TRUE
+
+# Guarantee these are all empty (we don't want a conflict with any env vars)
+LIBS :=
+INCLUDE :=
+BINS :=
+SCRIPTS :=
+SS :=
+STK :=
+MODELS :=
+ETC :=
+DOC :=
+MAN :=
+FONTS :=
+ICONS :=
+APPDEFAULTS :=
+TCL :=
+TELEUSE :=
+SHADERS :=
+
+ifeq (,$(MAKEFILE_PENV_VARS))
+include $(DTOOL)/inc/Makefile.penv.vars
+endif
+
+ifeq (,$(CTPROJECT))
+CTPROJECT = project
+endif
+
+ifeq (,$(CTPROJROOT))
+CTPROJROOT := $(shell $(DTOOL)/bin/ctproj -r)
+endif
+
+ifneq (,$(OPTIMIZE))
+export OPTIMIZE
+endif
+
+$(CTPROJECT): install
+
+install: install-$(CTPROJECT)
+
+uninstall: uninstall-$(CTPROJECT)
+
+clean: clean-$(CTPROJECT)
+
+cleanall: cleanall-$(CTPROJECT)
+
+touch: touch-$(CTPROJECT)
+
+copy: copy-$(CTPROJECT)
+
+isinstalled: isinstalled-$(CTPROJECT)
+
+notinstalled: notinstalled-$(CTPROJECT)
+
+checkinstall: checkinstall-$(CTPROJECT)
+
+toinstall: toinstall-$(CTPROJECT)
+
+depends: depends-$(CTPROJECT)
+
+nodepends: nodepends-$(CTPROJECT)
+
+showuses: showuses-$(CTPROJECT)
+
+endif  # MAKEFILE_PROJECT_VARS

+ 158 - 0
dtool/src/build/Makefile.so.rules

@@ -0,0 +1,158 @@
+# Rules to construct .so's from component files.
+
+ifneq (,$(SOLOCATIONS))
+.PRECIOUS: $(SOLOCATIONS)
+  ifeq (SGI,$(PENV))
+    ifeq (ld,$(LD))
+      SLOC := -update_registry $(SOLOCATIONS)
+    else
+      SLOC := -Wl,-update_registry,$(SOLOCATIONS)
+    endif
+  endif  # (SGI,$(PENV))
+endif  # $(SOLOCATIONS)
+
+
+ifeq (SGI,$(PENV))
+  ifeq (ld,$(LD))
+    NONE = -none
+  else
+    NONE = -Wl,-none
+  endif
+
+  DEFINE_SONAME = -soname $@
+endif  # (SGI,$(PENV))
+
+ifeq (SunOS,$(PENV))
+  SHARED_COMMAND = -G
+else
+  ifeq (OSX,$(PENV))
+    SHARED_COMMAND = -dynamiclib
+  else
+    SHARED_COMMAND = -shared
+  endif
+endif  # (SunOS,$(PENV))
+
+ifeq (OSX,$(PENV))
+ALL = 
+else
+ALL = -all
+endif  # (OSX,$(PENV))
+BASEFILE =
+
+ALLOFILES := $(ALLOFILES) $(OFILES)
+
+ifeq (,$(USE_DEFERRED))
+  LIBS := $(WHEN_NO_DEFER_LIBS) $(LIBS)
+else
+  LIBS := $(WHEN_DEFER_LIBS) $(LIBS)
+endif
+
+ifeq (,$(USE_DEFERRED))
+  SHOULD_DEFER_TARGET :=
+else
+  SHOULD_DEFER_TARGET := $(DEFERRED_TARGET)
+endif
+
+ifneq (,$(SHOULD_DEFER_TARGET))
+
+  # If the makefile requests a "deferred target", it means that we'll
+  # just write out a mini-makefile that defines the .o files that go
+  # into the target, rather than actually building the target now.
+  # Another Makefile later will presumably do the actual building.
+
+  DEFERRED_MAKEFILE := Deferred.$(DEFERRED_TARGET).$(BASETARGET)
+  THISDIR := $(notdir $(shell pwd))
+
+$(TARGET) : $(DEFERRED_MAKEFILE)
+$(DEFERRED_MAKEFILE): $(wildcard Makefile.*)
+	rm -f $@
+	echo ALLOFILES += $(patsubst ./%,../../src/$(THISDIR)/%,$(ALLOFILES)) > $@
+
+else # DEFERRED_TARGET
+
+  ifneq (,$(strip $(ALLOFILES)))
+
+  # This is less than ideal.  This means that the .so file doesn't get
+  # added to the configuration record, and hence gets none of the
+  # clearmake magic like derived-object status and winking in.
+  # However, it also means that clearmake doesn't get tricked by the
+  # so_locations file, so it seems to be a better choice than the
+  # alternative for the moment.
+  .NO_CONFIG_REC: $(TARGET)
+
+  TARGETLIB =
+  BASELIB =
+  DEFLIB =
+  EXPLIB =
+  PDBLIB =
+  LIBLIB =
+  VCFILES =
+
+  # Eliminate -lm and -ldl on NT because they don't exist
+  WINLIBS := $(filter-out -lm -ldl,$(SYSLIBS))
+  # On NT -l<library> needs to map to lib<library>.lib
+  WINLIBS := $(LIBS:-l%=lib%$(DEBUGNAME).lib) $(WINLIBS:-l%=lib%.lib)
+  # We also need to handle any explicitly listed .a libraries 
+  WINLIBS := $(WINLIBS:%.a=%.lib)
+  ifeq (WIN32_VC,$(PENV_COMPILER))
+    PDBLIB := $(TARGET:%.dll=%.pdb)
+    EXPLIB := $(TARGET:%.dll=%.exp)
+    LIBLIB := $(TARGET:%.dll=%.lib)
+    VCFILES := vc60.idb vc60.pdb
+  endif # WIN32_VC
+  
+  $(TARGET): $(OFILES)  # *not* ALLOFILES
+
+  #### The PlayStation2 doesn't do .so files AT ALL.
+  #### Solution: Every time panda/tool wants a .so, we make a .a
+
+  ifeq (PS2, $(PENV))
+	ee-ar -r a.out.$@ $(ALLOFILES)
+  else
+  ifeq (WIN32,$(PENV))
+    ifeq (WIN32_VC,$(PENV_COMPILER))
+	$(LD) $(LDFLAGS) $(LDTYPE) \
+		$(LPATH) $(LINKFLAGS) $(ALLOFILES) $(WINLIBS) -OUT:$@
+    endif # PENV_COMPILER 
+  else # NON-WIN32 
+    ifeq (OSX,$(PENV))
+	$(LD) $(SHARED_COMMAND) $(PTR) $(PTFLAGS) $(SLOC) $(LDFLAGS) \
+              $(LPATH) $(ALL) $(ALLOFILES) \
+              $(NONE) $(LIBS) $(SYSLIBS) -o $@ $(DEFINE_SONAME) \
+              $(BASEFILE) $(BASELIB) -lstdc++
+    else # non-win32 and non-OSX
+	$(LD) $(SHARED_COMMAND) $(PTR) $(PTFLAGS) $(SLOC) $(LDFLAGS) \
+		$(LPATH) $(ALL) $(ALLOFILES) \
+		$(NONE) $(LIBS) $(SYSLIBS) -o a.out.$@ $(DEFINE_SONAME) \
+		$(BASEFILE) $(BASELIB)
+    endif # non-win32 and non-OSX
+  endif # WIN32 
+  endif # PS2
+  
+  ifneq (WIN32,$(PENV))
+    ifneq (OSX,$(PENV))
+	mv a.out.$@ $@
+    endif # non-win32 and non-OSX
+    ifneq (SGI,$(PENV))
+      ifeq (4,$(OPTIMIZE))
+	strip $@
+      endif # (4,$(OPTIMIZE))
+    endif # (SGI,$(PENV))
+  endif
+  
+  endif # (,$(ALLOFILES))
+
+endif   # DEFERRED_TARGET
+  
+clean::
+	@rm -f $(TARGET) $(TARGETLIB) $(BASELIB) $(DEFLIB) $(EXPLIB) \
+		$(WINLIBS) $(PDBLIB) $(LIBLIB) $(VCFILES)
+
+cleanall: clean
+	rm -fr ii_files
+	rm -f $(TARGET) $(TARGETLIB) $(BASELIB) $(DEFLIB) $(EXPLIB) \
+		$(WINLIBS) $(PDBLIB) $(LIBLIB) $(VCFILES)
+
+list:
+	@echo $(TARGET) $(TARGETLIB) $(BASELIB) $(DEFLIB) $(EXPLIB) \
+		$(WINLIBS) $(PDBLIB) $(LIBLIB)

+ 22 - 0
dtool/src/build/Makefile.so.template

@@ -0,0 +1,22 @@
+#### Makefile for DSO's.  Any fields commented out are optional.
+
+#### Target's name:
+#CTTARGET
+
+#CTINCLUDE $DTOOL/lib/Makefile.o.include
+
+#### Pull in standard binary make variables.
+include $(DTOOL)/inc/Makefile.bin.vars
+
+#### Other files and lib.  Include $(ODIR) in any .o names.
+# OFILES = 
+# LIBS = 
+
+#### Additional search directories for lib:
+# LPATH := $(LPATH) -L/my/directory -L/my/other/directory
+
+#### Other linker flags. 
+# LDFLAGS = 
+
+#### The .so action is here.
+include $(DTOOL)/inc/Makefile.so.rules

+ 55 - 0
dtool/src/build/Makefile.ss.rules

@@ -0,0 +1,55 @@
+# Rules to construct .ss's from component files.
+
+##############################################################################
+#
+# .h -> .ss conversion rules
+#
+
+# Clear ALLSSFILES
+ALLSSFILES =
+
+ifneq (,$(HFILES))
+HSSFILES := $(HFILES:%.h=%.ss)
+$(HSSFILES) : %.ss : %.h
+	$(SALIVATE) $(SALIVATE-FLAGS) $< > $@
+ALLSSFILES := $(ALLSSFILES) $(HSSFILES)
+endif
+
+ifneq (,$(HHFILES))
+HHSSFILES := $(HHFILES:%.hh=%.ss)
+$(HHSSFILES) : %.ss : %.hh
+	@ cat $< > $(sstotmp)
+	@ for i in ${HHDIRS} ; do if test -r $$i/$(sstoh) ; then \
+          cat $$i/$(sstoh) >> $(sstotmp) ; fi ; done
+	$(SALIVATE) $(SALIVATE-FLAGS) $(sstotmp) > $@
+	@ rm -f $(sstotmp)
+ALLSSFILES := $(ALLSSFILES) $(HHSSFILES)
+endif
+
+TOTALSSFILES := $(ALLSSFILES) $(OTHERSSFILES)
+
+LIBTARGET := $(addprefix lib,$(addsuffix .so,$(basename $(TARGET))))
+
+ifneq (,$(TOTALSSFILES))
+$(TARGET): $(TOTALSSFILES)
+	@ echo -n "**** Creating Meta-ss file "$(TARGET)" ... "
+	@ echo '(load-shared-object "'$(LIBTARGET)'")' > $@
+ifeq (,$(STRAIGHTINCLUDE))
+	@ echo '(define dl-handle (dlopen "'$(LIBTARGET)'" 2))' >> $@
+	@ for i in ${TOTALSSFILES} ; do echo '  ('load-once '"'$$i'")' >> $@ ; done
+else
+	@ for i in ${TOTALSSFILES} ; do echo '  ('load-once '"'$$i'")' >> $@ ; done
+endif
+	@ echo "done"
+endif
+
+ifneq (,$(ALLSSFILES))
+clean::
+	rm -f $(TARGET) $(ALLSSFILES)
+endif
+
+cleanall: clean
+	rm -f $(TARGET)
+
+list:
+	@ echo $(TARGET)

+ 21 - 0
dtool/src/build/Makefile.ss.template

@@ -0,0 +1,21 @@
+#### Makefile for ss interfaces.  Any fields commented out are optional.
+
+#### Target's name:
+#CTTARGET
+
+#### Pull in standard .ss make variables
+include $(DTOOL)/inc/Makefile.ss.vars
+
+#### Source files
+# HFILES  = 
+# HHFILES = 
+# HHDIRS  = 
+
+#### Additional ss files to be inlcuded.
+# OTHERSSFILES = 
+
+#### Flags to control meta-ss creation.
+# STRAIGHTINCLUDE = TRUE
+
+#### The .ss action is here.
+include $(DTOOL)/inc/Makefile.ss.rules

+ 28 - 0
dtool/src/build/Makefile.ss.vars

@@ -0,0 +1,28 @@
+# Standard variable for creation of .ss files
+
+ifeq (,$(MAKEFILE_SS_VARS))
+MAKEFILE_SS_VARS = TRUE
+
+ifeq (,$(MAKEFILE_PENV_VARS))
+include $(DTOOL)/inc/Makefile.penv.vars
+endif
+
+# Delete the default suffixes
+.SUFFIXES:
+
+# Standard applications and flags.
+SALIVATE       = salivate $(SGI_BINFORMAT_SALIVATE)
+SALIVATE-FLAGS =
+
+ifneq (,$(DELIVERY_PLAYER))
+SALIVATE-FLAGS += -DDELIVERY_PLAYER
+endif
+
+# Some conversion macros
+sstotmp = `echo \`basename $@ ss\`tmp`
+sstoh   = `echo \`basename $@ ss\`h`
+
+# Set the default target
+install all : $(TARGET)
+
+endif  # MAKEFILE_SS_VARS

+ 20 - 0
dtool/src/build/Makefile.uxb.rules

@@ -0,0 +1,20 @@
+# UXB (teleuse) Makefile rules
+
+ifneq (,$(OPTIMIZE))
+UFLAGS := $(UFLAGS) -DOPTIMIZE
+endif
+
+all:
+	uxb $(UFLAGS)
+
+clean:
+	uxb $(UFLAGS) clean
+
+cleanall:
+	uxb $(UFLAGS) delete
+	rm -rf ii_files
+
+list:
+	@echo -n	
+
+install: all

+ 7 - 0
dtool/src/build/Makefile.uxb.template

@@ -0,0 +1,7 @@
+# Makefile for uxb (teleuse)
+
+#### flags to pass to uxb
+UFLAGS = 
+
+#### The uxb action is here.
+include $(DTOOL)/inc/Makefile.uxb.rules

+ 20 - 0
dtool/src/build/Sources.pp

@@ -0,0 +1,20 @@
+#define INSTALL_LIBS \
+    Makefile.a.template Makefile.bin.template Makefile.foreign.template \
+    Makefile.install.template Makefile.meta.template Makefile.o.include \
+    Makefile.o.template Makefile.project.template Makefile.so.template \
+    Makefile.ss.template Makefile.uxb.template
+
+#define INSTALL_HEADERS \
+    Makefile.a.rules Makefile.bin.rules Makefile.bin.vars \
+    Makefile.foreign.rules Makefile.foreign.vars Makefile.install.rules \
+    Makefile.install.vars Makefile.meta.rules Makefile.o.rules \
+    Makefile.o.vars Makefile.project.vars Makefile.so.rules \
+    Makefile.ss.rules Makefile.ss.vars Makefile.uxb.rules \
+    Makefile.penv.vars \
+    ctinstmake.pl ctproj.pl ctutils.pl
+
+#define INSTALL_SCRIPTS \
+    ctaddpkg ctaddtgt ctinitproj ctproj ctpathadjust
+
+#define EXTRA_DIST \
+    initialize

+ 92 - 0
dtool/src/build/ctaddpkg

@@ -0,0 +1,92 @@
+#!/usr/local/bin/perl
+
+if ($#ARGV != 0) {
+   exit print "Usage: ctaddpkg package-name\n" ;
+}
+
+$pkgname = $ARGV[0] ;
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured for CTtools" ;
+}
+
+#pull in tools for getting information on the project
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+
+#get what project we're currently in, and where it's root is.
+$proj = &CTProj ;
+$projroot = &CTProjRoot($proj) ;
+$projname = $proj ;
+$projname =~ tr/A-Z/a-z/ ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+#see if such a package already exists, if so STOP
+if ( -e "$projroot/src/all/$pkgname" ) {
+   die "Package '$pkgname' already exists in this project ('$proj')" ;
+}
+
+#make sure there is a project-wide makefile
+if ( ! -e "$projroot/Makefile" ) {
+   die "No project-wide Makefile for project '$proj'" ;
+}
+
+#make sure there is a package Makefile template
+if ( ! -e "$tool/lib/Makefile.meta.template" ) {
+   die "No package Makefile template in $tool/lib/." ;
+}
+
+#make sure there is a package install Makefile template
+if ( ! -e "$tool/lib/Makefile.install.template" ) {
+   die "No package install Makefile template in $tool/lib/." ;
+}
+
+#make the package directory
+require "$tool/inc/ctcm.pl" ;
+$item = "$projroot/src/all/$pkgname" ;
+if ( ! -e $item ) {
+    if ( ! &CTCMMkdir( $item, $projname, $spec ) ) {
+	die "Could not create directory '" . $item . "'\n" ;
+    }
+}
+
+#pull in tools for installing Makefiles
+require "$tool/inc/ctinstmake.pl" ;
+
+#install a package makefile and package install makefile into the package
+$item = "$projroot/src/all/$pkgname/Makefile" ;
+&CTInstallMake( "$tool/lib/Makefile.meta.template", $item ) ;
+if ( ! &CTCMMkelem( $item, $projname, $spec ) ) {
+    die "Could not make a verioned element of the project makefile\n" ;
+}
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+
+$item = "$projroot/src/all/$pkgname/Makefile.install" ;
+&CTInstallMake( "$tool/lib/Makefile.install.template", $item ) ;
+if ( ! &CTCMMkelem( $item, $projname, $spec ) ) {
+    die "Could not make a verioned element of the project install makefile\n" ;
+}
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+
+# delta the package in
+$item = "$projroot/src/all/$pkgname" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+
+# update the master makefile
+$item = "$projroot/Makefile" ;
+if ( ! &CTCMCheckout( $item, $projname, $spec ) ) {
+    die "Could not checkout master project makefile\n" ;
+}
+&CTInstallScanMake( $item ) ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta master project makefile\n" ;
+}

+ 91 - 0
dtool/src/build/ctaddtgt

@@ -0,0 +1,91 @@
+#!/usr/local/bin/perl
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured to run CTtools" ;
+}
+
+if ($#ARGV == -1) {
+   exit print "Usage: ctaddtgt [{bin,a,so,ss,foreign}] target-name ...\n" ;
+}
+
+require "$tool/inc/ctproj.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+
+@arglist = @ARGV ;
+
+$projname = &CTProj ;
+$projname =~ tr/A-Z/a-z/ ;
+$projroot = &CTProjRoot( $projname ) ;
+$pkgname = &CTProjPkg( $projname ) ;
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+# check for package makefile and package install makefile
+
+while ( @arglist != () ) {
+   # initialize target type to default
+   $type = "bin" ;
+
+   # potentially get the target type
+   if ( $arglist[0] eq "bin" ) {
+      shift( @arglist ) ;    # already set
+   } elsif (( $arglist[0] eq "foreign" ) || ( $arglist[0] eq "a" ) ||
+	    ( $arglist[0] eq "so" ) || ( $arglist[0] eq "ss" )) {
+      $type = $arglist[0] ;
+      shift( @arglist ) ;
+   }
+
+   # get the target name
+   $tgtname = $arglist[0] ;
+   $fulltgtname = $tgtname ;
+   shift( @arglist ) ;
+
+   require "$tool/inc/ctinstmake.pl" ;
+   require "$tool/inc/ctcm.pl" ;
+
+   $item = "$projroot/src/all/$pkgname" ;
+   if ( ! &CTCMCheckout( $item, $projname, $spec )) {
+       die "Could not checkout package '" . $pkgname . "'\n" ;
+   }
+   $item = "$projroot/src/all/$pkgname/Makefile" ;
+   if ( ! &CTCMCheckout( $item, $projname, $spec )) {
+       die "Could not checkout package '" . $pkgname . "' Makefile\n" ;
+   }
+
+   $curdir = "$projroot/src/all/$pkgname" ;
+   # install target makefile, and update package makefile
+   if ( $type eq "bin" ) {
+      &CTInstallMake( "$tool/lib/Makefile.bin.template",
+		      "$curdir/Makefile.$tgtname" ) ;
+      &CTInstallScanMake( "$curdir/Makefile" ) ;
+   } elsif ( $type eq "a" ) {
+      $fulltgtname = "lib" . $tgtname ;
+      &CTInstallMake( "$tool/lib/Makefile.a.template",
+		      "$curdir/Makefile.$tgtname" ) ;
+      &CTInstallScanMake( "$curdir/Makefile" ) ;
+   } elsif ( $type eq "so" ) {
+      $fulltgtname = "lib" . $tgtname ;
+      &CTInstallMake( "$tool/lib/Makefile.so.template",
+		      "$curdir/Makefile.$tgtname" ) ;
+      &CTInstallScanMake( "$curdir/Makefile" ) ;
+   } elsif ( $type eq "ss" ) {
+      &CTInstallMake( "$tool/lib/Makefile.ss.template",
+		      "$curdir/Makefile.$tgtname" ) ;
+      &CTInstallScanMake( "$curdir/Makefile" ) ;
+   } elsif ( $type eq "foreign" ) {
+      &CTInstallMake( "$tool/lib/Makefile.foreign.template",
+		      "$curdir/Makefile.$tgtname" ) ;
+      &CTInstallScanMake( "$curdir/Makefile" ) ;
+   }
+
+   $item = "$curdir/Makefile.tgtname" ;
+   if ( ! &CTCMMkelem( $item, $projname, $spec ) ) {
+       die "Could not make a verioned element of the target makefile\n" ;
+   }
+}
+
+print "You will want to edit Makefile, Makefile.install, and the target makefile(s)\n" ;
+print "manually.  Also, do not forget to delta the Makefile, target Makefile, and\n" ;
+print "directory when you are done.\n" ;

+ 128 - 0
dtool/src/build/ctinitproj

@@ -0,0 +1,128 @@
+#!/usr/local/bin/perl
+
+if ( $#ARGV != 1 ) {
+   print "Usage: ctinitproj project-name project-root\n" ;
+   print "    You should already be attached to the project\n" ;
+   exit print "    ex: ctinitproj dtool $DTOOL\n" ;
+}
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured for CTtools" ;
+}
+
+require "$tool/inc/ctutils.pl" ;
+require "$tool/inc/ctvspec.pl" ;
+require "$tool/inc/ctquery.pl" ;
+
+$projname = $ARGV[0] ;
+$projroot = &CTUShellEval( $ARGV[1] );
+$flav = &CTQueryProj( $projname ) ;
+$spec = &CTResolveSpec( $projname, $flav ) ;
+
+# make sure the directory exists
+if ( ! -e $projroot ) {
+   die "Project root ('$projroot') does not exist" ;
+}
+
+require "$tool/inc/ctcm.pl" ;
+
+# make all the default subdirectories
+$item = "$projroot/bin" ;
+if ( ! -e $item ) {
+    if ( ! &CTCMMkdir( $item, $projname, $spec ) ) {
+	die "Could not create directory '" . $item . "'\n" ;
+    }
+}
+$item = "$projroot/etc" ;
+if ( ! -e $item ) {
+    if ( ! &CTCMMkdir( $item, $projname, $spec ) ) {
+	die "Could not create directory '" . $item . "'\n" ;
+    }
+}
+$item = "$projroot/inc" ;
+if ( ! -e $item ) {
+    if ( ! &CTCMMkdir( $item, $projname, $spec ) ) {
+	die "Could not create directory '" . $item . "'\n" ;
+    }
+}
+$item = "$projroot/lib" ;
+if ( ! -e $item ) {
+    if ( ! &CTCMMkdir( $item, $projname, $spec ) ) {
+	die "Could not create directory '" . $item . "'\n" ;
+    }
+}
+$item = "$projroot/lib/ss" ;
+if ( ! -e $item ) {
+    if ( ! &CTCMMkdir( $item, $projname, $spec ) ) {
+	die "Could not create directory '" . $item . "'\n" ;
+    }
+}
+$item = "$projroot/lib/stk" ;
+if ( ! -e $item ) {
+    if ( ! &CTCMMkdir( $item, $projname, $spec ) ) {
+	die "Could not create directory '" . $item . "'\n" ;
+    }
+}
+$item = "$projroot/src" ;
+if ( ! -e "$projroot/src" ) {
+    if ( ! &CTCMMkdir( $item, $projname, $spec ) ) {
+	die "Could not create directory '" . $item . "'\n" ;
+    }
+}
+$item = "$projroot/src/all" ;
+if ( ! -e "$projroot/src/all" ) {
+    if ( ! &CTCMMkdir( $item, $projname, $spec ) ) {
+	die "Could not create directory '" . $item . "'\n" ;
+    }
+}
+
+# install the project-wide Makefile
+require "$tool/inc/ctinstmake.pl" ;
+
+$item = "$projroot/Makefile" ;
+&CTInstallMake( "$tool/lib/Makefile.project.template", $item ) ;
+if ( ! &CTCMMkelem( $item, $projname, $spec ) ) {
+    die "Could not make a versioned element of the master makefile\n" ;
+}
+
+# now delta everything in
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+ $item = "$projroot/src/all" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+$item = "$projroot/src" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+$item = "$projroot/lib/stk" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+$item = "$projroot/lib/ss" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+$item = "$projroot/lib" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+$item = "$projroot/inc" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+$item = "$projroot/etc" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+$item = "$projroot/bin" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}
+$item = "$projroot" ;
+if ( ! &CTCMDelta( $item, $projname, $spec ) ) {
+    die "Could not delta '" . $item . "'\n" ;
+}

+ 54 - 0
dtool/src/build/ctinstmake.pl

@@ -0,0 +1,54 @@
+# copy the template makefile to output, recursively expanding marked inclusions
+sub CTInstallMakeWrite {
+   local( *INMAKE ) ;
+   open( INMAKE, "<$_[0]" ) ;
+   while ( <INMAKE> ) {
+      if ( /^#CTINCLUDE/ ) {
+	 s/\n$// ;
+	 local( @CTIMWlist ) ;
+	 @CTIMWlist = split ;
+	 local( $tool ) = $ENV{ "DTOOL" } ;
+	 require "$tool/inc/ctutils.pl" ;
+	 local( $CTIMWtmp ) = &CTUShellEval( $CTIMWlist[1] ) ;
+	 &CTInstallMakeWrite( $CTIMWtmp ) ;
+      } elsif (( /^#CTPROJECT/ ) && ( $projname ne "" )){
+	 local( $CTIMWtmp ) = $projname ;
+         $CTIMWtmp =~ tr/A-Z/a-z/ ; # tolower
+	 print OUTMAKE "CTPROJECT = $CTIMWtmp\n" ;
+      } elsif (( /^#CTPROJROOT/ ) && ( $projname ne "" )) {
+	 local( $CTIMWtmp ) = $projname ;
+         $CTIMWtmp =~ tr/a-z/A-Z/ ; # toupper
+	 print OUTMAKE "CTPROJROOT = \$($CTIMWtmp)\n" ;
+      } elsif (( /^#CTPACKAGE/ ) && ( $pkgname ne "" )) {
+	 print OUTMAKE "PACKAGE = $pkgname\n" ;
+      } elsif (( /^#CTINSTPKG/ ) && ( $pkgname ne "" )) {
+	 print OUTMAKE "include src/all/$pkgname/Makefile.install\n" ;
+	 print OUTMAKE "#CTINSTPKG\n" ;
+      } elsif (( /^#CTTARGET/ ) && ( $fulltgtname ne "" )) {
+	 print OUTMAKE "TARGET = $fulltgtname\n" ;
+      } elsif (( /^SUBMAKES/ ) && ( $tgtname ne "" )) {
+	 s/\n$// ;
+	 print OUTMAKE "$_ $tgtname\n" ;
+      } else {
+	 print OUTMAKE $_ ;
+      }
+   }
+   close( INMAKE ) ;
+}
+
+# install a given makefile template, expanding any internal directives
+sub CTInstallMake {
+   local( *OUTMAKE ) ;
+   open( OUTMAKE, ">$_[1]" ) ;
+   &CTInstallMakeWrite( $_[0] ) ;
+   close( OUTMAKE );
+}
+
+# Scan the given makefile for CT markers to be expanded
+sub CTInstallScanMake {
+   local( $CTISMname ) = "/tmp/make.$$" ;
+   &CTInstallMake( $_[0], $CTISMname ) ;
+   system( "mv $CTISMname $_[0]" ) ;
+}
+
+1;

+ 74 - 0
dtool/src/build/ctpathadjust

@@ -0,0 +1,74 @@
+#!/usr/local/bin/perl
+
+# find the longest common directory prefix of the 2 input paths
+# input is:
+# $_[0] = path 1
+# $_[1] = path 2
+#
+# output is:
+# relative path
+sub CTCommonPrefix {
+   local( @path1 ) ;
+   local( @path2 ) ;
+   local( $count ) = 0 ;
+   local( $thresh ) ;
+   local( $tmp ) = $_[0] ;
+   $tmp =~ s/^\/// ;
+   @path1 = split ( /\//, $tmp ) ;
+   $tmp = $_[1] ;
+   $tmp =~ s/^\/// ;
+   @path2 = split ( /\//, $tmp ) ;
+   if ( $path1[0] eq "view" ) {
+      $thresh = 1 ;
+   } else {
+      $thresh = 0 ;
+   }
+   while (( $path1[0] eq $path2[0] ) &&
+	  ( $#path1 >= 0 ) &&
+	  ( $#path2 > 0 )) {
+      shift @path1;
+      shift @path2;
+      $count++ ;
+   }
+   local( $ret ) ;
+   if ( $count > $thresh ) {
+      while ( $#path1 >= 0 ) {
+	 $ret = $ret . "../" ;
+	 shift @path1 ;
+      }
+      while ( $#path2 >= 0 ) {
+	 $ret = $ret . $path2[0] . "/" ;
+	 shift @path2 ;
+      }
+      $ret =~ s/\/$// ;
+   } else {
+      $ret = $_[1] ;
+   }
+   $ret ;
+}
+
+# $pwd = $ENV{"PWD"} ;
+# sometimes the PWD environment variable lies, and getcwd by itself doesn't
+# report the view extention.
+use Cwd ;
+$pwd = getcwd() ;
+if ( $pwd =~ /^\/vobs/ ) {
+   open( VFILE, "/usr/atria/bin/cleartool pwv -short |" ) ;
+   $view = <VFILE> ;
+   close( VFILE ) ;
+   $view =~ s/\n$// ;
+   $pwd = "/view/" . $view . $pwd ;
+}
+$output = "" ;
+
+foreach $item ( @ARGV ) {
+   $common = &CTCommonPrefix( $pwd, $item ) ;
+   if ( length( $common ) > 0 ) {
+      if ( $output ne "" ) {
+	 $output = $output . " " ;
+      }
+      $output = $output . $common ;
+   }
+}
+
+print $output . "\n" ;

+ 35 - 0
dtool/src/build/ctproj

@@ -0,0 +1,35 @@
+#!/usr/local/bin/perl
+
+$tool = $ENV{"DTOOL"} ;
+if ( $tool eq "" ) {
+   die "Environment not configured to run CTtools" ;
+}
+
+require "$tool/inc/ctproj.pl" ;
+
+@arglist = @ARGV ;
+
+$prntroot = 0 ;
+if ( $arglist[0] =~ /^-r/ ) {
+   $prntroot = 1 ;
+   shift( @arglist ) ;
+} elsif ( $arglist[0] =~ /^-p/ ) {
+   $prntpkg = 1 ;
+   shift( @arglist ) ;
+}
+
+if ( @arglist == () ) {
+   $proj = &CTProj ;
+} else {
+   $proj = &CTProj( $arglist[0] ) ;
+}
+
+if ( $prntroot ) {
+   print &CTProjRoot( $proj ) ;
+} elsif ( $prntpkg ) {
+   print &CTProjPkg( $proj ) ;
+} else {
+   print $proj ;
+}
+
+print "\n" ;

+ 60 - 0
dtool/src/build/ctproj.pl

@@ -0,0 +1,60 @@
+# return the root of the given project.
+sub CTProjRoot {
+    local( $CTPRtmp ) = $_[0] ;
+    $CTPRtmp =~ tr/a-z/A-Z/ ;
+    local( $CTPRret ) = $ENV{ $CTPRtmp } ;
+    $CTPRret ;
+}
+
+# return the package we're currently in.
+# input:
+#   $_[0] = project
+sub CTProjPkg {
+    local( $CTPPret ) = `pwd`;
+    chop $CTPPret;
+    local( $CTPPtmp ) = $_[0] ;
+    $CTPPtmp  =~ tr/a-z/A-Z/ ;
+    $CTPPret =~ s/$ENV{ $CTPPtmp }// ;
+    $CTPPret =~ s/\/src\/// ;
+    $CTPPret =~ s/\/metalib\/// ;
+    $CTPPret ;
+}
+
+# reutrn the project containing the given directory.  If no directory is given,
+# return the project containing the current directory.
+sub CTProj {
+   local( $CTPdir ) ;
+   if ($_[0] eq "") {
+      $CTPdir = `pwd`;
+      chop $CTPdir;
+   } else {
+      # provided directory
+      $CTPdir = $_[0] ;
+   }
+   local( $CTPprojs ) = $ENV{"CTPROJS"} ;
+   local( $CTPdone ) = "" ;
+   local( @CTPlist ) ;
+   @CTPlist = split( / /, $CTPprojs ) ;
+   local( @CTPlist2 ) ;
+   local( $CTPtry ) ;
+   while (( $CTPdone eq "" ) && ( @CTPlist != () )){
+      # pop the first one off the list
+      $CTPtmp = $CTPlist[0] ;
+      shift( @CTPlist ) ;
+      # split the project from it's flavor
+      @CTPlist2 = split( /:/, $CTPtmp );
+      $CTPtry = &CTProjRoot( $CTPlist2[0] ) ;
+      # is CTPtry prefix of CTPdir?  if so we have our winner
+      if ( $CTPdir =~ /^$CTPtry/ ) {
+	 $CTPdone = "yep" ;
+      }
+   }
+   if ( $CTPdone eq "" ) {
+      $CTPtry = "" ;
+   } else {
+      $CTPtry = $CTPlist2[0] ;
+   }
+   $CTPtry ;
+}
+
+1;

+ 47 - 0
dtool/src/build/ctutils.pl

@@ -0,0 +1,47 @@
+# evaluate the given parameter to expand shell variables
+sub CTUShellEval {
+   local( *CTUSEFILE ) ;
+   open( CTUSEFILE, "echo $_[0] |" ) ;
+   local( $CTUSEret ) = <CTUSEFILE> ;
+   close( CTUSEFILE ) ;
+   $CTUSEret =~ s/\n$// ;
+   $CTUSEret ;
+}
+
+# if debug is on, print the argument
+sub CTUDebug {
+    if ( $ctdebug ) {
+	print STDERR $_[0] ;
+    }
+}
+
+use Cwd ;
+# get current directory
+sub CTUCurrDir {
+    local( $pwd ) = getcwd() ;
+    if ( $pwd =~ /^\/vobs/ ) {
+	local( *VFILE ) ;
+	open( VFILE, "cleartool pwv -short |" ) ;
+	local( $view ) = <VFILE> ;
+	close( VFILE ) ;
+	$view =~ s/\n$// ;
+	$pwd = "/view/" . $view . $pwd ;
+    }
+    $pwd ;
+}
+
+# turn a shell return code into a success/fail flag
+sub CTURetCode {
+    local( $ret ) ;
+    if ( $_[0] == 0 ) {
+	$ret = 1 ;
+    } else {
+	$ret = 0 ;
+    }
+    $ret ;
+}
+
+$ctdebug = $ENV{"CTATTACH_DEBUG"} ;
+$ctvspec_path = '/usr/local/etc' unless $ctvspec_path = $ENV{'CTVSPEC_PATH'};
+
+1;

+ 21 - 0
dtool/src/build/initialize

@@ -0,0 +1,21 @@
+#! /bin/sh
+
+if test "$1" = ""; then
+  echo "must give a make command as the argument."
+  echo "(eg: initialize /usr/atria/bin/clearmake -C gnu)"
+  exit 1
+fi
+
+test -d ../../inc || mkdir ../../inc
+test -d ../../bin || mkdir ../../bin
+
+cp Makefile.install.rules Makefile.meta.rules Makefile.install.vars Makefile.project.vars Makefile.penv.vars Makefile.o.vars ctproj.pl ../../inc
+cp ctproj ctpathadjust ../../bin
+cd ../..
+if test "$DTOOL" = ""; then
+   DTOOL=`pwd`
+   export DTOOL
+fi
+PATH=$DTOOL/bin:$PATH
+export PATH
+$* build attach

+ 46 - 0
dtool/src/cppparser/Sources.pp

@@ -0,0 +1,46 @@
+#define LOCAL_LIBS dtoolutil dtoolbase
+#define YACC_PREFIX cppyy
+
+#begin static_lib_target
+  #define TARGET cppParser
+  
+  #define SOURCES							  \
+    cppArrayType.cxx cppArrayType.h cppBison.h				  \
+    cppBison.yxx cppBisonDefs.h						  \
+    cppClassTemplateParameter.cxx cppClassTemplateParameter.h		  \
+    cppCommentBlock.cxx cppCommentBlock.h cppConstType.cxx		  \
+    cppConstType.h cppDeclaration.cxx cppDeclaration.h cppEnumType.cxx	  \
+    cppEnumType.h cppExpression.cxx cppExpression.h			  \
+    cppExpressionParser.cxx cppExpressionParser.h cppExtensionType.cxx	  \
+    cppExtensionType.h cppFile.cxx cppFile.h cppFunctionGroup.cxx	  \
+    cppFunctionGroup.h cppFunctionType.cxx cppFunctionType.h		  \
+    cppGlobals.cxx cppGlobals.h cppIdentifier.cxx cppIdentifier.h	  \
+    cppInstance.cxx cppInstance.h cppInstanceIdentifier.cxx		  \
+    cppInstanceIdentifier.h cppManifest.cxx cppManifest.h		  \
+    cppNameComponent.cxx cppNameComponent.h cppNamespace.cxx		  \
+    cppNamespace.h cppParameterList.cxx cppParameterList.h cppParser.cxx  \
+    cppParser.h cppPointerType.cxx cppPointerType.h cppPreprocessor.cxx	  \
+    cppPreprocessor.h cppReferenceType.cxx cppReferenceType.h		  \
+    cppScope.cxx cppScope.h cppSimpleType.cxx cppSimpleType.h		  \
+    cppStructType.cxx cppStructType.h cppTBDType.cxx cppTBDType.h	  \
+    cppTemplateParameterList.cxx cppTemplateParameterList.h		  \
+    cppTemplateScope.cxx cppTemplateScope.h cppToken.cxx cppToken.h	  \
+    cppType.cxx cppType.h cppTypeDeclaration.cxx cppTypeDeclaration.h	  \
+    cppTypeParser.cxx cppTypeParser.h cppTypeProxy.cxx cppTypeProxy.h	  \
+    cppTypedef.cxx cppTypedef.h cppUsing.cxx cppUsing.h cppVisibility.cxx \
+    cppVisibility.h indent.cxx indent.h
+
+// These are temporary; they need not be installed in the future.  These are
+// necessary only when using template stopgap.
+  #define INSTALL_HEADERS \
+    cppDeclaration.h cppExtensionType.h cppIdentifier.h cppInstance.h \
+    cppManifest.h cppPreprocessor.h cppScope.h cppToken.h cppType.h \
+    cppVisibility.h cppBisonDefs.h cppParser.h cppInstanceIdentifier.h \
+    cppFunctionType.h cppSimpleType.h cppParameterList.h cppTypedef.h \
+    cppTypeDeclaration.h \
+    cppPointerType.h cppReferenceType.h cppConstType.h cppArrayType.h \
+    cppEnumType.h cppStructType.h cppFile.h cppTemplateParameterList.h \
+    cppFunctionGroup.h cppNameComponent.h cppTypeProxy.h cppTBDType.h \
+    cppExpressionParser.h cppExpression.h cppGlobals.h cppCommentBlock.h
+
+#end static_lib_target

+ 227 - 0
dtool/src/cppparser/cppArrayType.cxx

@@ -0,0 +1,227 @@
+// Filename: cppArrayType.C
+// Created by:  drose (19Oct99)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+#include "cppArrayType.h"
+#include "cppExpression.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPPArrayType::
+CPPArrayType(CPPType *element_type, CPPExpression *bounds) :
+  CPPType(CPPFile()),
+  _element_type(element_type),
+  _bounds(bounds)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::is_fully_specified
+//       Access: Public, Virtual
+//  Description: Returns true if this declaration is an actual,
+//               factual declaration, or false if some part of the
+//               declaration depends on a template parameter which has
+//               not yet been instantiated.
+////////////////////////////////////////////////////////////////////
+bool CPPArrayType::
+is_fully_specified() const {
+  return CPPType::is_fully_specified() && 
+    _element_type->is_fully_specified();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::resolve_type
+//       Access: Public, Virtual
+//  Description: If this CPPType object is a forward reference or
+//               other nonspecified reference to a type that might now
+//               be known a real type, returns the real type.
+//               Otherwise returns the type itself.
+////////////////////////////////////////////////////////////////////
+CPPType *CPPArrayType::
+resolve_type(CPPScope *current_scope, CPPScope *global_scope) {
+  CPPType *ptype = _element_type->resolve_type(current_scope, global_scope);
+
+  if (ptype != _element_type) {
+    CPPArrayType *rep = new CPPArrayType(*this);
+    rep->_element_type = ptype;
+    return CPPType::new_type(rep);
+  }
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::is_tbd
+//       Access: Public, Virtual
+//  Description: Returns true if the type, or any nested type within
+//               the type, is a CPPTBDType and thus isn't fully
+//               determined right now.  In this case, calling
+//               resolve_type() may or may not resolve the type.
+////////////////////////////////////////////////////////////////////
+bool CPPArrayType::
+is_tbd() const {
+  return _element_type->is_tbd();
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::is_equivalent
+//       Access: Public, Virtual
+//  Description: This is a little more forgiving than is_equal(): it
+//               returns true if the types appear to be referring to
+//               the same thing, even if they may have different
+//               pointers or somewhat different definitions.  It's
+//               useful for parameter matching, etc.
+////////////////////////////////////////////////////////////////////
+bool CPPArrayType::
+is_equivalent(const CPPType &other) const {
+  const CPPArrayType *ot = ((CPPType *)&other)->as_array_type();
+  if (ot == (CPPArrayType *)NULL) {
+    return CPPType::is_equivalent(other);
+  }
+
+  return _element_type->is_equivalent(*ot->_element_type);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::substitute_decl
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPPDeclaration *CPPArrayType::
+substitute_decl(CPPDeclaration::SubstDecl &subst,
+		CPPScope *current_scope, CPPScope *global_scope) {
+  SubstDecl::const_iterator si = subst.find(this);
+  if (si != subst.end()) {
+    return (*si).second;
+  }
+
+  CPPArrayType *rep = new CPPArrayType(*this);
+  rep->_element_type = 
+    _element_type->substitute_decl(subst, current_scope, global_scope)
+    ->as_type();
+  
+  if (_bounds != NULL) {
+    rep->_bounds = 
+      _bounds->substitute_decl(subst, current_scope, global_scope)
+      ->as_expression();
+  }
+
+  if (rep->_element_type == _element_type &&
+      rep->_bounds == _bounds) {
+    delete rep;
+    rep = this;
+  }
+  rep = CPPType::new_type(rep)->as_array_type();
+  subst.insert(SubstDecl::value_type(this, rep));
+  return rep;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::output
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CPPArrayType::
+output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
+  _element_type->output(out, indent_level, scope, complete);
+  out << "[";
+  if (_bounds != NULL) {
+    out << *_bounds;
+  }
+  out << "]";
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::output_instance
+//       Access: Public, Virtual
+//  Description: Formats a C++-looking line that defines an instance
+//               of the given type, with the indicated name.  In most
+//               cases this will be "type name", but some types have
+//               special exceptions.
+////////////////////////////////////////////////////////////////////
+void CPPArrayType::
+output_instance(ostream &out, int indent_level, CPPScope *scope,
+		bool complete, const string &prename,
+		const string &name) const {
+  ostringstream brackets;
+  brackets << "[";
+  if (_bounds != NULL) {
+    brackets << *_bounds;
+  }
+  brackets << "]";
+  string bracketsstr = brackets.str();
+
+  _element_type->output_instance(out, indent_level, scope, complete, 
+				 prename, name + bracketsstr);
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::get_subtype
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPPDeclaration::SubType CPPArrayType::
+get_subtype() const {
+  return ST_array;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::as_array_type
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPPArrayType *CPPArrayType::
+as_array_type() {
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::is_equal
+//       Access: Protected, Virtual
+//  Description: Called by CPPDeclaration() to determine whether this type is
+//               equivalent to another type of the same type.
+////////////////////////////////////////////////////////////////////
+bool CPPArrayType::
+is_equal(const CPPDeclaration *other) const {
+  const CPPArrayType *ot = ((CPPDeclaration *)other)->as_array_type();
+  assert(ot != NULL);
+
+  if (_bounds != NULL && ot->_bounds != NULL) {
+    if (*_bounds != *ot->_bounds) {
+      return false;
+    }
+  } else if (_bounds == NULL || ot->_bounds == NULL) {
+    return false;
+  }
+
+  return _element_type == ot->_element_type;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPArrayType::is_less
+//       Access: Protected, Virtual
+//  Description: Called by CPPDeclaration() to determine whether this type
+//               should be ordered before another type of the same
+//               type, in an arbitrary but fixed ordering.
+////////////////////////////////////////////////////////////////////
+bool CPPArrayType::
+is_less(const CPPDeclaration *other) const {
+  const CPPArrayType *ot = ((CPPDeclaration *)other)->as_array_type();
+  assert(ot != NULL);
+
+  if (_bounds != NULL && ot->_bounds != NULL) {
+    if (*_bounds != *ot->_bounds) {
+      return *_bounds < *ot->_bounds;
+    }
+  } else if (_bounds == NULL || ot->_bounds == NULL) {
+    return _bounds < ot->_bounds;
+  }
+
+  return _element_type < ot->_element_type;
+}
+

+ 52 - 0
dtool/src/cppparser/cppArrayType.h

@@ -0,0 +1,52 @@
+// Filename: cppArrayType.h
+// Created by:  drose (19Oct99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef CPPARRAYTYPE_H
+#define CPPARRAYTYPE_H
+
+#include <dtoolbase.h>
+
+#include "cppType.h"
+
+class CPPExpression;
+
+///////////////////////////////////////////////////////////////////
+// 	 Class : CPPArrayType
+// Description :
+////////////////////////////////////////////////////////////////////
+class CPPArrayType : public CPPType {
+public:
+  CPPArrayType(CPPType *element_type, CPPExpression *bounds);
+
+  CPPType *_element_type;
+  CPPExpression *_bounds;
+
+  virtual bool is_fully_specified() const;
+  virtual CPPDeclaration *substitute_decl(SubstDecl &subst,
+					  CPPScope *current_scope,
+					  CPPScope *global_scope);
+
+  virtual CPPType *resolve_type(CPPScope *current_scope,
+				CPPScope *global_scope);
+  virtual bool is_tbd() const;
+  virtual bool is_equivalent(const CPPType &other) const;
+
+  virtual void output(ostream &out, int indent_level, CPPScope *scope,
+		      bool complete) const;
+  virtual void output_instance(ostream &out, int indent_level,
+			       CPPScope *scope,
+			       bool complete, const string &prename,
+			       const string &name) const;
+
+  virtual SubType get_subtype() const;
+
+  virtual CPPArrayType *as_array_type();
+
+protected:
+  virtual bool is_equal(const CPPDeclaration *other) const;
+  virtual bool is_less(const CPPDeclaration *other) const;
+};
+
+#endif

+ 2527 - 0
dtool/src/cppparser/cppBison.yxx

@@ -0,0 +1,2527 @@
+// Filename: cppBison.y
+// Created by:  drose (16Jan99)
+// 
+////////////////////////////////////////////////////////////////////
+
+%{
+
+#include "cppBisonDefs.h"
+#include "cppParser.h"
+#include "cppExpression.h"
+#include "cppSimpleType.h"
+#include "cppExtensionType.h"
+#include "cppStructType.h"
+#include "cppEnumType.h"
+#include "cppFunctionType.h"
+#include "cppTBDType.h"
+#include "cppParameterList.h"
+#include "cppInstance.h"
+#include "cppClassTemplateParameter.h"
+#include "cppTemplateParameterList.h"
+#include "cppInstanceIdentifier.h"
+#include "cppTypedef.h"
+#include "cppTypeDeclaration.h"
+#include "cppVisibility.h"
+#include "cppIdentifier.h"
+#include "cppScope.h"
+#include "cppTemplateScope.h"
+#include "cppNamespace.h"
+#include "cppUsing.h"
+
+////////////////////////////////////////////////////////////////////
+// Defining the interface to the parser.
+////////////////////////////////////////////////////////////////////
+
+CPPScope *current_scope = NULL;
+CPPScope *global_scope = NULL;
+CPPPreprocessor *current_lexer = NULL;
+
+static CPPStructType *current_struct = NULL; 
+static CPPEnumType *current_enum = NULL;
+static int current_storage_class = 0;
+static CPPType *current_type = NULL;
+static CPPExpression *current_expr = NULL;
+static int publish_nest_level = 0;
+static CPPVisibility publish_previous;
+static YYLTYPE publish_loc;
+
+static vector<CPPScope *> last_scopes;
+static vector<int> last_storage_classes;
+static vector<CPPStructType *> last_structs;
+
+int yyparse();
+
+#define YYERROR_VERBOSE
+
+static void
+yyerror(const string &msg) {
+  current_lexer->error(msg);
+}
+
+static void
+yyerror(const string &msg, YYLTYPE &loc) {
+  current_lexer->error(msg, loc.first_line, loc.first_column);
+}
+
+static void
+yywarning(const string &msg, YYLTYPE &loc) {
+  current_lexer->warning(msg, loc.first_line, loc.first_column);
+}
+
+static int
+yylex(YYSTYPE *lval, YYLTYPE *lloc) {
+  CPPToken token = current_lexer->get_next_token();
+  *lval = token._lval;
+  *lloc = token._lloc;
+  return token._token;
+}
+
+void
+parse_cpp(CPPParser *cp) {
+  CPPScope *old_scope = current_scope;
+  CPPScope *old_global_scope = global_scope;
+  CPPPreprocessor *old_lexer = current_lexer;
+
+  current_scope = cp;
+  global_scope = cp;
+  current_lexer = cp;
+  publish_nest_level = 0;
+  yyparse();
+
+  if (publish_nest_level != 0) {
+    yyerror("Unclosed __begin_publish", publish_loc);
+    publish_nest_level = 0;
+  }
+
+  current_scope = old_scope;
+  global_scope = old_global_scope;
+  current_lexer = old_lexer;
+    
+}
+
+CPPExpression *
+parse_const_expr(CPPPreprocessor *pp, CPPScope *new_current_scope,
+		 CPPScope *new_global_scope) {
+  CPPScope *old_scope = current_scope;
+  CPPScope *old_global_scope = global_scope;
+  CPPPreprocessor *old_lexer = current_lexer;
+  CPPExpression *old_expr = current_expr;
+
+  current_scope = new_current_scope;
+  global_scope = new_global_scope;
+  current_expr = (CPPExpression *)NULL;
+  current_lexer = pp;
+  yyparse();
+
+  CPPExpression *result = current_expr;
+
+  current_scope = old_scope;
+  global_scope = old_global_scope;
+  current_lexer = old_lexer;
+  current_expr = old_expr;
+
+  return result;
+}
+
+CPPType *
+parse_type(CPPPreprocessor *pp, CPPScope *new_current_scope,
+	   CPPScope *new_global_scope) {
+  CPPScope *old_scope = current_scope;
+  CPPScope *old_global_scope = global_scope;
+  CPPPreprocessor *old_lexer = current_lexer;
+  CPPType *old_type = current_type;
+
+  current_scope = new_current_scope;
+  global_scope = new_global_scope;
+  current_type = (CPPType *)NULL;
+  current_lexer = pp;
+  yyparse();
+
+  CPPType *result = current_type;
+  
+  current_scope = old_scope;
+  global_scope = old_global_scope;
+  current_lexer = old_lexer;
+  current_type = old_type;
+
+  return result;
+}
+
+static void
+push_scope(CPPScope *new_scope) {
+  last_scopes.push_back(current_scope);
+  if (new_scope != NULL) {
+    current_scope = new_scope;
+  }
+}
+
+static void
+pop_scope() {
+  assert(!last_scopes.empty());
+  current_scope = last_scopes.back();
+  last_scopes.pop_back();
+}
+
+static void
+push_storage_class(int new_storage_class) {
+  last_storage_classes.push_back(current_storage_class);
+  current_storage_class = new_storage_class;
+}
+
+static void
+pop_storage_class() {
+  assert(!last_storage_classes.empty());
+  current_storage_class = last_storage_classes.back();
+  last_storage_classes.pop_back();
+}
+
+static void
+push_struct(CPPStructType *new_struct) {
+  last_structs.push_back(current_struct);
+  current_struct = new_struct;
+}
+
+static void
+pop_struct() {
+  assert(!last_structs.empty());
+  current_struct = last_structs.back();
+  last_structs.pop_back();
+}
+
+%}
+
+/* This is a bison-specific declaration to enable recursive calls to
+   yyparse().  It changes the calling sequence to yylex(), passing
+   pointers to the current yylval and yylloc. */
+%pure_parser
+
+%token <u.real> REAL
+%token <u.integer> INTEGER
+%token <u.integer> CHAR
+%token <str> STRING SIMPLE_IDENTIFIER
+%token <u.identifier> IDENTIFIER TYPENAME_IDENTIFIER SCOPING
+%token <u.type> TYPEDEFNAME
+
+%token ELLIPSIS
+%token OROR
+%token ANDAND
+%token EQCOMPARE
+%token NECOMPARE
+%token LECOMPARE
+%token GECOMPARE
+%token LSHIFT
+%token RSHIFT
+%token POINTSAT_STAR
+%token DOT_STAR
+%token UNARY
+%token UNARY_NOT
+%token UNARY_NEGATE
+%token UNARY_MINUS
+%token UNARY_STAR
+%token UNARY_REF
+%token POINTSAT
+%token SCOPE
+%token PLUSPLUS 
+%token MINUSMINUS 
+%token TIMESEQUAL
+%token DIVIDEEQUAL
+%token MODEQUAL
+%token PLUSEQUAL
+%token MINUSEQUAL
+%token OREQUAL
+%token ANDEQUAL
+%token XOREQUAL
+%token LSHIFTEQUAL
+%token RSHIFTEQUAL
+%token TOKENPASTE
+
+%token KW_BEGIN_PUBLISH
+%token KW_BOOL
+%token KW_CATCH
+%token KW_CHAR
+%token KW_CLASS 
+%token KW_CONST 
+%token KW_DELETE
+%token KW_DOUBLE
+%token KW_DYNAMIC_CAST
+%token KW_ELSE
+%token KW_END_PUBLISH 
+%token KW_ENUM 
+%token KW_EXTERN
+%token KW_EXPLICIT
+%token KW_PUBLISHED
+%token KW_FALSE
+%token KW_FLOAT
+%token KW_FRIEND
+%token KW_FOR
+%token KW_GOTO
+%token KW_IF
+%token KW_INLINE
+%token KW_INT
+%token KW_LONG
+%token KW_LONGLONG
+%token KW_MUTABLE
+%token KW_NAMESPACE
+%token KW_NEW
+%token KW_OPERATOR
+%token KW_PRIVATE
+%token KW_PROTECTED
+%token KW_PUBLIC
+%token KW_REGISTER
+%token KW_RETURN
+%token KW_SHORT
+%token KW_SIGNED
+%token KW_SIZEOF
+%token KW_STATIC
+%token KW_STATIC_CAST
+%token KW_STRUCT 
+%token KW_TEMPLATE
+%token KW_THROW
+%token KW_TRUE
+%token KW_TRY
+%token KW_TYPEDEF 
+%token KW_TYPENAME
+%token KW_UNION 
+%token KW_UNSIGNED
+%token KW_USING
+%token KW_VIRTUAL
+%token KW_VOID
+%token KW_VOLATILE
+%token KW_WHILE
+
+/* These special tokens are used to set the starting state of the
+   parser.  The lexer places the appropriate one of these on the head
+   of the input stream. */
+%token START_CPP
+%token START_CONST_EXPR
+%token START_TYPE
+
+%type <u.integer> storage_class
+%type <u.instance> function_prototype
+%type <u.integer> function_post
+%type <str> function_operator
+%type <u.decl> template_formal_parameter
+%type <u.type> template_formal_parameter_type
+%type <u.inst_ident> instance_identifier
+%type <u.param_list> formal_parameter_list
+%type <u.param_list> formal_parameters
+%type <u.expr> template_parameter_maybe_initialize
+%type <u.expr> maybe_initialize
+%type <u.expr> maybe_initialize_or_function_body
+%type <u.instance> formal_parameter
+%type <u.inst_ident> not_paren_formal_parameter_identifier
+%type <u.inst_ident> formal_parameter_identifier
+%type <u.inst_ident> empty_instance_identifier
+%type <u.type> type
+%type <u.decl> type_decl
+%type <u.type> predefined_type
+%type <u.type> full_type
+%type <u.struct_type> anonymous_struct
+%type <u.struct_type> named_struct
+%type <u.enum_type> anonymous_enum
+%type <u.enum_type> named_enum
+%type <u.extension_enum> enum_keyword
+%type <u.extension_enum> struct_keyword
+%type <u.simple_type> simple_type
+%type <u.simple_type> simple_int_type
+%type <u.simple_type> simple_float_type
+%type <u.simple_type> simple_void_type
+%type <u.type> class_derivation_name
+/*%type <u.type> typedefname*/
+%type <u.identifier> name
+%type <str> string
+
+/* We need to treat KW_OPERATOR as a scopable keyword. */
+%type <u.identifier> KW_OPERATOR
+
+%type <u.expr> optional_const_expr
+%type <u.expr> optional_const_expr_comma
+%type <u.expr> const_expr_comma
+%type <u.expr> no_angle_bracket_const_expr
+%type <u.expr> const_expr
+%type <u.expr> const_operand
+
+
+/* Precedence rules. */
+
+%left IDENTIFIER TYPENAME_IDENTIFIER TYPEDEFNAME KW_ENUM ELLIPSIS KW_OPERATOR KW_TYPENAME KW_INT KW_SHORT KW_UNSIGNED KW_SIGNED KW_LONG KW_FLOAT KW_DOUBLE KW_CHAR KW_BOOL
+
+%left '{' ',' ';'
+
+%nonassoc KW_THROW
+%right ':'
+%right '='
+%right '?'
+%left OROR
+%left ANDAND
+%left '|'
+%left '^'
+%left '&'
+%left EQCOMPARE NECOMPARE
+%left LECOMPARE GECOMPARE '<' '>'
+%left LSHIFT RSHIFT
+%left '+' '-'
+%left '*' '/' '%'
+%left POINTSAT_STAR DOT_STAR
+%right UNARY PLUSPLUS MINUSMINUS '~'
+%left POINTSAT '.' '(' '['
+
+%right SCOPE
+%nonassoc KW_NEW KW_DELETE KW_TRY KW_CATCH
+
+%%
+
+grammar:
+	START_CPP cpp
+	| START_CONST_EXPR const_expr
+{
+  current_expr = $2;
+}
+	| START_TYPE full_type
+{
+  current_type = $2;
+}
+	;
+
+cpp:
+	empty
+	| cpp ';'
+	| cpp declaration
+	;
+
+constructor_inits:
+	constructor_init
+	| constructor_inits ',' constructor_init
+	;
+
+constructor_init:
+	name '(' optional_const_expr_comma ')'
+{
+  delete $3;
+}
+	;
+
+/* This is principally for the syntax: extern "C" { ... }.
+
+   We use storage_class instead of simply KW_EXTERN to avoid
+   shift/reduce conflicts with yacc's limited differentiation
+   ability. */
+extern_c:
+	storage_class '{'
+{
+  push_storage_class((current_storage_class & ~CPPInstance::SC_c_binding) | 
+		     ($1 & CPPInstance::SC_c_binding));
+}
+	cpp '}'
+{
+  pop_storage_class();
+}
+	;
+
+declaration:
+	type_like_declaration
+	| template_declaration
+	| extern_c
+	| namespace_declaration
+	| using_declaration
+	| friend_declaration
+	| KW_TYPEDEF typedef_declaration
+	| KW_BEGIN_PUBLISH 
+{
+  if (publish_nest_level != 0) {
+    yyerror("Unclosed __begin_publish", publish_loc);
+    publish_nest_level = 0;
+    current_scope->set_current_vis(V_public);
+  }
+
+  publish_previous = current_scope->get_current_vis();
+  publish_loc = @1;
+  publish_nest_level++;
+  current_scope->set_current_vis(V_published);
+}
+	| KW_END_PUBLISH 
+{
+  if (publish_nest_level != 1) {
+    yyerror("Unmatched __end_publish", @1);
+  } else {
+    current_scope->set_current_vis(publish_previous);
+  }
+  publish_nest_level = 0;
+}
+	| KW_PUBLISHED ':'
+{
+  current_scope->set_current_vis(V_published);
+}
+	| KW_PUBLIC ':'
+{
+  current_scope->set_current_vis(V_public);
+}
+	| KW_PROTECTED ':'
+{
+  current_scope->set_current_vis(V_protected);
+}
+	| KW_PRIVATE ':'
+{
+  current_scope->set_current_vis(V_private);
+}
+	;
+
+friend_declaration:
+	KW_FRIEND
+{
+  CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("temp"),
+				     V_public);
+  push_scope(new_scope);
+}
+	declaration
+{
+  delete current_scope;
+  pop_scope();
+}
+	;
+
+
+storage_class:
+	empty
+{
+  $$ = 0;
+}
+	| storage_class KW_EXTERN
+{
+  $$ = $1 | (int)CPPInstance::SC_extern;
+}
+	| storage_class KW_EXTERN string
+{
+  $$ = $1 | (int)CPPInstance::SC_extern;
+  if ($3 == "C") {
+    $$ |= (int)CPPInstance::SC_c_binding;
+  } else if ($3 == "C++") {
+    $$ &= ~(int)CPPInstance::SC_c_binding;
+  } else {
+    yywarning("Ignoring unknown linkage type \"" + $3 + "\"", @3);
+  }
+}
+	| storage_class KW_STATIC
+{
+  $$ = $1 | (int)CPPInstance::SC_static;
+}
+	| storage_class KW_INLINE
+{
+  $$ = $1 | (int)CPPInstance::SC_inline;
+}
+	| storage_class KW_VIRTUAL
+{
+  $$ = $1 | (int)CPPInstance::SC_virtual;
+}
+	| storage_class KW_EXPLICIT
+{
+  $$ = $1 | (int)CPPInstance::SC_explicit;
+}
+	| storage_class KW_VOLATILE
+{
+  $$ = $1 | (int)CPPInstance::SC_volatile;
+}
+	| storage_class KW_MUTABLE
+{
+  $$ = $1 | (int)CPPInstance::SC_mutable;
+}
+	| storage_class KW_REGISTER
+{
+  $$ = $1 | (int)CPPInstance::SC_register;
+}
+	;
+
+type_like_declaration:
+	multiple_var_declaration
+{
+  /* multiple_var_declaration adds itself to the scope. */
+}
+	| storage_class type_decl ';'
+{
+  // We don't really care about the storage class here.  In fact, it's
+  // not actually legal to define a class or struct using a particular
+  // storage class, but we require it just to help yacc out in its
+  // parsing.
+
+  current_scope->add_declaration($2, global_scope, current_lexer, @2);
+}
+	| storage_class function_prototype maybe_initialize_or_function_body
+{
+  if ($2 != (CPPInstance *)NULL) {
+    $2->_storage_class |= (current_storage_class | $1);
+    current_scope->add_declaration($2, global_scope, current_lexer, @2);
+    $2->set_initializer($3);
+  }
+}
+	;
+
+multiple_var_declaration:
+	storage_class type_decl
+{
+  // We don't need to push/pop type, because we can't nest
+  // multiple_var_declarations.
+  if ($2->as_type_declaration()) {
+    current_type = $2->as_type_declaration()->_type;
+  } else {
+    current_type = $2->as_type();
+  }
+  push_storage_class($1);
+}
+	multiple_instance_identifiers
+{
+  pop_storage_class();
+}
+	| storage_class KW_CONST type
+{
+  // We don't need to push/pop type, because we can't nest
+  // multiple_var_declarations.
+  current_type = $3;
+  push_storage_class($1);
+}
+	multiple_const_instance_identifiers
+{
+  pop_storage_class();
+}
+
+	/* We don't need to include a rule for variables that point to
+           functions, because we get those from the function_prototype
+           definition. */
+	;
+
+multiple_instance_identifiers:
+	instance_identifier maybe_initialize_or_function_body
+{
+  CPPInstance *inst = new CPPInstance(current_type, $1,
+				      current_storage_class,
+				      @1.file);
+  inst->set_initializer($2);
+  current_scope->add_declaration(inst, global_scope, current_lexer, @1);
+}
+	| instance_identifier maybe_initialize ',' multiple_instance_identifiers
+{
+  CPPInstance *inst = new CPPInstance(current_type, $1,
+				      current_storage_class,
+				      @1.file);
+  inst->set_initializer($2);
+  current_scope->add_declaration(inst, global_scope, current_lexer, @1);
+}
+	;
+
+multiple_const_instance_identifiers:
+	instance_identifier maybe_initialize_or_function_body
+{
+  $1->add_modifier(IIT_const);
+  CPPInstance *inst = new CPPInstance(current_type, $1,
+				      current_storage_class,
+				      @1.file);
+  inst->set_initializer($2);
+  current_scope->add_declaration(inst, global_scope, current_lexer, @1);
+}
+	| instance_identifier maybe_initialize ',' multiple_const_instance_identifiers
+{
+  $1->add_modifier(IIT_const);
+  CPPInstance *inst = new CPPInstance(current_type, $1,
+				      current_storage_class,
+				      @1.file);
+  inst->set_initializer($2);
+  current_scope->add_declaration(inst, global_scope, current_lexer, @1);
+}
+	;
+
+
+typedef_declaration:
+	storage_class type_decl
+{
+  // We don't need to push/pop type, because we can't nest
+  // multiple_var_declarations.
+  if ($2->as_type_declaration()) {
+    current_type = $2->as_type_declaration()->_type;
+  } else {
+    current_type = $2->as_type();
+  }
+  push_storage_class($1);
+}
+	typedef_instance_identifiers
+{
+  pop_storage_class();
+}
+	| storage_class KW_CONST type
+{
+  // We don't need to push/pop type, because we can't nest
+  // multiple_var_declarations.
+  current_type = $3;
+  push_storage_class($1);
+}
+	typedef_const_instance_identifiers
+{
+  pop_storage_class();
+}
+	| storage_class function_prototype maybe_initialize_or_function_body
+{
+  if ($2 != (CPPDeclaration *)NULL) {
+    CPPInstance *inst = $2->as_instance();
+    if (inst != (CPPInstance *)NULL) {
+      inst->_storage_class |= (current_storage_class | $1);
+      current_scope->add_declaration(inst, global_scope, current_lexer, @2);
+      current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @2);
+    }
+  }
+}
+	;
+
+typedef_instance_identifiers:
+	instance_identifier maybe_initialize_or_function_body
+{
+  CPPInstance *inst = new CPPInstance(current_type, $1,
+				      current_storage_class,
+				      @1.file);
+  inst->set_initializer($2);
+  current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @1);
+}
+	| instance_identifier maybe_initialize ',' typedef_instance_identifiers
+{
+  CPPInstance *inst = new CPPInstance(current_type, $1,
+				      current_storage_class,
+				      @1.file);
+  inst->set_initializer($2);
+  current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @1);
+}
+	;
+
+typedef_const_instance_identifiers:
+	instance_identifier maybe_initialize_or_function_body
+{
+  $1->add_modifier(IIT_const);
+  CPPInstance *inst = new CPPInstance(current_type, $1,
+				      current_storage_class,
+				      @1.file);
+  inst->set_initializer($2);
+  current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @1);
+}
+	| instance_identifier maybe_initialize ',' typedef_const_instance_identifiers
+{
+  $1->add_modifier(IIT_const);
+  CPPInstance *inst = new CPPInstance(current_type, $1,
+				      current_storage_class,
+				      @1.file);
+  inst->set_initializer($2);
+  current_scope->add_declaration(new CPPTypedef(inst, current_scope == global_scope), global_scope, current_lexer, @1);
+}
+	;
+
+function_prototype:
+
+/* Functions with implicit return types, and constructors */
+	IDENTIFIER '(' 
+{
+  push_scope($1->get_scope(current_scope, global_scope));
+}
+	formal_parameter_list ')' function_post
+{
+  pop_scope();
+  CPPType *type;
+  if ($1->get_simple_name() == current_scope->get_simple_name()) {
+    // This is a constructor, and has no return.
+    type = new CPPSimpleType(CPPSimpleType::T_void);
+  } else {
+    // This isn't a constructor, so it has an implicit return type of
+    // int.
+    type = new CPPSimpleType(CPPSimpleType::T_int);
+  }
+
+  CPPInstanceIdentifier *ii = new CPPInstanceIdentifier($1);
+  ii->add_func_modifier($4, $6);
+
+  $$ = new CPPInstance(type, ii, 0, @1.file);
+}
+	| TYPENAME_IDENTIFIER '('
+{
+  push_scope($1->get_scope(current_scope, global_scope));
+}
+	formal_parameter_list ')' function_post
+{
+  pop_scope();
+  CPPType *type;
+  if ($1->get_simple_name() == current_scope->get_simple_name()) {
+    // This is a constructor, and has no return.
+    type = new CPPSimpleType(CPPSimpleType::T_void);
+  } else {
+    // This isn't a constructor, so it has an implicit return type of
+    // int.
+    type = new CPPSimpleType(CPPSimpleType::T_int);
+  }
+
+  CPPInstanceIdentifier *ii = new CPPInstanceIdentifier($1);
+  ii->add_func_modifier($4, $6);
+
+  $$ = new CPPInstance(type, ii, 0, @1.file);
+}
+
+/* Destructors */
+	| '~' name '('
+{
+  push_scope($2->get_scope(current_scope, global_scope));
+}
+	formal_parameter_list ')' function_post
+{
+  pop_scope();
+  if ($2->is_scoped()) {
+    yyerror("Invalid destructor name: ~" + $2->get_fully_scoped_name(), @2);
+  } else {
+    CPPIdentifier *ident = 
+      new CPPIdentifier("~" + $2->get_simple_name(), @2.file);
+    delete $2;
+
+    CPPType *type;
+    type = new CPPSimpleType(CPPSimpleType::T_void);
+    
+    CPPInstanceIdentifier *ii = new CPPInstanceIdentifier(ident);
+    ii->add_func_modifier($5, $7);
+
+    $$ = new CPPInstance(type, ii, 0, @2.file);
+  }
+}
+
+/* This is a special case: a function pointer declaration that looks
+   at first a lot like a constructor declaration.  This is provided to
+   help yacc sort out the differences.  It isn't an ideal solution,
+   because it doesn't catch a lot of subtle variants on this form--but
+   this will get at least the 99% most common uses. */
+
+	| TYPENAME_IDENTIFIER '(' '*' instance_identifier ')' '('
+{
+  push_scope($4->get_scope(current_scope, global_scope));
+}
+	formal_parameter_list ')' function_post
+{
+  pop_scope();
+  CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  assert(type != NULL);
+
+  CPPInstanceIdentifier *ii = $4;
+  ii->add_modifier(IIT_pointer);
+  ii->add_func_modifier($8, $10);
+  $$ = new CPPInstance(type, ii, 0, @1.file);
+}
+	| TYPENAME_IDENTIFIER '(' SCOPING '*' instance_identifier ')' '('
+{
+  push_scope($5->get_scope(current_scope, global_scope));
+}
+	formal_parameter_list ')' function_post
+{
+  pop_scope();
+  CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  assert(type != NULL);
+
+  CPPInstanceIdentifier *ii = $5;
+  ii->add_scoped_pointer_modifier($3);
+  ii->add_func_modifier($9, $11);
+  $$ = new CPPInstance(type, ii, 0, @1.file);
+}
+
+/* Typecast operators */
+	| KW_OPERATOR type not_paren_formal_parameter_identifier '('
+{
+  if ($1 != NULL) {
+    push_scope($1->get_scope(current_scope, global_scope));
+  }
+}
+	formal_parameter_list ')' function_post
+{
+  if ($1 != NULL) {
+    pop_scope();
+  }
+
+  // We use formal_parameter_identifier, because that can match a type
+  // name with or without an identifier, but especially without, which
+  // is what follows the keyword "operator" in a typecast function.
+  // As an added bonus, the type of the formal_parameter will be the
+  // typecast type, i.e. the return type of the typecast function.
+
+  // We give all typecast operators the name "operator typecast".
+  // Only their return type will differentiate them.  (Naturally, this
+  // violates actual C++ rules, but we're not an actual C++ compiler
+  // so we don't care.  And this is the easiest way to do it.)
+  CPPIdentifier *ident = $1;
+  if (ident == NULL) {
+    ident = new CPPIdentifier("operator typecast", @1.file);
+  } else {
+    ident->add_name("operator typecast");
+  }
+  $$ = CPPInstance::make_typecast_function
+    (new CPPInstance($2, $3, 0, @3.file), ident, $6, $8);
+}
+	| KW_OPERATOR KW_CONST type not_paren_formal_parameter_identifier '('
+{
+  if ($1 != NULL) {
+    push_scope($1->get_scope(current_scope, global_scope));
+  }
+}
+	formal_parameter_list ')' function_post
+{
+  if ($1 != NULL) {
+    pop_scope();
+  }
+
+  CPPIdentifier *ident = $1;
+  if (ident == NULL) {
+    ident = new CPPIdentifier("operator typecast", @1.file);
+  } else {
+    ident->add_name("operator typecast");
+  }
+  $4->add_modifier(IIT_const);
+  $$ = CPPInstance::make_typecast_function
+    (new CPPInstance($3, $4, 0, @4.file), ident, $7, $9);
+}
+
+/* Not actually a function prototype, but maybe a template
+   instantiation.  Just included here (instead of somewhere else) to
+   avoid shift/reduce conflicts. */
+	| IDENTIFIER
+{
+  CPPDeclaration *decl = 
+    $1->find_symbol(current_scope, global_scope, current_lexer);
+  if (decl != (CPPDeclaration *)NULL) {
+    $$ = decl->as_instance();
+  } else {
+    $$ = (CPPInstance *)NULL;
+  }
+}
+	;
+
+function_post:
+	empty
+{
+  $$ = 0;
+}
+	| KW_CONST
+{
+  $$ = (int)CPPFunctionType::F_const_method;
+}
+	| function_post KW_THROW '(' ')'
+{
+  $$ = $1;
+}
+	| function_post KW_THROW '(' name ')'
+{
+  $$ = $1;
+}
+	;
+
+function_operator:
+	'!'
+{
+  $$ = "!";
+}
+	| '~'
+{
+  $$ = "~";
+}
+	| '*'
+{
+  $$ = "*";
+}
+	| '/'
+{
+  $$ = "/";
+}
+	| '%'
+{
+  $$ = "%";
+}
+	| '+'
+{
+  $$ = "+";
+}
+	| '-'
+{
+  $$ = "-";
+}
+	| '|'
+{
+  $$ = "|";
+}
+	| '&'
+{
+  $$ = "&";
+}
+	| '^'
+{
+  $$ = "^";
+}
+	| OROR
+{
+  $$ = "||";
+}
+	| ANDAND
+{
+  $$ = "&&";
+}
+	| EQCOMPARE
+{
+  $$ = "==";
+}
+	| NECOMPARE
+{
+  $$ = "!=";
+}
+	| LECOMPARE
+{
+  $$ = "<=";
+}
+	| GECOMPARE
+{
+  $$ = ">=";
+}
+	| '<'
+{
+  $$ = "<";
+}
+	| '>'
+{
+  $$ = ">";
+}
+	| LSHIFT
+{
+  $$ = "<<";
+}
+	| RSHIFT
+{
+  $$ = ">>";
+}
+	| '='
+{
+  $$ = "=";
+}
+	| ','
+{
+  $$ = ",";
+}
+	| PLUSPLUS
+{
+  $$ = "++";
+}
+	| MINUSMINUS
+{
+  $$ = "--";
+}
+	| TIMESEQUAL
+{
+  $$ = "*=";
+}
+	| DIVIDEEQUAL
+{
+  $$ = "/=";
+}
+	| MODEQUAL
+{
+  $$ = "%=";
+}
+	| PLUSEQUAL
+{
+  $$ = "+=";
+}
+	| MINUSEQUAL
+{
+  $$ = "-=";
+}
+	| OREQUAL
+{
+  $$ = "|=";
+}
+	| ANDEQUAL
+{
+  $$ = "&=";
+}
+	| XOREQUAL
+{
+  $$ = "^=";
+}
+	| LSHIFTEQUAL
+{
+  $$ = "<<=";
+}
+	| RSHIFTEQUAL
+{
+  $$ = ">>=";
+}
+	| POINTSAT
+{
+  $$ = "->";
+}
+	| '[' ']'
+{
+  $$ = "[]";
+}
+	| '(' ')'
+{
+  $$ = "()";
+}
+	| KW_NEW
+{
+  $$ = "new";
+}
+	| KW_DELETE
+{
+  $$ = "delete";
+}
+	;
+
+more_template_declaration:
+	type_like_declaration
+	| template_declaration
+	;
+
+template_declaration:
+	KW_TEMPLATE
+{
+  push_scope(new CPPTemplateScope(current_scope));
+}
+	'<' template_formal_parameters '>' more_template_declaration
+{
+  pop_scope();
+}
+	;
+
+template_formal_parameters:
+	empty
+	| template_nonempty_formal_parameters
+	;
+
+template_nonempty_formal_parameters:	
+	template_formal_parameter
+{
+  CPPTemplateScope *ts = current_scope->as_template_scope();
+  assert(ts != NULL);
+  ts->add_template_parameter($1);
+}
+	| template_nonempty_formal_parameters ',' template_formal_parameter
+{
+  CPPTemplateScope *ts = current_scope->as_template_scope();
+  assert(ts != NULL);
+  ts->add_template_parameter($3);
+}
+	;
+
+template_formal_parameter:
+	KW_CLASS name
+{
+  $$ = CPPType::new_type(new CPPClassTemplateParameter($2));
+}
+	| KW_CLASS name '=' full_type
+{
+  $$ = CPPType::new_type(new CPPClassTemplateParameter($2, $4));
+}
+	| template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize
+{
+  CPPInstance *inst = new CPPInstance($1, $2, 0, @2.file);
+  inst->set_initializer($3);
+  $$ = inst;
+}
+	| KW_CONST template_formal_parameter_type formal_parameter_identifier template_parameter_maybe_initialize
+{
+  $3->add_modifier(IIT_const);
+  CPPInstance *inst = new CPPInstance($2, $3, 0, @3.file);
+  inst->set_initializer($4);
+  $$ = inst;
+}
+	;
+
+template_formal_parameter_type:
+	simple_type
+{
+  $$ = CPPType::new_type($1);
+}
+	| IDENTIFIER
+{
+  yywarning("Not a type: " + $1->get_fully_scoped_name(), @1);
+  $$ = CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown));
+}
+	| TYPENAME_IDENTIFIER
+{
+  $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  assert($$ != NULL);
+}
+	| KW_TYPENAME name
+{
+  $$ = CPPType::new_type(new CPPTBDType($2));
+}
+	;
+
+
+instance_identifier:
+	name
+{
+  $$ = new CPPInstanceIdentifier($1);
+}
+	| KW_OPERATOR function_operator
+{
+  // For an operator function.  We implement this simply by building a
+  // ficticious name for the function; in other respects it's just
+  // like a regular function.
+  CPPIdentifier *ident = $1;
+  if (ident == NULL) {
+    ident = new CPPIdentifier("operator "+$2, @2.file);
+  } else {
+    ident->_names.push_back("operator "+$2);
+  }
+
+  $$ = new CPPInstanceIdentifier(ident);
+}
+	| KW_CONST instance_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_const);
+}
+	| '*' instance_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_pointer);
+}
+	| '&' instance_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_reference);
+}
+	| SCOPING '*' instance_identifier  %prec UNARY
+{
+  $$ = $3;
+  $$->add_scoped_pointer_modifier($1);
+}
+	| instance_identifier '[' optional_const_expr ']'
+{
+  $$ = $1;
+  $$->add_array_modifier($3);
+}
+	| '(' instance_identifier ')'
+{
+  $$ = $2;
+  $$->add_modifier(IIT_paren);
+}
+	| instance_identifier '('
+{
+  push_scope($1->get_scope(current_scope, global_scope));
+}
+	formal_parameter_list ')' function_post
+{
+  pop_scope();
+  $$ = $1;
+  $$->add_func_modifier($4, $6);
+}
+	;
+
+
+formal_parameter_list:
+	empty
+{
+  $$ = new CPPParameterList;
+}
+	| ELLIPSIS
+{
+  $$ = new CPPParameterList;
+  $$->_includes_ellipsis = true;
+}
+	| formal_parameters
+{
+  $$ = $1;
+}
+	| formal_parameters ',' ELLIPSIS
+{
+  $$ = $1;
+  $$->_includes_ellipsis = true;
+}
+	| formal_parameters ELLIPSIS
+{
+  $$ = $1;
+  $$->_includes_ellipsis = true;
+}
+	;
+
+formal_parameters:
+	formal_parameter
+{
+  $$ = new CPPParameterList;
+  $$->_parameters.push_back($1);
+}
+	| formal_parameters ',' formal_parameter
+{
+  $$ = $1;
+  $$->_parameters.push_back($3);
+}
+	;
+
+template_parameter_maybe_initialize:
+	empty
+{
+  $$ = (CPPExpression *)NULL;
+}
+	| '=' no_angle_bracket_const_expr
+{
+  $$ = $2;
+}
+	;
+
+maybe_initialize:
+	empty
+{
+  $$ = (CPPExpression *)NULL;
+}
+	| '=' const_expr
+{
+  $$ = $2;
+}
+	;
+
+maybe_initialize_or_function_body:
+	';'
+{
+  $$ = (CPPExpression *)NULL;
+}
+	| '{' code '}'
+{
+  $$ = (CPPExpression *)NULL;
+}
+	| ':' constructor_inits '{' code '}'
+{
+  $$ = (CPPExpression *)NULL;
+}
+	| '=' const_expr ';'
+{
+  $$ = $2;
+}
+	| '=' '{' structure_init '}'
+{
+  $$ = (CPPExpression *)NULL;
+}
+	;
+
+structure_init:
+	empty
+	| structure_init_body
+	| structure_init_body ','
+	;
+
+structure_init_body:
+	const_expr
+{
+}
+	| '{' structure_init '}'
+	| structure_init_body ',' const_expr
+	| structure_init_body ',' '{' structure_init '}'
+	;
+
+formal_parameter:
+	type formal_parameter_identifier maybe_initialize
+{
+  $$ = new CPPInstance($1, $2, 0, @2.file);
+  $$->set_initializer($3);
+}
+	| IDENTIFIER formal_parameter_identifier maybe_initialize
+{
+  yywarning("Not a type: " + $1->get_fully_scoped_name(), @1);
+  CPPType *type =
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_unknown));
+  $$ = new CPPInstance(type, $2, 0, @2.file);
+  $$->set_initializer($3);
+}
+	| KW_CONST type formal_parameter_identifier maybe_initialize
+{
+  $3->add_modifier(IIT_const);
+  $$ = new CPPInstance($2, $3, 0, @3.file);
+  $$->set_initializer($4);
+}
+	;
+
+not_paren_formal_parameter_identifier:
+	empty
+{
+  $$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
+}
+	| IDENTIFIER
+{
+  $$ = new CPPInstanceIdentifier($1);
+}
+	| TYPENAME_IDENTIFIER
+{
+  $$ = new CPPInstanceIdentifier($1);
+}
+	| KW_CONST not_paren_formal_parameter_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_const);
+}
+	| '*' not_paren_formal_parameter_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_pointer);
+}
+	| '&' not_paren_formal_parameter_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_reference);
+}
+	| SCOPING '*' not_paren_formal_parameter_identifier  %prec UNARY
+{
+  $$ = $3;
+  $$->add_scoped_pointer_modifier($1);
+}
+	| not_paren_formal_parameter_identifier '[' optional_const_expr ']'
+{
+  $$ = $1;
+  $$->add_array_modifier($3);
+}
+	;
+
+formal_parameter_identifier:
+	empty
+{
+  $$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
+}
+	| IDENTIFIER
+{
+  $$ = new CPPInstanceIdentifier($1);
+}
+	| TYPENAME_IDENTIFIER
+{
+  $$ = new CPPInstanceIdentifier($1);
+}
+	| KW_CONST formal_parameter_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_const);
+}
+	| '*' formal_parameter_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_pointer);
+}
+	| '&' formal_parameter_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_reference);
+}
+	| SCOPING '*' formal_parameter_identifier  %prec UNARY
+{
+  $$ = $3;
+  $$->add_scoped_pointer_modifier($1);
+}
+	| formal_parameter_identifier '[' optional_const_expr ']'
+{
+  $$ = $1;
+  $$->add_array_modifier($3);
+}
+	| '(' formal_parameter_identifier ')' '(' formal_parameter_list ')' function_post
+{
+  $$ = $2;
+  $$->add_modifier(IIT_paren);
+  $$->add_func_modifier($5, $7);
+}
+	;
+
+empty_instance_identifier:
+	empty
+{
+  $$ = new CPPInstanceIdentifier((CPPIdentifier *)NULL);
+}
+	| KW_CONST empty_instance_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_const);
+}
+	| '*' empty_instance_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_pointer);
+}
+	| '&' empty_instance_identifier  %prec UNARY
+{
+  $$ = $2;
+  $$->add_modifier(IIT_reference);
+}
+	| SCOPING '*' empty_instance_identifier  %prec UNARY
+{
+  $$ = $3;
+  $$->add_scoped_pointer_modifier($1);
+}
+	| empty_instance_identifier '[' optional_const_expr ']'
+{
+  $$ = $1;
+  $$->add_array_modifier($3);
+}
+	| '(' empty_instance_identifier ')' '(' formal_parameter_list ')' function_post
+{
+  $$ = $2;
+  $$->add_modifier(IIT_paren);
+  $$->add_func_modifier($5, $7);
+}
+	;
+
+type:
+	simple_type
+{
+  $$ = CPPType::new_type($1);
+}
+	| TYPENAME_IDENTIFIER
+{
+  $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  assert($$ != NULL);
+}
+	| KW_TYPENAME name
+{
+  $$ = CPPType::new_type(new CPPTBDType($2));
+}
+	| anonymous_struct
+{
+  $$ = CPPType::new_type($1);
+}
+	| named_struct
+{
+  $$ = CPPType::new_type($1);
+}
+	| anonymous_enum
+{
+  $$ = CPPType::new_type($1);
+}
+	| named_enum
+{
+  $$ = CPPType::new_type($1);
+}
+	| struct_keyword name
+{
+  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  if (type != NULL) {
+    $$ = type;
+  } else {
+    CPPExtensionType *et = 
+      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      ->as_extension_type();
+    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    if (scope != NULL) {
+      scope->define_extension_type(et);
+    }
+    $$ = et;
+  }
+}
+	| enum_keyword name
+{
+  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  if (type != NULL) {
+    $$ = type;
+  } else {
+    CPPExtensionType *et = 
+      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      ->as_extension_type();
+    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    if (scope != NULL) {
+      scope->define_extension_type(et);
+    }
+    $$ = et;
+  }
+}
+	;
+
+type_decl:
+	simple_type
+{
+  $$ = CPPType::new_type($1);
+}
+	| TYPENAME_IDENTIFIER
+{
+  $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  assert($$ != NULL);
+}
+	| KW_TYPENAME name
+{
+  $$ = CPPType::new_type(new CPPTBDType($2));
+}
+	| anonymous_struct
+{
+  $$ = CPPType::new_type($1);
+}
+	| named_struct
+{
+  $$ = new CPPTypeDeclaration(CPPType::new_type($1));
+}
+	| anonymous_enum
+{
+  $$ = CPPType::new_type($1);
+}
+	| named_enum
+{
+  $$ = new CPPTypeDeclaration(CPPType::new_type($1));
+}
+	| struct_keyword name
+{
+  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  if (type != NULL) {
+    $$ = type;
+  } else {
+    CPPExtensionType *et = 
+      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      ->as_extension_type();
+    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    if (scope != NULL) {
+      scope->define_extension_type(et);
+    }
+    $$ = et;
+  }
+}
+	| enum_keyword name
+{
+  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  if (type != NULL) {
+    $$ = type;
+  } else {
+    CPPExtensionType *et = 
+      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      ->as_extension_type();
+    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    if (scope != NULL) {
+      scope->define_extension_type(et);
+    }
+    $$ = et;
+  }
+}
+	;
+
+predefined_type:
+	simple_type
+{
+  $$ = CPPType::new_type($1);
+}
+	| TYPENAME_IDENTIFIER
+{
+  $$ = $1->find_type(current_scope, global_scope, false, current_lexer);
+  assert($$ != NULL);
+}
+	| KW_TYPENAME name
+{
+  $$ = CPPType::new_type(new CPPTBDType($2));
+}
+	| struct_keyword name
+{
+  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  if (type != NULL) {
+    $$ = type;
+  } else {
+    CPPExtensionType *et = 
+      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      ->as_extension_type();
+    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    if (scope != NULL) {
+      scope->define_extension_type(et);
+    }
+    $$ = et;
+  }
+}
+	| enum_keyword name
+{
+  CPPType *type = $2->find_type(current_scope, global_scope, false, current_lexer);
+  if (type != NULL) {
+    $$ = type;
+  } else {
+    CPPExtensionType *et = 
+      CPPType::new_type(new CPPExtensionType($1, $2, current_scope, @1.file))
+      ->as_extension_type();
+    CPPScope *scope = $2->get_scope(current_scope, global_scope);
+    if (scope != NULL) {
+      scope->define_extension_type(et);
+    }
+    $$ = et;
+  }
+}
+	;
+
+full_type:
+	type empty_instance_identifier
+{
+  CPPInstance *inst = new CPPInstance($1, $2, 0, @1.file);
+  $$ = inst->_type;
+  delete inst;
+}
+	| KW_CONST type empty_instance_identifier
+{
+  $3->add_modifier(IIT_const);
+  CPPInstance *inst = new CPPInstance($2, $3, 0, @1.file);
+  $$ = inst->_type;
+  delete inst;
+}
+	;
+
+anonymous_struct:
+	struct_keyword '{'
+{
+  CPPVisibility starting_vis = 
+  ($1 == CPPExtensionType::T_class) ? V_private : V_public;
+  
+  CPPScope *new_scope = new CPPScope(current_scope, CPPNameComponent("anon"),
+				     starting_vis);
+  CPPStructType *st = new CPPStructType($1, NULL, current_scope,
+					new_scope, @1.file);
+  new_scope->set_struct_type(st);
+
+  push_scope(new_scope);
+  push_struct(st);
+}
+	cpp '}'
+{
+  $$ = current_struct;
+  current_struct->_incomplete = false;
+  pop_struct();
+  pop_scope();
+}
+	;
+
+named_struct:
+	struct_keyword name
+{
+  CPPVisibility starting_vis = 
+  ($1 == CPPExtensionType::T_class) ? V_private : V_public;
+
+  CPPScope *scope = $2->get_scope(current_scope, global_scope, current_lexer);
+  if (scope == NULL) {
+    scope = current_scope;
+  }
+  CPPScope *new_scope = new CPPScope(scope, $2->_names.back(),
+				     starting_vis);
+
+  CPPStructType *st = new CPPStructType($1, $2, current_scope,
+					new_scope, @1.file);
+  new_scope->set_struct_type(st);
+  current_scope->define_extension_type(st);
+  
+  push_scope(new_scope);
+  push_struct(st);
+}
+	maybe_class_derivation '{' cpp '}'
+{
+  $$ = current_struct;
+  current_struct->_incomplete = false;
+  pop_struct();
+  pop_scope();
+}
+	;
+
+maybe_class_derivation:
+	empty
+	| class_derivation
+	;
+
+class_derivation:
+	':' base_specification
+	| class_derivation ',' base_specification
+	;
+
+base_specification:
+	KW_PUBLIC class_derivation_name
+{
+  current_struct->append_derivation($2, V_public, false);
+}
+	| KW_PROTECTED class_derivation_name
+{
+  current_struct->append_derivation($2, V_protected, false);
+}
+	| KW_PRIVATE class_derivation_name
+{
+  current_struct->append_derivation($2, V_private, false);
+}
+	| KW_VIRTUAL KW_PUBLIC class_derivation_name
+{
+  current_struct->append_derivation($3, V_public, true);
+}
+	| KW_VIRTUAL KW_PROTECTED class_derivation_name
+{
+  current_struct->append_derivation($3, V_protected, true);
+}
+	| KW_VIRTUAL KW_PRIVATE class_derivation_name
+{
+  current_struct->append_derivation($3, V_private, true);
+}
+	| KW_PUBLIC KW_VIRTUAL class_derivation_name
+{
+  current_struct->append_derivation($3, V_public, true);
+}
+	| KW_PROTECTED KW_VIRTUAL class_derivation_name
+{
+  current_struct->append_derivation($3, V_protected, true);
+}
+	| KW_PRIVATE KW_VIRTUAL class_derivation_name
+{
+  current_struct->append_derivation($3, V_private, true);
+}
+	;
+
+anonymous_enum:
+	enum_keyword '{'
+{
+  current_enum = new CPPEnumType(NULL, current_scope, @1.file);
+}
+	enum_body '}'
+{
+  $$ = current_enum;
+  current_enum = NULL;
+}
+	;
+
+named_enum:
+	enum_keyword name '{'
+{
+  current_enum = new CPPEnumType($2, current_scope, @1.file);
+}
+	enum_body '}'
+{
+  $$ = current_enum;
+  current_enum = NULL;
+}
+	;
+
+enum_body:
+	empty
+	| enum_body_no_trailing_comma
+	| enum_body_no_trailing_comma ','
+	;
+
+enum_body_no_trailing_comma:
+	name
+{
+  assert(current_enum != NULL);
+  current_enum->add_element($1->get_simple_name(), current_scope);
+}
+	| name '=' const_expr
+{
+  assert(current_enum != NULL);
+  current_enum->add_element($1->get_simple_name(), current_scope, $3);
+}
+	| enum_body_no_trailing_comma ',' name
+{
+  assert(current_enum != NULL);
+  current_enum->add_element($3->get_simple_name(), current_scope);
+}
+	| enum_body_no_trailing_comma ',' name '=' const_expr
+{
+  assert(current_enum != NULL);
+  current_enum->add_element($3->get_simple_name(), current_scope, $5);
+}
+	;
+
+enum_keyword:
+	KW_ENUM
+{
+  $$ = CPPExtensionType::T_enum;
+}
+	;
+
+struct_keyword:
+	KW_CLASS
+{
+  $$ = CPPExtensionType::T_class;
+}
+	| KW_STRUCT
+{
+  $$ = CPPExtensionType::T_struct;
+}
+	| KW_UNION
+{
+  $$ = CPPExtensionType::T_union;
+}
+	;
+
+namespace_declaration:
+	KW_NAMESPACE name '{'
+{
+  CPPScope *scope = $2->find_scope(current_scope, global_scope, current_lexer);
+  if (scope == NULL) {
+    // This must be a new namespace declaration.
+    CPPScope *parent_scope = 
+      $2->get_scope(current_scope, global_scope, current_lexer);
+    if (parent_scope == NULL) {
+      parent_scope = current_scope;
+    }
+    scope = new CPPScope(parent_scope, $2->_names.back(), V_public);
+  }
+
+  CPPNamespace *nspace = new CPPNamespace($2, scope, @1.file);
+  current_scope->add_declaration(nspace, global_scope, current_lexer, @1);
+  current_scope->define_namespace(nspace);
+  push_scope(scope);
+}
+	cpp '}'
+{
+  pop_scope();
+}
+	| KW_NAMESPACE '{' cpp '}'
+	;
+
+using_declaration:
+	KW_USING name
+{
+  CPPUsing *using_decl = new CPPUsing($2, false, @1.file);
+  current_scope->add_declaration(using_decl, global_scope, current_lexer, @1);
+  current_scope->add_using(using_decl, global_scope, current_lexer);
+}
+	| KW_USING KW_NAMESPACE name
+{
+  CPPUsing *using_decl = new CPPUsing($3, true, @1.file);
+  current_scope->add_declaration(using_decl, global_scope, current_lexer, @1);
+  current_scope->add_using(using_decl, global_scope, current_lexer);
+}
+	;
+
+simple_type:
+	simple_int_type
+	| simple_float_type
+	| simple_void_type
+	;
+
+simple_int_type:
+        KW_BOOL
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_bool);
+}
+	| KW_CHAR
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_char);
+}
+	| KW_SHORT
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_int,
+			 CPPSimpleType::F_short);
+}
+	| KW_LONG
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_int,
+			 CPPSimpleType::F_long);
+}
+	| KW_LONGLONG
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_int,
+			 CPPSimpleType::F_longlong);
+}
+	| KW_UNSIGNED
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_int,
+			 CPPSimpleType::F_unsigned);
+}
+	| KW_SIGNED
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_int,
+			 CPPSimpleType::F_signed);
+}
+	| KW_INT
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_int);
+}
+	| KW_SHORT simple_int_type
+{
+  $$ = $2;
+  $$->_flags |= CPPSimpleType::F_short;
+}
+	| KW_LONG simple_int_type
+{
+  $$ = $2;
+  if ($$->_flags & CPPSimpleType::F_long) {
+    $$->_flags |= CPPSimpleType::F_longlong;
+  } else {
+    $$->_flags |= CPPSimpleType::F_long;
+  }
+}
+	| KW_UNSIGNED simple_int_type
+{
+  $$ = $2;
+  $$->_flags |= CPPSimpleType::F_unsigned;
+}
+	| KW_SIGNED simple_int_type
+{
+  $$ = $2;
+  $$->_flags |= CPPSimpleType::F_signed;
+}
+	;
+
+simple_float_type:
+	KW_FLOAT
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_float);
+}
+	| KW_LONG KW_FLOAT
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_float,
+			 CPPSimpleType::F_long);
+}
+	| KW_DOUBLE
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_double);
+}
+	| KW_LONG KW_LONG KW_FLOAT
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_float,
+			 CPPSimpleType::F_longlong);
+}
+	| KW_LONG KW_DOUBLE
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_double,
+			 CPPSimpleType::F_long);
+}
+	;
+
+simple_void_type:
+	KW_VOID
+{
+  $$ = new CPPSimpleType(CPPSimpleType::T_void);
+}
+	;
+
+/* We don't care what the code is.  We just want to be sure we match
+   up opening and closing braces properly.  For anything else, we'll
+   accept just token salad. */
+code:
+{
+  current_lexer->_resolve_identifiers = false;
+}
+	code_block
+{
+  current_lexer->_resolve_identifiers = true;
+}
+	;
+
+code_block:
+	empty
+	| code_block element
+	;
+
+element:
+	REAL
+{
+}
+	| INTEGER
+{
+}
+	| STRING
+{
+}
+	| CHAR
+{
+}
+	| IDENTIFIER
+{
+}
+	| TYPENAME_IDENTIFIER
+{
+}
+	| SCOPING
+{
+}
+	| SIMPLE_IDENTIFIER
+{
+}
+	| ELLIPSIS | OROR | ANDAND
+	| EQCOMPARE | NECOMPARE | LECOMPARE | GECOMPARE
+	| LSHIFT | RSHIFT | POINTSAT_STAR | DOT_STAR | POINTSAT
+	| SCOPE | PLUSPLUS | MINUSMINUS 
+	| TIMESEQUAL | DIVIDEEQUAL | MODEQUAL | PLUSEQUAL | MINUSEQUAL
+	| OREQUAL | ANDEQUAL | XOREQUAL | LSHIFTEQUAL | RSHIFTEQUAL
+	| KW_BOOL | KW_CATCH | KW_CHAR | KW_CLASS | KW_CONST
+	| KW_DELETE | KW_DOUBLE | KW_DYNAMIC_CAST | KW_ELSE | KW_ENUM
+	| KW_EXTERN | KW_EXPLICIT | KW_FALSE
+	| KW_FLOAT | KW_FRIEND | KW_FOR | KW_GOTO 
+	| KW_IF | KW_INLINE | KW_INT
+	| KW_LONG | KW_MUTABLE | KW_NEW | KW_PRIVATE | KW_PROTECTED
+	| KW_PUBLIC | KW_PUBLISHED | KW_REGISTER | KW_RETURN
+	| KW_SHORT | KW_SIGNED | KW_SIZEOF | KW_STATIC | KW_STATIC_CAST
+	| KW_STRUCT | KW_THROW | KW_TRUE | KW_TRY | KW_TYPEDEF | KW_TYPENAME
+	| KW_UNION | KW_UNSIGNED | KW_VIRTUAL | KW_VOID | KW_VOLATILE
+	| KW_WHILE
+	| KW_OPERATOR
+{
+}
+	| '+' | '-' | '*' | '/' | '&' | '|' | '^' | '!' | '~' | '=' | '%'
+	| '<' | '>' | '(' | ')' | '.' | ',' | ';' | ':' | '[' | ']'
+	| '?' | '{' code_block '}'
+	;
+
+optional_const_expr:
+	empty
+{
+  $$ = (CPPExpression *)NULL;
+}
+	| const_expr
+{
+  $$ = $1;
+}
+	;
+
+optional_const_expr_comma:
+	empty
+{
+  $$ = (CPPExpression *)NULL;
+}
+	| const_expr_comma
+{
+  $$ = $1;
+}
+	;
+
+const_expr_comma:
+	const_expr
+{
+  $$ = $1;
+}
+	| const_expr_comma ',' const_expr
+{
+  $$ = new CPPExpression(',', $1, $3)
+}
+	;
+
+no_angle_bracket_const_expr:
+	const_operand
+{
+  $$ = $1;
+}
+	| '(' full_type ')' no_angle_bracket_const_expr %prec UNARY
+{
+  $$ = new CPPExpression(CPPExpression::typecast_op($2, $4));
+}
+	| KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')'
+{
+  $$ = new CPPExpression(CPPExpression::typecast_op($3, $6));
+}
+	| KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')'
+{
+  $$ = new CPPExpression(CPPExpression::typecast_op($3, $6));
+}
+	| KW_SIZEOF '(' full_type ')' %prec UNARY
+{
+  $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+	| '!' no_angle_bracket_const_expr    %prec UNARY
+{
+  $$ = new CPPExpression(UNARY_NOT, $2);
+}
+	| '~' no_angle_bracket_const_expr    %prec UNARY
+{
+  $$ = new CPPExpression(UNARY_NEGATE, $2);
+}
+	| '-' no_angle_bracket_const_expr    %prec UNARY
+{
+  if ($2->_type == CPPExpression::T_integer) {
+    $$ = $2;
+    $$->_u._integer = -$$->_u._integer;
+  } else if ($2->_type == CPPExpression::T_real) {
+    $$ = $2;
+    $$->_u._real = -$$->_u._real;
+  } else {
+    $$ = new CPPExpression(UNARY_MINUS, $2);
+  }
+}
+	| '*' no_angle_bracket_const_expr    %prec UNARY
+{
+  $$ = new CPPExpression(UNARY_STAR, $2);
+}
+	| '&' no_angle_bracket_const_expr    %prec UNARY
+{
+  $$ = new CPPExpression(UNARY_REF, $2);
+}
+	| no_angle_bracket_const_expr '*' no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression('*', $1, $3)
+}
+	| no_angle_bracket_const_expr '/' no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression('/', $1, $3)
+}
+	| no_angle_bracket_const_expr '%' no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression('%', $1, $3)
+}
+	| no_angle_bracket_const_expr '+' no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression('+', $1, $3)
+}
+	| no_angle_bracket_const_expr '-' no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression('-', $1, $3)
+}
+	| no_angle_bracket_const_expr '|' no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression('|', $1, $3)
+}
+	| no_angle_bracket_const_expr '&' no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression('&', $1, $3)
+}
+	| no_angle_bracket_const_expr OROR no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression(OROR, $1, $3)
+}
+	| no_angle_bracket_const_expr ANDAND no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression(ANDAND, $1, $3)
+}
+	| no_angle_bracket_const_expr EQCOMPARE no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression(EQCOMPARE, $1, $3)
+}
+	| no_angle_bracket_const_expr NECOMPARE no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression(NECOMPARE, $1, $3)
+}
+	| no_angle_bracket_const_expr LECOMPARE no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression(LECOMPARE, $1, $3)
+}
+	| no_angle_bracket_const_expr GECOMPARE no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression(GECOMPARE, $1, $3)
+}
+	| no_angle_bracket_const_expr LSHIFT no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression(LSHIFT, $1, $3)
+}
+	| no_angle_bracket_const_expr RSHIFT no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression(RSHIFT, $1, $3)
+}
+	| no_angle_bracket_const_expr '?' no_angle_bracket_const_expr ':' no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression('?', $1, $3, $5)
+}
+	| no_angle_bracket_const_expr '[' const_expr ']'
+{
+  $$ = new CPPExpression('[', $1, $3);
+}
+	| no_angle_bracket_const_expr '(' const_expr_comma ')'
+{
+  $$ = new CPPExpression('f', $1, $3);
+}
+	| no_angle_bracket_const_expr '(' ')'
+{
+  $$ = new CPPExpression('f', $1);
+}
+	| no_angle_bracket_const_expr '.' no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression('.', $1, $3)
+}
+	| no_angle_bracket_const_expr POINTSAT no_angle_bracket_const_expr
+{
+  $$ = new CPPExpression(POINTSAT, $1, $3)
+}
+	| '(' const_expr_comma ')'
+{
+  $$ = $2;
+}
+	;
+	
+
+const_expr:
+	const_operand
+{
+  $$ = $1;
+}
+	| '(' full_type ')' const_expr %prec UNARY
+{
+  $$ = new CPPExpression(CPPExpression::typecast_op($2, $4));
+}
+	| KW_STATIC_CAST '<' full_type '>' '(' const_expr_comma ')'
+{
+  $$ = new CPPExpression(CPPExpression::typecast_op($3, $6));
+}
+	| KW_DYNAMIC_CAST '<' full_type '>' '(' const_expr_comma ')'
+{
+  $$ = new CPPExpression(CPPExpression::typecast_op($3, $6));
+}
+	| TYPENAME_IDENTIFIER '(' optional_const_expr_comma ')'
+{
+  // A constructor call.
+  CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  assert(type != NULL);
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_INT '(' optional_const_expr_comma ')'
+{
+  CPPType *type = 
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_CHAR '(' optional_const_expr_comma ')'
+{
+  CPPType *type = 
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_char));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_BOOL '(' optional_const_expr_comma ')'
+{
+  CPPType *type = 
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_bool));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_SHORT '(' optional_const_expr_comma ')'
+{
+  CPPType *type = 
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
+					CPPSimpleType::F_short));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_LONG '(' optional_const_expr_comma ')'
+{
+  CPPType *type = 
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
+					CPPSimpleType::F_long));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_UNSIGNED '(' optional_const_expr_comma ')'
+{
+  CPPType *type = 
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
+					CPPSimpleType::F_unsigned));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_SIGNED '(' optional_const_expr_comma ')'
+{
+  CPPType *type = 
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_int,
+					CPPSimpleType::F_signed));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_FLOAT '(' optional_const_expr_comma ')'
+{
+  CPPType *type = 
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_float));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_DOUBLE '(' optional_const_expr_comma ')'
+{
+  CPPType *type = 
+    CPPType::new_type(new CPPSimpleType(CPPSimpleType::T_double));
+  $$ = new CPPExpression(CPPExpression::construct_op(type, $3));
+}
+	| KW_SIZEOF '(' full_type ')' %prec UNARY
+{
+  $$ = new CPPExpression(CPPExpression::sizeof_func($3));
+}
+	| KW_NEW predefined_type %prec UNARY
+{
+  $$ = new CPPExpression(CPPExpression::new_op($2));
+}
+	| KW_NEW predefined_type '(' optional_const_expr_comma ')' %prec UNARY
+{
+  $$ = new CPPExpression(CPPExpression::new_op($2, $4));
+}
+	| '!' const_expr    %prec UNARY
+{
+  $$ = new CPPExpression(UNARY_NOT, $2);
+}
+	| '~' const_expr    %prec UNARY
+{
+  $$ = new CPPExpression(UNARY_NEGATE, $2);
+}
+	| '-' const_expr    %prec UNARY
+{
+  if ($2->_type == CPPExpression::T_integer) {
+    $$ = $2;
+    $$->_u._integer = -$$->_u._integer;
+  } else if ($2->_type == CPPExpression::T_real) {
+    $$ = $2;
+    $$->_u._real = -$$->_u._real;
+  } else {
+    $$ = new CPPExpression(UNARY_MINUS, $2);
+  }
+}
+	| '*' const_expr    %prec UNARY
+{
+  $$ = new CPPExpression(UNARY_STAR, $2);
+}
+	| '&' const_expr    %prec UNARY
+{
+  $$ = new CPPExpression(UNARY_REF, $2);
+}
+	| const_expr '*' const_expr
+{
+  $$ = new CPPExpression('*', $1, $3)
+}
+	| const_expr '/' const_expr
+{
+  $$ = new CPPExpression('/', $1, $3)
+}
+	| const_expr '%' const_expr
+{
+  $$ = new CPPExpression('%', $1, $3)
+}
+	| const_expr '+' const_expr
+{
+  $$ = new CPPExpression('+', $1, $3)
+}
+	| const_expr '-' const_expr
+{
+  $$ = new CPPExpression('-', $1, $3)
+}
+	| const_expr '|' const_expr
+{
+  $$ = new CPPExpression('|', $1, $3)
+}
+	| const_expr '&' const_expr
+{
+  $$ = new CPPExpression('&', $1, $3)
+}
+	| const_expr OROR const_expr
+{
+  $$ = new CPPExpression(OROR, $1, $3)
+}
+	| const_expr ANDAND const_expr
+{
+  $$ = new CPPExpression(ANDAND, $1, $3)
+}
+	| const_expr EQCOMPARE const_expr
+{
+  $$ = new CPPExpression(EQCOMPARE, $1, $3)
+}
+	| const_expr NECOMPARE const_expr
+{
+  $$ = new CPPExpression(NECOMPARE, $1, $3)
+}
+	| const_expr LECOMPARE const_expr
+{
+  $$ = new CPPExpression(LECOMPARE, $1, $3)
+}
+	| const_expr GECOMPARE const_expr
+{
+  $$ = new CPPExpression(GECOMPARE, $1, $3)
+}
+	| const_expr '<' const_expr
+{
+  $$ = new CPPExpression('<', $1, $3)
+}
+	| const_expr '>' const_expr
+{
+  $$ = new CPPExpression('>', $1, $3)
+}
+	| const_expr LSHIFT const_expr
+{
+  $$ = new CPPExpression(LSHIFT, $1, $3)
+}
+	| const_expr RSHIFT const_expr
+{
+  $$ = new CPPExpression(RSHIFT, $1, $3)
+}
+	| const_expr '?' const_expr ':' const_expr
+{
+  $$ = new CPPExpression('?', $1, $3, $5)
+}
+	| const_expr '[' const_expr ']'
+{
+  $$ = new CPPExpression('[', $1, $3);
+}
+	| const_expr '(' const_expr_comma ')'
+{
+  $$ = new CPPExpression('f', $1, $3);
+}
+	| const_expr '(' ')'
+{
+  $$ = new CPPExpression('f', $1);
+}
+	| const_expr '.' const_expr
+{
+  $$ = new CPPExpression('.', $1, $3)
+}
+	| const_expr POINTSAT const_expr
+{
+  $$ = new CPPExpression(POINTSAT, $1, $3)
+}
+	| '(' const_expr_comma ')'
+{
+  $$ = $2;
+}
+	;
+
+const_operand:
+	INTEGER
+{
+  $$ = new CPPExpression($1);
+}
+	| KW_TRUE
+{
+  $$ = new CPPExpression(true);
+}
+	| KW_FALSE
+{
+  $$ = new CPPExpression(false);
+}
+	| CHAR
+{
+  $$ = new CPPExpression($1);
+}
+	| REAL
+{
+  $$ = new CPPExpression($1);
+}
+	| string
+{
+  $$ = new CPPExpression($1);
+}
+	| IDENTIFIER
+{
+  $$ = new CPPExpression($1, current_scope, global_scope, current_lexer);
+}
+	;
+
+class_derivation_name:
+	name
+{
+  CPPType *type = $1->find_type(current_scope, global_scope, true);
+  if (type == NULL) {
+    type = CPPType::new_type(new CPPTBDType($1));
+  }
+  $$ = type;
+}
+	| struct_keyword name
+{
+  CPPType *type = $2->find_type(current_scope, global_scope, true, current_lexer);
+  if (type == NULL) {
+    type = CPPType::new_type(new CPPTBDType($2));
+  }
+  $$ = type;
+}
+	| KW_TYPENAME name
+{
+  $$ = CPPType::new_type(new CPPTBDType($2));
+}
+	;
+
+/*	
+typedefname:
+	TYPENAME_IDENTIFIER
+{
+  CPPType *type = $1->find_type(current_scope, global_scope, false, current_lexer);
+  assert(type != NULL);
+  $$ = type;
+}
+	| KW_TYPENAME name
+{
+  $$ = CPPType::new_type(new CPPTBDType($2));
+}
+	;
+*/
+
+
+name:
+	IDENTIFIER
+{
+  $$ = $1;
+}
+	| TYPENAME_IDENTIFIER
+{
+  $$ = $1;
+}
+	;
+
+string:
+	STRING
+{
+  $$ = $1;
+}
+	| string STRING
+{
+  $$ = $1 + $2;
+}
+	;
+
+empty:
+	;

+ 96 - 0
dtool/src/cppparser/cppBisonDefs.h

@@ -0,0 +1,96 @@
+// Filename: cppBison.h
+// Created by:  drose (17Jan99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef CPPBISON_H
+#define CPPBISON_H
+
+// This header file defines the interface to the yacc (actually,
+// bison) parser and grammar.  None of these interfaces are intended
+// to be used directly; they're defined here strictly to be used by
+// the CPPParser and CPPExpressionParser classes.
+
+#include <dtoolbase.h>
+
+#include <string>
+
+#include "cppExtensionType.h"
+#include "cppFile.h"
+
+using namespace std;
+
+class CPPParser;
+class CPPExpression;
+class CPPPreprocessor;
+class CPPDeclaration;
+class CPPInstance;
+class CPPType;
+class CPPStructType;
+class CPPEnumType;
+class CPPSimpleType;
+class CPPInstanceIdentifier;
+class CPPParameterList;
+class CPPTemplateParameterList;
+class CPPScope;
+class CPPIdentifier;
+
+void parse_cpp(CPPParser *cp);
+CPPExpression *parse_const_expr(CPPPreprocessor *pp,
+				CPPScope *new_current_scope,
+				CPPScope *new_global_scope);
+CPPType *parse_type(CPPPreprocessor *pp,
+		    CPPScope *new_current_scope,
+		    CPPScope *new_global_scope);
+
+extern CPPScope *current_scope;
+extern CPPScope *global_scope;
+extern CPPPreprocessor *current_lexer;
+
+
+// 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 YYSTYPE {
+public:
+  string str;
+  union {
+    int integer;
+    double real;
+    CPPScope *scope;
+    CPPDeclaration *decl;
+    CPPInstance *instance;
+    CPPType *type;
+    CPPStructType *struct_type;
+    CPPEnumType *enum_type;
+    CPPSimpleType *simple_type;
+    CPPInstanceIdentifier *inst_ident;
+    CPPParameterList *param_list;
+    CPPTemplateParameterList *template_param_list;
+    CPPExtensionType::Type extension_enum;
+    CPPExpression *expr;
+    CPPIdentifier *identifier;
+  } u;
+};
+
+// This structure takes advantage of a bison feature to track the
+// exact location in the file of each token, for more useful error
+// reporting.  We define it up here so we can reference it in the
+// lexer.
+
+struct cppyyltype {
+  int timestamp;
+  int first_line;
+  int first_column;
+  int last_line;
+  int last_column;
+  char *text;
+  CPPFile file;
+};
+#define YYLTYPE cppyyltype
+
+#endif

+ 112 - 0
dtool/src/cppparser/cppClassTemplateParameter.cxx

@@ -0,0 +1,112 @@
+// Filename: cppClassTemplateParameter.C
+// Created by:  drose (28Oct99)
+// 
+////////////////////////////////////////////////////////////////////
+
+
+#include "cppClassTemplateParameter.h"
+#include "cppIdentifier.h"
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPClassTemplateParameter::Constructor
+//       Access: Public
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPPClassTemplateParameter::
+CPPClassTemplateParameter(CPPIdentifier *ident, CPPType *default_type) :
+  CPPType(CPPFile()),
+  _ident(ident),
+  _default_type(default_type)
+{
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPClassTemplateParameter::is_fully_specified
+//       Access: Public, Virtual
+//  Description: Returns true if this declaration is an actual,
+//               factual declaration, or false if some part of the
+//               declaration depends on a template parameter which has
+//               not yet been instantiated.
+////////////////////////////////////////////////////////////////////
+bool CPPClassTemplateParameter::
+is_fully_specified() const {
+  return false;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPClassTemplateParameter::output
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+void CPPClassTemplateParameter::
+output(ostream &out, int indent_level, CPPScope *scope, bool complete) const {
+  if (complete) {
+    out << "class ";
+    _ident->output(out, scope);
+    if (_default_type) {
+      out << " = ";
+      _default_type->output(out, indent_level, scope, false);
+    }
+  } else {
+    _ident->output(out, scope);
+  }
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPClassTemplateParameter::get_subtype
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPPDeclaration::SubType CPPClassTemplateParameter::
+get_subtype() const {
+  return ST_class_template_parameter;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPClassTemplateParameter::as_classTemplateParameter
+//       Access: Public, Virtual
+//  Description: 
+////////////////////////////////////////////////////////////////////
+CPPClassTemplateParameter *CPPClassTemplateParameter::
+as_class_template_parameter() {
+  return this;
+}
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPClassTemplateParameter::is_equal
+//       Access: Protected, Virtual
+//  Description: Called by CPPDeclaration() to determine whether this type is
+//               equivalent to another type of the same type.
+////////////////////////////////////////////////////////////////////
+bool CPPClassTemplateParameter::
+is_equal(const CPPDeclaration *other) const {
+  const CPPClassTemplateParameter *ot = ((CPPDeclaration *)other)->as_class_template_parameter();
+  assert(ot != NULL);
+
+  if (_default_type != ot->_default_type) {
+    return false;
+  }
+
+  return *_ident == *ot->_ident;
+}
+
+
+////////////////////////////////////////////////////////////////////
+//     Function: CPPClassTemplateParameter::is_less
+//       Access: Protected, Virtual
+//  Description: Called by CPPDeclaration() to determine whether this type
+//               should be ordered before another type of the same
+//               type, in an arbitrary but fixed ordering.
+////////////////////////////////////////////////////////////////////
+bool CPPClassTemplateParameter::
+is_less(const CPPDeclaration *other) const {
+  const CPPClassTemplateParameter *ot = ((CPPDeclaration *)other)->as_class_template_parameter();
+  assert(ot != NULL);
+
+  if (_default_type != ot->_default_type) {
+    return _default_type < ot->_default_type;
+  }
+
+  return *_ident < *ot->_ident;
+}

+ 40 - 0
dtool/src/cppparser/cppClassTemplateParameter.h

@@ -0,0 +1,40 @@
+// Filename: cppClassTemplateParameter.h
+// Created by:  drose (28Oct99)
+//
+////////////////////////////////////////////////////////////////////
+
+#ifndef CPPCLASSTEMPLATEPARAMETER_H
+#define CPPCLASSTEMPLATEPARAMETER_H
+
+#include <dtoolbase.h>
+
+#include "cppType.h"
+
+class CPPIdentifier;
+
+///////////////////////////////////////////////////////////////////
+// 	 Class : CPPClassTemplateParameter
+// Description :
+////////////////////////////////////////////////////////////////////
+class CPPClassTemplateParameter : public CPPType {
+public:
+  CPPClassTemplateParameter(CPPIdentifier *ident,
+			    CPPType *default_type = NULL);
+
+  virtual bool is_fully_specified() const;
+  virtual void output(ostream &out, int indent_level, CPPScope *scope,
+		      bool complete) const;
+  virtual SubType get_subtype() const;
+
+  virtual CPPClassTemplateParameter *as_class_template_parameter();
+
+  CPPIdentifier *_ident;
+  CPPType *_default_type;
+
+protected:
+  virtual bool is_equal(const CPPDeclaration *other) const;
+  virtual bool is_less(const CPPDeclaration *other) const;
+};
+
+#endif
+

+ 7 - 0
dtool/src/cppparser/cppCommentBlock.cxx

@@ -0,0 +1,7 @@
+// Filename: cppCommentBlock.C
+// Created by:  drose (15Aug00)
+// 
+////////////////////////////////////////////////////////////////////
+
+#include "cppCommentBlock.h"
+

Some files were not shown because too many files changed in this diff