Initial revision

This commit is contained in:
David Rose
2000-10-11 23:38:03 +00:00
parent 9bad163654
commit 3ca8c86cf0
31 changed files with 8619 additions and 0 deletions

26
ppremake/Depends.pp Normal file
View File

@@ -0,0 +1,26 @@
//
// Depends.pp
//
// This file is loaded and run after each Sources.pp is read. It
// defines the inter-directory dependencies, which is useful for
// determining build order.
//
#if $[eq $[DIR_TYPE], src]
#if $[eq $[DEPENDS],]
#map local_libs TARGET(*/lib_target */noinst_lib_target)
// Allow the user to define additional DEPENDS targets in each
// Sources.pp.
#define DEPENDS
#set DEPENDS $[EXTRA_DEPENDS]
#forscopes lib_target bin_target noinst_bin_target
#set DEPENDS $[DEPENDS] $[local_libs $[DIRNAME],$[LOCAL_LIBS]] $[LOCAL_INCS]
#end lib_target bin_target noinst_bin_target
#set DEPENDS $[sort $[DEPENDS]]
#endif
#endif // DIR_TYPE

334
ppremake/Global.stopgap.pp Normal file
View File

@@ -0,0 +1,334 @@
//
// Global.stopgap.pp
//
// This file is read in before any of the individual Sources.pp files
// are read. It defines a few global variables to assist
// Template.stopgap.pp.
//
// Define some various compile flags, derived from the variables set
// in Config.pp.
#if $[HAVE_PYTHON]
// We want to let the PYTHON_INCLUDE directory include wildcard characters.
#define python_ipath $[patsubst %,-I%,$[isdir $[PYTHON_IPATH]]]
#define python_lpath $[patsubst %,-L%,$[isdir $[PYTHON_LPATH]]]
#endif
#if $[HAVE_NSPR]
// We want to let the NSPR directories include wildcard characters.
#define nspr_ipath $[patsubst %,-I%,$[isdir $[NSPR_IPATH]]]
#define nspr_lpath $[patsubst %,-L%,$[isdir $[NSPR_LPATH]]]
#define nspr_libs $[NSPR_LIBS]
#endif
#if $[HAVE_ZLIB]
#define zlib_ipath $[ZLIB_IPATH:%=-I%]
#define zlib_lpath $[ZLIB_LPATH:%=-L%]
#define zlib_libs $[ZLIB_LIBS]
#endif
#if $[HAVE_SOXST]
#define soxst_ipath $[SOXST_IPATH:%=-I%]
#define soxst_lpath $[SOXST_LPATH:%=-L%]
#define soxst_libs $[SOXST_LIBS]
#endif
#if $[HAVE_GL]
#define gl_ipath $[GL_IPATH:%=-I%]
#define gl_lpath $[GL_LPATH:%=-L%]
#define gl_libs $[GL_LIBS]
#endif
#if $[HAVE_DX]
#define dx_ipath $[DX_IPATH:%=-I%]
#define dx_lpath $[DX_LPATH:%=-L%]
#define dx_libs $[DX_LIBS]
#endif
#if $[HAVE_MIKMOD]
#define mikmod_ipath $[MIKMOD_IPATH:%=-I%]
#define mikmod_cflags $[MIKMOD_CFLAGS]
#define mikmod_lpath $[MIKMOD_LPATH:%=-L%]
#define mikmod_libs $[MIKMOD_LIBS]
#endif
#if $[HAVE_GTKMM]
#define gtkmm_ipath $[GTKMM_IPATH:%=-I%]
#define gtkmm_cflags $[GTKMM_CFLAGS]
#define gtkmm_lpath $[GTKMM_LPATH:%=-L%]
#define gtkmm_libs $[GTKMM_LIBS]
#endif
#if $[and $[HAVE_MAYA],$[MAYA_LOCATION]]
#define maya_ipath -I$[MAYA_LOCATION]/include
#define maya_lpath -L$[MAYA_LOCATION]/lib
#define maya_ld $[MAYA_LOCATION]/bin/mayald
#endif
#if $[HAVE_NET]
#define net_ipath $[NET_IPATH:%=-I%]
#define net_lpath $[NET_LPATH:%=-L%]
#define net_libs $[NET_LIBS]
#endif
#if $[HAVE_AUDIO]
#define audio_ipath $[AUDIO_IPATH:%=-I%]
#define audio_lpath $[AUDIO_LPATH:%=-L%]
#define audio_libs $[AUDIO_LIBS]
#endif
// This variable, when evaluated in the scope of a particular directory,
// will indicate true (i.e. nonempty) when the directory is truly built,
// or false (empty) when the directory is not to be built.
#defer build_directory \
$[and \
$[or $[not $[DIRECTORY_IF_GL]],$[HAVE_GL]], \
$[or $[not $[DIRECTORY_IF_DX]],$[HAVE_DX]], \
$[or $[not $[DIRECTORY_IF_GLX]],$[HAVE_GLX]], \
$[or $[not $[DIRECTORY_IF_GLUT]],$[HAVE_GLUT]], \
$[or $[not $[DIRECTORY_IF_WGL]],$[HAVE_WGL]], \
$[or $[not $[DIRECTORY_IF_RIB]],$[HAVE_RIB]], \
$[or $[not $[DIRECTORY_IF_PS2]],$[HAVE_PS2]], \
$[or $[not $[DIRECTORY_IF_SGIGL]],$[HAVE_SGIGL]], \
$[or $[not $[DIRECTORY_IF_VRPN]],$[HAVE_VRPN]], \
$[or $[not $[DIRECTORY_IF_NET]],$[HAVE_NET]], \
$[or $[not $[DIRECTORY_IF_AUDIO]],$[HAVE_AUDIO]], \
$[or $[not $[DIRECTORY_IF_GTKMM]],$[HAVE_GTKMM]], \
$[or $[not $[DIRECTORY_IF_MAYA]],$[HAVE_MAYA]], \
1 ]
// This variable is true if we are building on some flavor of Unix.
#define unix_platform $[ne $[PLATFORM],Win32]
// This variable is true if we are building on some flavor of Windows.
#define windows_platform $[eq $[PLATFORM],Win32]
// This subroutine will set up the sources variable to reflect the
// complete set of sources for this target, and also set the
// alt_cflags, alt_libs, etc. as appropriate according to how the
// various USE_* flags are set for the current target.
#defsub get_sources
#define sources $[SOURCES]
#if $[ne $[HAVE_ZLIB],]
#set sources $[sources] $[IF_ZLIB_SOURCES]
#endif
#if $[ne $[HAVE_PYTHON],]
#set sources $[sources] $[IF_PYTHON_SOURCES]
#endif
#define alt_cflags $[nspr_cflags] $[mikmod_cflags] $[python_cflags]
#define alt_ipath $[nspr_ipath] $[mikmod_ipath] $[python_ipath]
#define alt_lpath $[nspr_lpath] $[mikmod_lpath] $[python_lpath]
#define alt_libs $[nspr_libs] $[mikmod_libs]
#define alt_ld
// If any of a metalib's constituent libraries require interrogate,
// then so does the metalib itself. To look this up, we need this map
// variable.
#map components TARGET(*/lib_target */noinst_lib_target)
#if $[ne $[USE_ZLIB] $[components $[USE_ZLIB],$[COMPONENT_LIBS]],]
#set alt_cflags $[alt_cflags] $[zlib_cflags]
#set alt_ipath $[alt_ipath] $[zlib_ipath]
#set alt_lpath $[alt_lpath] $[zlib_lpath]
#set alt_libs $[alt_libs] $[zlib_libs]
#endif
#if $[ne $[USE_GL] $[components $[USE_GL],$[COMPONENT_LIBS]],]
#set alt_cflags $[alt_cflags] $[gl_cflags]
#set alt_ipath $[alt_ipath] $[gl_ipath]
#set alt_lpath $[alt_lpath] $[gl_lpath]
#set alt_libs $[alt_libs] $[gl_libs]
#endif
#if $[ne $[USE_DX] $[components $[USE_DX],$[COMPONENT_LIBS]],]
#set alt_cflags $[alt_cflags] $[dx_cflags]
#set alt_ipath $[alt_ipath] $[dx_ipath]
#set alt_lpath $[alt_lpath] $[dx_lpath]
#set alt_libs $[alt_libs] $[dx_libs]
#endif
#if $[ne $[USE_SOXST] $[components $[USE_SOXST],$[COMPONENT_LIBS]],]
#set alt_cflags $[alt_cflags] $[soxst_cflags]
#set alt_ipath $[alt_ipath] $[soxst_ipath]
#set alt_lpath $[alt_lpath] $[soxst_lpath]
#set alt_libs $[alt_libs] $[soxst_libs]
#endif
#if $[ne $[USE_NET] $[components $[USE_NET],$[COMPONENT_LIBS]],]
#set alt_cflags $[alt_cflags] $[net_cflags]
#set alt_ipath $[alt_ipath] $[net_ipath]
#set alt_lpath $[alt_lpath] $[net_lpath]
#set alt_libs $[alt_libs] $[net_libs]
#endif
#if $[ne $[USE_AUDIO] $[components $[USE_AUDIO],$[COMPONENT_LIBS]],]
#set alt_cflags $[alt_cflags] $[audio_cflags]
#set alt_ipath $[alt_ipath] $[audio_ipath]
#set alt_lpath $[alt_lpath] $[audio_lpath]
#set alt_libs $[alt_libs] $[audio_libs]
#endif
#if $[ne $[USE_GTKMM] $[components $[USE_GTKMM],$[COMPONENT_LIBS]],]
#set alt_cflags $[alt_cflags] $[gtkmm_cflags]
#set alt_ipath $[alt_ipath] $[gtkmm_ipath]
#set alt_lpath $[alt_lpath] $[gtkmm_lpath]
#set alt_libs $[alt_libs] $[gtkmm_libs]
#endif
#if $[ne $[USE_MAYA] $[components $[USE_MAYA],$[COMPONENT_LIBS]],]
#set alt_cflags $[alt_cflags] $[maya_cflags]
#set alt_ipath $[alt_ipath] $[maya_ipath]
#set alt_lpath $[alt_lpath] $[maya_lpath]
#set alt_libs $[alt_libs] $[maya_libs]
#set alt_ld $[maya_ld]
#endif
#if $[unix_platform]
#set alt_libs $[alt_libs] $[UNIX_SYS_LIBS] $[components $[UNIX_SYS_LIBS],$[COMPONENT_LIBS]]
#endif
#end get_sources
// This subroutine will set when_defer, when_no_defer, and when_either
// correctly to the set of libs we should link with for current
// target.
#defsub get_libs
// For the WHEN_DEFER case, we need to know the complete set of
// metalibs that encapsulates each of our LOCAL_LIBS. In the case
// where a particular library is not part of a metalib, we include the
// library itself.
// These map variables are handy to determine that.
#map module COMPONENT_LIBS(*/metalib_target)
#map all_libs TARGET(*/static_lib_target */lib_target */noinst_lib_target */metalib_target)
#define when_defer
#foreach lib $[LOCAL_LIBS]
// Only consider libraries that we're actually building.
#if $[all_libs $[build_directory],$[lib]]
#define modmeta $[module $[TARGET],$[lib]]
#if $[ne $[modmeta],]
#set when_defer $[when_defer] $[modmeta]
#else
#set when_defer $[when_defer] $[lib]
#endif
#endif
#end lib
#set when_defer $[unique $[when_defer]] $[patsubst %:m,%,$[filter %:m,$[OTHER_LIBS]]]
// Also filter out the libraries we don't want from when_no_defer, although
// we don't need to translate these to metalibs.
#define when_no_defer
#foreach lib $[COMPONENT_LIBS] $[LOCAL_LIBS]
#if $[all_libs $[build_directory],$[lib]]
#set when_no_defer $[when_no_defer] $[lib]
#endif
#end lib
#set when_no_defer $[unique $[when_no_defer]] $[patsubst %:c,%,$[filter %:c,$[OTHER_LIBS]]]
// Finally, get the set of libraries that we want in either case. At
// the moment, this is just the set of libraries in OTHER_LIBS that's
// not flagged with either a :c or a :m.
#define when_either $[filter-out %:m %:c,$[OTHER_LIBS]]
#end get_libs
// This subroutine converts depend_libs from a list of plain library names
// to a list of the form libname.so or libname.a, according to whether the
// named libraries are static or dynamic.
#defsub convert_depend_libs
#map static_libs TARGET(*/static_lib_target)
#map dynamic_libs TARGET(*/lib_target */metalib_target)
#map all_libs TARGET(*/static_lib_target */lib_target */metalib_target)
#define new_depend_libs
#foreach lib $[depend_libs]
// Make sure the library is something we're actually building.
#if $[all_libs $[build_directory],$[lib]]
#define libname $[static_libs lib$[TARGET].a,$[lib]] $[dynamic_libs lib$[TARGET].so,$[lib]]
#if $[eq $[libname],]
Warning: No such library $[lib], dependency of $[DIRNAME].
#else
#set new_depend_libs $[new_depend_libs] $[libname]
#endif
#endif
#end lib
#set depend_libs $[sort $[new_depend_libs]]
#end convert_depend_libs
// This subroutine determines the set of libraries our various targets
// depend on. This is a complicated definition. It is the union of
// all of our targets' dependencies, except:
// If a target is part of a metalib, it depends (a) directly on all of
// its normal library dependencies that are part of the same metalib,
// and (b) indirectly on all of the metalibs that every other library
// dependency is part of. If a target is not part of a metalib, it is
// the same as case (b) above.
#defsub get_depend_libs
#map module COMPONENT_LIBS(*/metalib_target)
#define depend_libs
#forscopes lib_target noinst_lib_target
#define metalib $[module $[TARGET],$[TARGET]]
#if $[ne $[metalib],]
// This library is included on a metalib.
#foreach depend $[LOCAL_LIBS]
#define depend_metalib $[module $[TARGET],$[depend]]
#if $[eq $[depend_metalib],$[metalib]]
// Here's a dependent library in the *same* metalib.
#set depend_libs $[depend_libs] $[depend]
#elif $[ne $[depend_metalib],]
// This dependent library is in a *different* metalib.
#set depend_libs $[depend_libs] $[depend_metalib]
#else
// This dependent library is not in any metalib.
#set depend_libs $[depend_libs] $[depend]
#endif
#end depend
#else
// This library is *not* included on a metalib.
#foreach depend $[LOCAL_LIBS]
#define depend_metalib $[module $[TARGET],$[depend]]
#if $[ne $[depend_metalib],]
// This dependent library is on a metalib.
#set depend_libs $[depend_libs] $[depend_metalib]
#else
// This dependent library is not in any metalib.
#set depend_libs $[depend_libs] $[depend]
#endif
#end depend
#endif
#end lib_target noinst_lib_target
// These will never be part of a metalib.
#forscopes static_lib_target bin_target noinst_bin_target metalib_target
#foreach depend $[LOCAL_LIBS]
#define depend_metalib $[module $[TARGET],$[depend]]
#if $[ne $[depend_metalib],]
// This dependent library is on a metalib.
#set depend_libs $[depend_libs] $[depend_metalib]
#else
// This dependent library is not in any metalib.
#set depend_libs $[depend_libs] $[depend]
#endif
#end depend
#end static_lib_target bin_target noinst_bin_target metalib_target
// In case we're defining any metalibs, these depend directly on
// their components as well.
#set depend_libs $[depend_libs] $[COMPONENT_LIBS(metalib_target)]
// Now correct all the libraries listed in depend_libs to refer to a
// real library name.
#map static_libs TARGET(*/static_lib_target)
#map dynamic_libs TARGET(*/lib_target */metalib_target)
#map all_libs TARGET(*/static_lib_target */lib_target */metalib_target)
#define new_depend_libs
#foreach lib $[sort $[depend_libs]]
// Make sure the library is something we're actually building.
#if $[all_libs $[build_directory],$[lib]]
#define libname $[static_libs lib$[TARGET].a,$[lib]] $[dynamic_libs lib$[TARGET].so,$[lib]]
#if $[eq $[libname],]
Warning: No such library $[lib], dependency of $[DIRNAME].
#else
#set new_depend_libs $[new_depend_libs] $[libname]
#endif
#endif
#end lib
#set depend_libs $[sort $[new_depend_libs]]
#end get_depend_libs

20
ppremake/Makefile.am Normal file
View File

@@ -0,0 +1,20 @@
bin_PROGRAMS = ppremake
ppremake_SOURCES = \
find_searchpath.cxx find_searchpath.h \
gnu_getopt.c gnu_getopt.h \
ppCommandFile.cxx ppCommandFile.h ppDirectoryTree.cxx \
ppDirectoryTree.h ppMain.cxx ppMain.h \
ppFilenamePattern.cxx \
ppFilenamePattern.h ppNamedScopes.cxx ppNamedScopes.h \
ppScope.cxx ppScope.h ppSubroutine.cxx ppSubroutine.h \
ppremake.cxx ppremake.h tokenize.cxx \
tokenize.h
data_DATA = \
System.pp Depends.pp Template.autoconf.pp \
Global.stopgap.pp Template.stopgap.pp
EXTRA_DIST =\
System.pp Depends.pp Template.autoconf.pp \
Global.stopgap.pp Template.stopgap.pp

34
ppremake/System.pp Normal file
View File

@@ -0,0 +1,34 @@
//
// System.pp
//
// This is a system-wide configure file for ppremake. It's normally
// #included from a package-specific Config.pp in the root of the
// source tree. It makes variable declarations that are not normally
// user-editable, but are required to set up the normal processing of
// ppremake.
//
// Define DIR_TYPE as "src", since that's the most common kind of source
// file.
#if $[eq $[DIR_TYPE],]
#define DIR_TYPE src
#endif
// Define where to look for the various kinds of system files.
#if $[eq $[DEPENDS_FILE],]
#define DEPENDS_FILE $[PPREMAKE_DIR]/Depends.pp
#endif
#if $[eq $[GLOBAL_FILE],]
#define GLOBAL_FILE $[PPREMAKE_DIR]/Global.$[BUILD_TYPE].pp
#endif
#if $[eq $[TEMPLATE_FILE],]
#define TEMPLATE_FILE $[PPREMAKE_DIR]/Template.$[BUILD_TYPE].pp
#endif
// Include the global definitions for the template type, if the file
// is there.
#sinclude $[GLOBAL_FILE]

View File

@@ -0,0 +1,922 @@
//
// Template.autoconf.pp
//
// This file defines the set of output files that will be generated to
// support an autoconf/automake style build. This works particularly
// well when gcc/g++ will be used to compile, for instance on Linux.
//
#defer get_sys_libs $[subst -ldl,@libdl@,$[patsubst %,-l%,$[UNIX_SYS_LIBS]]]
// First, check to see if the entire directory has been switched out.
#define omit
#if $[DIRECTORY_IF_GL]
#set omit $[not $[HAVE_GL]]
#endif
#if $[DIRECTORY_IF_GLX]
#set omit $[not $[HAVE_GLX]]
#endif
#if $[DIRECTORY_IF_WGL]
#set omit $[not $[HAVE_WGL]]
#endif
#if $[DIRECTORY_IF_GLUT]
#set omit $[not $[HAVE_GLUT]]
#endif
#if $[DIRECTORY_IF_SGIGL]
#set omit $[not $[HAVE_SGIGL]]
#endif
#if $[DIRECTORY_IF_DX]
#set omit $[not $[HAVE_DX]]
#endif
#if $[DIRECTORY_IF_PS2]
#set omit $[not $[HAVE_PS2]]
#endif
#if $[DIRECTORY_IF_RIB]
#set omit $[not $[HAVE_RIB]]
#endif
#if $[DIRECTORY_IF_VRPN]
#set omit $[not $[HAVE_VRPN]]
#endif
//////////////////////////////////////////////////////////////////////
#if $[eq $[DIR_TYPE], src]
//////////////////////////////////////////////////////////////////////
// For a source directory, build a Makefile.am with a number of targets.
#output Makefile.am
#format makefile
# Makefile.am generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
#if $[omit]
// If we're omitting the directory, everything becomes an extra_dist.
EXTRA_DIST = Sources.pp $[EXTRA_DIST] $[SOURCES(static_lib_target noinst_lib_target lib_target noinst_bin_target bin_target test_bin_target)]
#else // $[omit]
// We define a map variable that allows us to look up all the libs in
// the various directories by target name. With this map variable, we
// can translate the list of local_libs (which is simply a list of
// library names, with no directory information), into a list of
// relative filenames to each library.
#map local_libs TARGET(*/static_lib_target */lib_target */noinst_lib_target)
#define all_include_dirs
lib_LTLIBRARIES = $[TARGET(static_lib_target lib_target):%=lib%.la]
noinst_LTLIBRARIES = $[TARGET(noinst_lib_target):%=lib%.la]
bin_PROGRAMS = $[TARGET(bin_target)]
noinst_PROGRAMS = $[TARGET(noinst_bin_target)]
EXTRA_PROGRAMS = $[TARGET(test_bin_target)]
#if $[ne $[YACC_PREFIX],]
YFLAGS = -d --name-prefix=$[YACC_PREFIX] $[YFLAGS]
LFLAGS = -P$[YACC_PREFIX] -olex.yy.c $[LFLAGS]
#else
YFLAGS = -d $[YFLAGS]
LFLAGS = $[LFLAGS]
#endif
#define alt_cflags @nspr_cflags@ @python_cflags@
#define alt_lflags @nspr_lflags@
#define alt_libs @nspr_libs@
#if $[ne $[USE_ZLIB],]
#define alt_cflags $[alt_cflags] @zlib_cflags@
#define alt_lflags $[alt_lflags] @zlib_lflags@
#define alt_libs $[alt_libs] @zlib_libs@
#endif
#if $[ne $[USE_GL],]
#define alt_cflags $[alt_cflags] @gl_cflags@ @glut_cflags@
#define alt_lflags $[alt_lflags] @gl_lflags@ @glut_lflags@
#define alt_libs $[alt_libs] @gl_libs@ @glut_libs@
#endif
#define built_sources
#define install_data
#forscopes static_lib_target lib_target noinst_lib_target
// This map variable lets us identify which metalib, if any, is
// including this particular library.
#map module LOCAL_LIBS(*/metalib_target)
// And this defines the complete set of libs we depend on: the
// LOCAL_LIBS we listed as directly depending on, plus all of the
// LOCAL_LIBS *those* libraries listed, and so on.
#define complete_local_libs $[closure local_libs,$[LOCAL_LIBS]]
#if $[ne $[IF_ZLIB_SOURCES],]
if HAVE_ZLIB
EXTRA_ZLIB = $[IF_ZLIB_SOURCES]
else
EXTRA_ZLIB =
endif
#define SOURCES $[SOURCES] $(EXTRA_ZLIB)
#endif
#define local_incs $[local_libs $[RELDIR],$[complete_local_libs]] $[RELDIR($[LOCAL_INCS:%=%/])]
// Check for interrogate.
#if $[eq $[IGATESCAN], all]
#define IGATESCAN $[filter-out %.I %.lxx %.yxx %.N,$[SOURCES]]
#endif
#if $[ne $[IGATESCAN],]
#define IGATEFILE $[TARGET].in.cxx
#define IGATEDBFILE lib$[TARGET].in
#define IGATELIBRARY lib$[TARGET]
#define IGATEMODULE lib$[module $[TARGET],$[TARGET]]
#if $[eq $[IGATEMODULE], lib]
#define IGATEMODULE $[IGATELIBRARY]
#endif
IGATESCAN = $[IGATESCAN]
$[IGATEFILE] : $(IGATESCAN)
@dtool@/bin/interrogate $[IGATEFLAGS] @system_igate@ -DCPPPARSER -D__cplusplus -I@dtool@/include/parser-inc @trees_inc@ $[local_incs:%=-I%] $[alt_cflags] $[CDEFINES] -module "$[IGATEMODULE]" -library "$[IGATELIBRARY]" -oc $[IGATEFILE] -od $[IGATEDBFILE] -fnames -string -refcount -assert -promiscuous -python $(IGATESCAN)
#set built_sources $[built_sources] $[IGATEFILE]
#set install_data $[install_data] $[IGATEDBFILE]
#endif
#define SOURCES $[SOURCES] $[IGATEFILE]
lib$[TARGET]_la_SOURCES = $[SOURCES]
lib$[TARGET]_la_LIBADD = $[OTHER_LIBS:%=-l%] $[alt_libs] $[get_sys_libs]
#set all_include_dirs $[all_include_dirs] $[local_incs]
#end static_lib_target lib_target noinst_lib_target
#forscopes bin_target noinst_bin_target test_bin_target
#if $[ne $[IF_ZLIB_SOURCES],]
if HAVE_ZLIB
EXTRA_ZLIB = $[IF_ZLIB_SOURCES]
else
EXTRA_ZLIB =
endif
#define $[SOURCES] $(EXTRA_ZLIB)
#endif
// This defines the complete set of libs we depend on: the LOCAL_LIBS
// we listed as directly depending on, plus all of the LOCAL_LIBS
// *those* libraries listed, and so on.
#define complete_local_libs $[closure local_libs,$[LOCAL_LIBS]]
$[TARGET]_SOURCES = $[SOURCES]
$[TARGET]_LDADD = $[local_libs $[RELDIR]/lib$[TARGET].la,$[complete_local_libs]] $[OTHER_LIBS:%=-l%] $[alt_libs] $[get_sys_libs]
#set all_include_dirs $[all_include_dirs] $[local_libs $[RELDIR],$[complete_local_libs]]
#set all_include_dirs $[all_include_dirs] $[RELDIR($[LOCAL_INCS:%=%/])]
#end bin_target noinst_bin_target test_bin_target
include_HEADERS = $[sort $[INSTALL_HEADERS(static_lib_target lib_target bin_target)] $[INSTALL_HEADERS]]
#set install_data $[install_data] $[INSTALL_DATA]
#if $[ne $[INSTALL_PARSER_INC],]
parserincdir = @includedir@/parser-inc
parserinc_HEADERS = $[INSTALL_PARSER_INC]
#endif
INCLUDES = $[patsubst %,-I%,$[sort $[all_include_dirs]]] @trees_inc@ $[alt_cflags]
LDFLAGS = @ldflags@ @trees_lflags@ $[alt_lflags]
EXTRA_DIST = Sources.pp $[EXTRA_DIST] $[INSTALL_LIBS] $[INSTALL_SCRIPTS]$[install_data]
BUILT_SOURCES =$[built_sources]
data_DATA =$[install_data]
#endif // $[omit]
#end Makefile.am
//////////////////////////////////////////////////////////////////////
#elif $[eq $[DIR_TYPE], metalib]
//////////////////////////////////////////////////////////////////////
// A metalib directory is similar to a regular source directory,
// but a little simpler.
#output Makefile.am
#format makefile
# Makefile.am generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
#if $[omit]
// If we're omitting the directory, everything becomes an extra_dist.
EXTRA_DIST = Sources.pp $[EXTRA_DIST] $[SOURCES(static_lib_target noinst_lib_target lib_target noinst_bin_target bin_target test_bin_target)]
#else // $[omit]
// We define a map variable that allows us to look up all the libs in
// the various directories by target name. With this map variable, we
// can translate the list of local_libs (which is simply a list of
// library names, with no directory information), into a list of
// relative filenames to each library.
#map local_libs TARGET(*/static_lib_target */lib_target */noinst_lib_target)
#define all_include_dirs $(includedir)
lib_LTLIBRARIES = $[TARGET(metalib_target):%=lib%.la]
#define alt_cflags @nspr_cflags@ @python_cflags@
#define alt_lflags @nspr_lflags@
#define alt_libs @nspr_libs@
#if $[ne $[USE_ZLIB],]
#define alt_cflags $[alt_cflags] @zlib_cflags@
#define alt_lflags $[alt_lflags] @zlib_lflags@
#define alt_libs $[alt_libs] @zlib_libs@
#endif
#if $[ne $[USE_GL],]
#define alt_cflags $[alt_cflags] @gl_cflags@
#define alt_lflags $[alt_lflags] @gl_lflags@
#define alt_libs $[alt_libs] @gl_libs@
#endif
#forscopes metalib_target
#if $[ne $[IF_PYTHON_SOURCES],]
if HAVE_PYTHON
EXTRA_PYTHON = $[IF_PYTHON_SOURCES]
else
EXTRA_PYTHON =
endif
#define SOURCES $[SOURCES] $(EXTRA_PYTHON)
#endif
// This defines the complete set of libs we depend on: the LOCAL_LIBS
// we listed as directly depending on, plus all of the LOCAL_LIBS
// *those* libraries listed, and so on.
#define complete_local_libs $[closure local_libs,$[LOCAL_LIBS]]
lib$[TARGET]_la_SOURCES = $[SOURCES]
lib$[TARGET]_la_LIBADD = $[complete_local_libs:%=-l%] $[get_sys_libs]
#end metalib_target
INCLUDES = $[patsubst %,-I%,$[sort $[all_include_dirs]]] @trees_inc@ $[alt_cflags]
LDFLAGS = @ldflags@ -L$(libdir) -rpath $(libdir) @trees_lflags@ $[alt_lflags]
EXTRA_DIST = Sources.pp $[EXTRA_DIST]
#endif // $[omit]
#end Makefile.am
//////////////////////////////////////////////////////////////////////
#elif $[eq $[DIR_TYPE], group]
//////////////////////////////////////////////////////////////////////
#output Makefile.am
#format makefile
# Makefile.am generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
SUBDIRS = $[SUBDIRS]
EXTRA_DIST = Sources.pp $[EXTRA_DIST]
#end Makefile.am
//////////////////////////////////////////////////////////////////////
#elif $[eq $[DIR_TYPE], toplevel]
//////////////////////////////////////////////////////////////////////
#output Makefile.am
#format makefile
# Makefile.am generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
FIRSTBUILD_SUBDIRS = $[filter_out metalibs,$[SUBDIRS]]
SUBDIRS = $[SUBDIRS]
#define INSTALL_HEADERS $[INSTALL_HEADERS] $[CONFIG_HEADER]
include_HEADERS = $[INSTALL_HEADERS]
EXTRA_DIST = Sources.pp Config.pp $[EXTRA_DIST]
# We define this custom rule for all-recursive as an ordering hack.
# It's just like the default rule, except that it traverses through
# only FIRSTBUILD_SUBDIRS, instead of all of SUBDIRS. The idea is
# that first we build everything in FIRSTBUILD_SUBDIRS, and then when
# we're installing, we build everything in SUBDIRS as well. This hack
# is necessary to build targets in metalibs that link directly with
# installed shared libraries.
all-recursive:
@set fnord $(MAKEFLAGS); amf=$$2; \
dot_seen=no; \
target=`echo $@ | sed s/-recursive//`; \
list='$(FIRSTBUILD_SUBDIRS)'; for subdir in $$list; do \
echo "Making $$target in $$subdir"; \
if test "$$subdir" = "."; then \
dot_seen=yes; \
local_target="$$target-am"; \
else \
local_target="$$target"; \
fi; \
(cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
|| case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \
done; \
if test "$$dot_seen" = "no"; then \
$(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
fi; test -z "$$fail"
#end Makefile.am
#output configure.in
#format straight
dnl configure.in generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
dnl Process this file with autoconf to produce a configure script.
AC_INIT($[SAMPLE_SOURCE_FILE])
AM_INIT_AUTOMAKE($[PACKAGE], $[VERSION])
#if $[eq $[CONFIG_HEADER],]
dnl This package doesn't care about a generated config.h file. This causes
dnl a few problems with automake, so we fake it out with this hack.
AM_CONFIG_HEADER(ignore_config.h)
#else
AM_CONFIG_HEADER($[CONFIG_HEADER])
#endif
if test "${CTPROJS+set}" = set; then
if test "${$[upcase $[PACKAGE]]+set}" != set; then
echo ""
echo "The environment variable CTPROJS is currently set, indicating"
echo "you are attached to one or more trees, but you are not attached"
echo "to $[upcase $[PACKAGE]]. Either unattach from everything, or attach to $[upcase $[PACKAGE]]."
echo ""
exit 1
fi
# If we're currently attached, the install directory is the same as
# the source directory.
if test "$prefix" != "NONE"; then
echo ""
echo The environment variable CTPROJS is currently set, indicating
echo you are attached to one or more trees. When you configure the
echo package while attached, you cannot specify a --prefix to install
echo the built sources--it always installs in the source directory.
echo ""
exit 1
fi
prefix=$$[upcase $[PACKAGE]]
fi
AC_PREFIX_DEFAULT($[INSTALL_DIR])
AC_PROG_MAKE_SET
AC_CANONICAL_HOST
# If we have a CFLAGS variable but not a CXXFLAGS variable, let them
# be the same.
if test "${CXXFLAGS+set}" != set -a "${CFLAGS+set}" = set; then
CXXFLAGS=$CFLAGS
fi
# Save these variables for later, so we can easily append to them or
# change them.
user_ldflags=${LDFLAGS-}
user_cflags=${CFLAGS-}
user_cxxflags=${CXXFLAGS-}
dnl Choose a suitable set of system-dependent interrogate flags.
case "$host_os" in
irix*) system_igate="-D__mips__ -D__MIPSEB__";;
linux-gnu*) system_igate="-D__i386__";;
esac
AC_SUBST(system_igate)
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CXX
AM_PROG_LEX
AM_DISABLE_STATIC
AM_PROG_LIBTOOL
AC_PATH_XTRA
dnl We require specifically Bison, not any other flavor of Yacc.
AC_CHECK_PROGS(YACC, 'bison -y')
AC_ARG_WITH(optimize,
[ --with-optimize=LEVEL Specify the optimization/debug symbol level (1-4, default 1)])
if test "${with_optimize-no}" = "no"; then
with_optimize=$[OPTIMIZE]
fi
if test "$with_optimize" = "1"; then
# Optimize level 1: No optimizations, and full debug symbols.
if test "${ac_cv_prog_gcc}" = "yes"; then
CFLAGS="$user_cflags -g -Wall"
CXXFLAGS="$user_cxxflags -g -Wall"
else
CFLAGS="$user_cflags -g"
CXXFLAGS="$user_cxxflags -g"
fi
elif test "$with_optimize" = "2"; then
# Optimize level 2: Compiler optimizations, and full debug if supported.
if test "${ac_cv_prog_gcc}" = "yes"; then
CFLAGS="$user_cflags -O2 -g -Wall"
CXXFLAGS="$user_cxxflags -O2 -g -Wall"
else
CFLAGS="$user_cflags -O"
CXXFLAGS="$user_cxxflags -O"
fi
elif test "$with_optimize" = "3"; then
# Optimize level 3: Compiler optimizations, without debug symbols.
if test "${ac_cv_prog_gcc}" = "yes"; then
CFLAGS="$user_cflags -O2 -Wall"
CXXFLAGS="$user_cxxflags -O2 -Wall"
else
CFLAGS="$user_cflags -O"
CXXFLAGS="$user_cxxflags -O"
fi
elif test "$with_optimize" = "4"; then
# Optimize level 4: As above, with asserts removed.
if test "${ac_cv_prog_gcc}" = "yes"; then
CFLAGS="$user_cflags -O2 -Wall -DNDEBUG"
CXXFLAGS="$user_cxxflags -O2 -Wall -DNDEBUG"
else
CFLAGS="$user_cflags -O -DNDEBUG"
CXXFLAGS="$user_cxxflags -O -DNDEBUG"
fi
else
echo "Invalid optimize level: $with_optimize"
exit 0
fi
trees_inc=
trees_lflags=
#foreach require $[REQUIRED_TREES]
AC_ARG_WITH($[require],
[ --with-$[require]=DIR Prefix where $[upcase $[require]] is installed (same as --prefix)])
if test "${CTPROJS+set}" = set; then
if test "$with_$[require]" != ""; then
echo ""
echo "The environment variable CTPROJS is currently set, indicating"
echo "you are attached to one or more trees. When you configure the"
echo "package while attached, you cannot specify a directory to search"
echo "for --$[require]; it will always search in the currently attached $[upcase $[require]]."
echo ""
exit 1
fi
if test "${$[upcase $[require]]+set}" != set; then
echo ""
echo "The environment variable CTPROJS is currently set, indicating"
echo "you are attached to one or more trees, but you are not attached"
echo "to $[upcase $[require]]. Either unattach from everything, or attach to $[upcase $[require]]."
echo ""
exit 1
fi
$[require]='${$[upcase $[require]]}'
else
# No attachments--respect the --with-$[require] parameter.
if test "$with_$[require]" != "" -a "$with_$[require]" != "no" -a "$with_$[require]" != "yes"; then
$[require]=$with_$[require]
else
$[require]='${prefix}'
fi
trees_inc="$trees_inc -I"'$($[require])/include'
trees_lflags="$trees_lflags -L"'$($[require])/lib'
fi
AC_SUBST($[require])
#end require
AC_SUBST(trees_inc)
AC_SUBST(trees_lflags)
dnl First, we'll test for C-specific features.
AC_LANG_C
dnl Checks for libraries.
libdl=
libm=
AC_CHECK_LIB(dl, dlopen, libdl=-ldl)
AC_CHECK_LIB(m, sin, libm=-lm)
AC_SUBST(libdl)
AC_SUBST(libm)
// Only bother to make the following tests if we're actually building
// a config.h.
#if $[ne $[CONFIG_HEADER],]
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(malloc.h alloca.h unistd.h io.h minmax.h sys/types.h)
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_BIGENDIAN
AC_GETTIMEOFDAY
dnl Checks for library functions.
AC_CHECK_FUNCS(getopt getopt_long_only)
dnl Now we can test some C++-specific features.
AC_LANG_CPLUSPLUS
AC_HEADER_IOSTREAM
AC_CHECK_HEADERS(sstream)
AC_NAMESPACE
AC_IOS_BINARY
#endif
AC_LANG_C
AC_ARG_WITH(python,
[ --with-python=DIR Prefix where Python is installed (usually /usr/local)])
have_python=no
include_python=
if test "$with_python" != "no"; then
if test "$with_python" = "yes" -o "$with_python" = ""; then
AC_SEARCH_HPACKAGE(/usr/local /usr,
python1.6 python,
Python.h, python)
else
AC_SEARCH_HPACKAGE($with_python,
python1.6 python,
Python.h, python)
fi
if test "$with_python" != ""; then
if test "$python_PKG" != "yes"; then
dnl If the user specified to search for python but we didn't find it,
dnl abort now.
echo ""
echo "**** Could not locate Python package. Use --with-python=directory,"
echo " e.g. --with-python=/usr/local, or just --with-python."
echo " If Python is not installed, specify --without-python."
echo ""
exit 1
fi
fi
if test "$python_PKG" = "yes"; then
#if $[ne $[CONFIG_HEADER],]
AC_DEFINE(HAVE_PYTHON)
#endif
have_python=yes
python_cflags=-I$python_INCLUDE
fi
fi
AC_SUBST(have_python)
AC_SUBST(python_cflags)
AM_CONDITIONAL(HAVE_PYTHON, test "$have_python" = "yes")
AC_ARG_WITH(nspr,
[ --with-nspr=DIR Prefix where NSPR is installed (usually /usr/local/mozilla)])
have_nspr=no
include_nspr=
if test "$with_nspr" != "no"; then
if test "$with_nspr" = "yes" -o "$with_nspr" = ""; then
AC_SEARCH_PACKAGE(/usr/local/mozilla /usr/local/mozilla/dist/*,,
nspr.h, nspr3, PR_Init, nspr)
else
AC_SEARCH_PACKAGE($with_nspr $with_nspr/dist/*,,
nspr.h, nspr3, PR_Init, nspr)
fi
if test "$with_nspr" != ""; then
if test "$nspr_PKG" != "yes"; then
dnl If the user specified to search for NSPR but we didn't find it,
dnl abort now.
echo ""
echo "**** Could not locate NSPR package. Use --with-nspr=directory,"
echo " e.g. --with-nspr=/usr/local, or just --with-nspr."
echo " If NSPR is not installed, specify --without-nspr."
echo ""
exit 1
fi
fi
if test "$nspr_PKG" = "yes"; then
#if $[ne $[CONFIG_HEADER],]
AC_DEFINE(HAVE_NSPR)
#endif
have_nspr=yes
nspr_cflags="-I$nspr_INCLUDE"
nspr_ldflags="-L$nspr_LIB"
nspr_libs="-lnspr3"
fi
fi
AC_SUBST(have_nspr)
AC_SUBST(nspr_cflags)
AC_SUBST(nspr_lflags)
AC_SUBST(nspr_libs)
AM_CONDITIONAL(HAVE_NSPR, test "$have_nspr" = "yes")
AC_ARG_WITH(zlib,
[ --with-zlib=DIR Prefix where zlib is installed (usually /usr)])
have_zlib=no
include_zlib=
if test "$with_zlib" != "no"; then
if test "$with_zlib" = "yes" -o "$with_zlib" = ""; then
AC_SEARCH_PACKAGE(/usr /usr/local,,
zlib.h, z, gzopen, zlib)
else
AC_SEARCH_PACKAGE($with_zlib,,
zlib.h, z, gzopen, zlib)
fi
if test "$with_zlib" != ""; then
if test "$zlib_PKG" != "yes"; then
dnl If the user specified to search for zlib but we didn't find it,
dnl abort now.
echo ""
echo "**** Could not locate zlib package. Use --with-zlib=directory,"
echo " e.g. --with-zlib=/usr/local, or just --with-zlib."
echo " If zlib is not installed, specify --without-zlib."
echo ""
exit 1
fi
fi
if test "$zlib_PKG" = "yes"; then
#if $[ne $[CONFIG_HEADER],]
AC_DEFINE(HAVE_ZLIB)
#endif
have_zlib=yes
if test "$zlib_INCLUDE" != ""; then
zlib_cflags="-I$zlib_INCLUDE"
fi
if test "$zlib_LIB" != ""; then
zlib_lflags="-L$zlib_LIB"
fi
zlib_libs="-lz"
fi
fi
AC_SUBST(have_zlib)
AC_SUBST(zlib_cflags)
AC_SUBST(zlib_lflags)
AC_SUBST(zlib_libs)
AM_CONDITIONAL(HAVE_ZLIB, test "$have_zlib" = "yes")
AC_ARG_WITH(gl,
[ --with-gl=DIR Prefix where OpenGL is installed (usually /usr)])
have_gl=no
include_gl=
if test "$with_gl" != "no"; then
if test "$with_gl" = "yes" -o "$with_gl" = ""; then
AC_SEARCH_PACKAGE(/usr /usr/local,,
GL/gl.h, GL, glVertex3f, gl)
else
AC_SEARCH_PACKAGE($with_gl,,
GL/gl.h, GL, glVertex3f, gl)
fi
if test "$with_gl" != ""; then
if test "$gl_PKG" != "yes"; then
dnl If the user specified to search for OpenGL but we didn't find it,
dnl abort now.
echo ""
echo "**** Could not locate OpenGL package. Use --with-gl=directory,"
echo " e.g. --with-gl=/usr/local, or just --with-gl."
echo " If OpenGL is not installed, specify --without-gl."
echo ""
exit 1
fi
fi
if test "$gl_PKG" = "yes"; then
#if $[ne $[CONFIG_HEADER],]
AC_DEFINE(HAVE_GL)
#endif
have_gl=yes
if test "$gl_INCLUDE" != ""; then
gl_cflags="-I$gl_INCLUDE"
fi
if test "$gl_LIB" != ""; then
gl_lflags="-L$gl_LIB"
fi
gl_libs="-lGL -lGLU"
fi
fi
AC_SUBST(have_gl)
AC_SUBST(gl_cflags)
AC_SUBST(gl_lflags)
AC_SUBST(gl_libs)
AM_CONDITIONAL(HAVE_GL, test "$have_gl" = "yes")
AC_ARG_WITH(glu,
[ --with-glu=DIR Prefix where GL util library is installed (usually /usr)])
have_glu=no
include_glu=
if test "$with_glu" != "no"; then
if test "$with_glu" = "yes" -o "$with_glu" = ""; then
AC_SEARCH_PACKAGE($gl_INCLUDE /usr /usr/local,,
GL/glu.h, GLU, gluSphere, glu)
else
AC_SEARCH_PACKAGE($with_glu,,
GL/glu.h, GLU, gluSphere, glu)
fi
if test "$with_glu" != ""; then
if test "$glu_PKG" != "yes"; then
dnl If the user specified to search for GL util library but we didn't find it,
dnl abort now.
echo ""
echo "**** Could not locate GL util library. Use --with-glu=directory,"
echo " e.g. --with-glu=/usr/local, or just --with-glu."
echo " If GL util library is not installed, specify --without-glu."
echo ""
exit 1
fi
fi
if test "$glu_PKG" = "yes"; then
#if $[ne $[CONFIG_HEADER],]
AC_DEFINE(HAVE_GLU)
#endif
have_glu=yes
if test "$glu_INCLUDE" != ""; then
glu_cflags="-I$glu_INCLUDE"
fi
if test "$glu_LIB" != ""; then
glu_lflags="-L$glu_LIB"
fi
glu_libs="-lGLU -lGLUU"
fi
fi
AC_SUBST(have_glu)
AC_SUBST(glu_cflags)
AC_SUBST(glu_lflags)
AC_SUBST(glu_libs)
AM_CONDITIONAL(HAVE_GLU, test "$have_glu" = "yes")
AC_ARG_WITH(glx,
[ --with-glx=DIR Prefix where GLX is installed (usually /usr)])
have_glx=no
include_glx=
if test "$with_glx" != "no"; then
if test "$with_glx" = "yes" -o "$with_glx" = ""; then
AC_SEARCH_HPACKAGE($gl_INCLUDE /usr /usr/local $x_libraries,,
GL/glx.h, glx)
else
AC_SEARCH_HPACKAGE($with_glx,,
GL/glx.h, glx)
fi
if test "$with_glx" != ""; then
if test "$glx_PKG" != "yes"; then
dnl If the user specified to search for GLX but we didn't find it,
dnl abort now.
echo ""
echo "**** Could not locate GLX package. Use --with-glx=directory,"
echo " e.g. --with-glx=/usr/local, or just --with-glx."
echo " If GLX is not installed, specify --without-glx."
echo ""
exit 1
fi
fi
if test "$glx_PKG" = "yes"; then
#if $[ne $[CONFIG_HEADER],]
AC_DEFINE(HAVE_GLX)
#endif
have_glx=yes
if test "$glx_INCLUDE" != ""; then
glx_cflags="-I$glx_INCLUDE"
fi
fi
fi
AC_SUBST(have_glx)
AC_SUBST(glx_cflags)
AM_CONDITIONAL(HAVE_GLX, test "$have_glx" = "yes")
AC_ARG_WITH(glut,
[ --with-glut=DIR Prefix where glut is installed (usually /usr)])
have_glut=no
include_glut=
if test "$with_glut" != "no"; then
if test "$with_glut" = "yes" -o "$with_glut" = ""; then
AC_SEARCH_PACKAGE($gl_INCLUDE /usr /usr/local $x_libraries,,
GL/glut.h, glut, glutInit, glut, -lGL -lGLU)
else
AC_SEARCH_PACKAGE($with_glut,,
GLUT/glut.h, glut, glutInit, glut, -lGL -lGLU)
fi
if test "$with_glut" != ""; then
if test "$glut_PKG" != "yes"; then
dnl If the user specified to search for glut but we didn't find it,
dnl abort now.
echo ""
echo "**** Could not locate glut package. Use --with-glut=directory,"
echo " e.g. --with-glut=/usr/local, or just --with-glut."
echo " If glut is not installed, specify --without-glut."
echo ""
exit 1
fi
fi
if test "$glut_PKG" = "yes"; then
#if $[ne $[CONFIG_HEADER],]
AC_DEFINE(HAVE_GLUT)
#endif
have_glut=yes
if test "$glut_INCLUDE" != ""; then
glut_cflags="-I$glut_INCLUDE"
fi
if test "$glut_LIB" != ""; then
glut_lflags="-L$glut_LIB"
fi
glut_libs="-lglut"
fi
fi
AC_SUBST(have_glut)
AC_SUBST(glut_cflags)
AC_SUBST(glut_lflags)
AC_SUBST(glut_libs)
AM_CONDITIONAL(HAVE_GLUT, test "$have_glut" = "yes")
AC_ARG_WITH(rib,
[ --with-rib Compile in the Renderman interface.])
have_rib=no
if test "$with_rib" = "yes"; then
have_rib=yes
fi
AC_SUBST(have_rib)
#if $[ne $[CONFIG_HEADER],]
if test "$have_rib" = "yes"; then
AC_DEFINE(HAVE_RIB)
fi
#endif
AM_CONDITIONAL(HAVE_RIB, test "$have_rib" = "yes")
AC_ARG_WITH(mikmod,
[ --with-mikmod[=libmikmod-config] Use the mikmod interface for audio.])
have_mikmod=no
include_mikmod=
if test "$with_mikmod" != "no"; then
if test "$with_mikmod" = "" -o "$with_mikmod" = "yes"; then
dnl search for the libmikmod-config program on the path.
AC_CHECK_PROG(with_mikmod, libmikmod-config, libmikmod-config, "no")
fi
fi
if test "$with_mikmod" != "no"; then
have_mikmod=yes
CFLAGS="$CFLAGS "`$with_mikmod --cflags`
CXXFLAGS="$CXXFLAGS "`$with_mikmod --cflags`
LDFLAGS="$LDFLAGS "`$with_mikmod --libs`
#if $[ne $[CONFIG_HEADER],]
AC_DEFINE(HAVE_MIKMOD)
#endif
fi
AC_SUBST(have_mikmod)
AM_CONDITIONAL(HAVE_MIKMOD, test "$have_mikmod" = "yes")
ldflags=$LDFLAGS
AC_SUBST(ldflags)
AC_OUTPUT([$[TREE:%=%/Makefile]])
#end configure.in
//////////////////////////////////////////////////////////////////////
#endif // DIR_TYPE

View File

@@ -0,0 +1,721 @@
//
// Template.stopgap.pp
//
// This file defines the set of output files that will be generated to
// support our old-style Makefile system. It is intended to aid as a
// transition to the new system.
//
//////////////////////////////////////////////////////////////////////
#if $[eq $[DIR_TYPE], src]
//////////////////////////////////////////////////////////////////////
// For a source directory, build a Makefile, Makefile.install, and a
// Makefile.target for each target.
#define submakes $[TARGET(static_lib_target):%=%.a] $[TARGET(lib_target noinst_lib_target):%=%.so] $[TARGET(sed_bin_target bin_target noinst_bin_target test_bin_target)]
#define install $[TARGET(static_lib_target):%=%.a] $[TARGET(lib_target noinst_lib_target):%=%.so] $[TARGET(sed_bin_target bin_target noinst_bin_target)]
// This map variable lets us identify which metalib, if any, is
// including each library built here.
#map module COMPONENT_LIBS(*/metalib_target)
// Now iterate through the libraries we're building and see which ones
// actually *are* being included in a metalib. For each one that is,
// we install the appropriate deferred file.
#define deferred
#forscopes lib_target
#define metalib $[module $[TARGET],$[TARGET]]
#if $[ne $[metalib],]
#set deferred $[deferred] Deferred.$[metalib].lib$[TARGET].so
#endif
#end lib_target
// Get the full set of libraries we depend on.
#call get_depend_libs
// Also get the targets we'll be installing.
#define install_libs $[sort $[TARGET(lib_target):%=lib%.so] $[TARGET(static_lib_target):%=lib%.a] $[INSTALL_LIBS]]
#define install_bin $[sort $[TARGET(bin_target)] $[INSTALL_BIN]]
#define install_scripts $[sort $[INSTALL_SCRIPTS(static_lib_target lib_target bin_target)] $[TARGET(sed_bin_target)] $[INSTALL_SCRIPTS]]
#define install_headers $[sort $[INSTALL_HEADERS(static_lib_target lib_target bin_target)] $[INSTALL_HEADERS]]
#define install_data $[sort $[INSTALL_DATA(static_lib_target lib_target sed_bin_target bin_target)] $[INSTALL_DATA]]
// Collect the set of interrogate database files we'll install,
// possibly one for each library we build.
#define install_igatedb
#if $[HAVE_PYTHON]
#forscopes lib_target
#if $[ne $[IGATESCAN],]
#set install_igatedb $[install_igatedb] lib$[TARGET].in
#endif
#end lib_target
#endif
#output Makefile
#format makefile
#### Meta Makefile.
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
################################# DO NOT EDIT ###########################
#### Sub make targets (extension of sub Makefile, eg 'foo' for Makefile.foo):
SUBMAKES = $[submakes]
#### List the minimal set of sub makes on the list above required to install.
INSTALL = $[install]
#### Location of sub Makefiles.
MAKEDIR = .
#### The action is here.
include $(DTOOL)/inc/Makefile.meta.rules
#### Sub-make build order dependencies:
# foo: bar
#end Makefile
#output Makefile.install
#format makefile
#### Installation makefile
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
################################# DO NOT EDIT ###########################
# 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)):
PACKAGE = $[DIRNAME]
PKGROOT = $[PATH]
ifneq (,$(PACKAGE))
#### Package dependencies (USESOTHER needs relative paths from project root):
USESLIBS = $[depend_libs]
# USESINCLUDE =
# USESOTHER =
#### Installed files:
LIBS = $[install_libs]
DEFERRED = $[deferred]
INCLUDE = $[install_headers]
BINS = $[install_bin]
SCRIPTS = $[install_scripts]
# SS =
# STK =
# MODELS =
ETC = $[install_data]
IGATEDB =$[install_igatedb]
# DOC =
# MAN =
# FONTS =
# ICONS =
# APPDEFAULTS =
# TCL =
# TELEUSE =
# SHADERS =
#### Other files to be installed (use relative pathname from project root):
#if $[ne $[INSTALL_PARSER_INC],]
PARSER_INC = $[INSTALL_PARSER_INC]
SRC_PARSER_INC = $(addprefix $(PKGROOT)/,$(PARSER_INC))
INST_PARSER_INC = $(addprefix inc/parser-inc/,$(PARSER_INC))
OTHER = $(INST_PARSER_INC)
#else
# OTHER =
#endif
#### 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
#if $[ne $[INSTALL_PARSER_INC],]
$(INST_PARSER_INC) : inc/parser-inc/% : $(PKGROOT)/%
$(MKINSTALL)
#endif
#### 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
#end Makefile.install
// Now generate a suitable Makefile for each library target.
#forscopes lib_target noinst_lib_target
// Again, is this library included in a metalib? If so, output the
// appropriate deferred rules.
#define metalib $[module $[TARGET],$[TARGET]]
// We might need to define a BUILDING_ symbol for win32. We use the
// BUILDING_DLL variable name, defined typically in the metalib, for
// this; but in some cases, where the library isn't part of a metalib,
// we define BUILDING_DLL directly for the target.
#define building_var $[BUILDING_DLL]
#if $[ne $[metalib],]
#set building_var $[module $[BUILDING_DLL],$[TARGET]]
#endif
// Get the full set of sources for this target.
#call get_sources
#call get_libs
// Which files will we interrogate, if any?
#if $[HAVE_PYTHON]
#if $[ne $[IGATESCAN],]
#if $[eq $[IGATESCAN],all]
#define igatescan $[filter-out %.I %.lxx %.yxx %.N,$[sources]]
#else
#define igatescan $[IGATESCAN]
#endif
#endif
#endif
#output Makefile.$[TARGET].so
#format makefile
#### Makefile for DSO's. Any fields commented out are optional.
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
################################# DO NOT EDIT ###########################
#### Target's name:
TARGET = lib$[TARGET].so
DEFERRED_TARGET = $[metalib]
# Standard .o file conversion information.
#### Lex files
LFILES = $[filter %.lxx,$[sources]]
LEX = flex
LFLAGS = $[LFLAGS] $[YACC_PREFIX:%=-P%] -olex.yy.c
LEXTENSION = cxx
#### Yacc files
YFILES = $[filter %.yxx,$[sources]]
YACC = bison
YFLAGS = -y -d $[patsubst %,--name-prefix=%,$[YACC_PREFIX]]
YEXTENSION = cxx
#### C files
CFILES = $[filter %.c,$[sources]]
CFLAGS = $[building_var:%=-D%] $[alt_cflags] $[CFLAGS]
#### C++ files
C++FILES = $[filter %.cxx,$[sources]]
C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[C++FLAGS]
# USETEMPLATES = TRUE
# PTREPOSITORY = # Specify only if you want a specific name
#### Interrogate info
IGATESCAN = $[igatescan]
IGATEFLAGS = $[alt_ipath]
# IGATEFILE = # Specify only if you want a specific name
#### Additional search directories for C/C++ header files:
IPATH = $[alt_ipath]
#### Location to put .o files:
# ODIR =
#### Source file dependencies (unnecessary with clearmake)
# foo.c: foo.h
#### Other files and lib. Include $(ODIR) in any .o names.
# OFILES =
WHEN_NO_DEFER_LIBS = $[when_no_defer:%=-l%]
WHEN_DEFER_LIBS = $[when_defer:%=-l%]
LIBS = $[when_either:%=-l%]
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
#### Additional search directories for lib:
LPATH = $[alt_lpath]
#### Other linker flags.
#if $[ne $[alt_ld],]
LD = $[alt_ld]
#endif
# LDFLAGS =
#### Pull in standard .o make variables
include $(DTOOL)/inc/Makefile.o.vars
#### The .o action is here.
include $(DTOOL)/inc/Makefile.o.rules
#### Pull in standard binary make variables.
include $(DTOOL)/inc/Makefile.bin.vars
#### The .so action is here.
include $(DTOOL)/inc/Makefile.so.rules
#end Makefile.$[TARGET].so
#end lib_target noinst_lib_target
// Also generate a suitable Makefile for each static library target.
#forscopes static_lib_target
// Get the full set of sources for this target.
#call get_sources
#call get_libs
#output Makefile.$[TARGET].a
#format makefile
#### Makefile for archive libraries. Any fields commented out are optional.
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
################################# DO NOT EDIT ###########################
#### Target's name:
TARGET = lib$[TARGET].a
# Standard .o file conversion information.
#### Lex files
LFILES = $[filter %.lxx,$[sources]]
LEX = flex
LFLAGS = $[LFLAGS] $[YACC_PREFIX:%=-P%] -olex.yy.c
LEXTENSION = yy.cxx
# LSUBST =
#### Yacc files
YFILES = $[filter %.yxx,$[sources]]
YACC = bison
YFLAGS = -y -d $[patsubst %,--name-prefix=%,$[YACC_PREFIX]]
YEXTENSION = tab.cxx
# YSUBST =
#### C files
CFILES = $[filter %.c,$[sources]]
CFLAGS = $[building_var:%=-D%] $[alt_cflags] $[CFLAGS]
#### C++ files
C++FILES = $[filter %.cxx,$[sources]]
C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[C++FLAGS]
# USETEMPLATES = TRUE
# PTREPOSITORY = # Specify only if you want a specific name
#### Additional search directories for C/C++ header files:
IPATH = $[alt_ipath]
#### Location to put .o files:
# ODIR =
#### Source file dependencies (unnecessary with clearmake)
# foo.c: foo.h
#### Other .o files.
# OFILES =
#### Libs and flags for template instantiation.
WHEN_NO_DEFER_LIBS = $[when_no_defer:%=-l%]
WHEN_DEFER_LIBS = $[when_defer:%=-l%]
LIBS = $[when_either:%=-l%]
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
#### Additional search directories for lib:
LPATH = $[alt_lpath]
#### Archiver flags
# ARFLAGS =
#### Pull in standard .o make variables
include $(DTOOL)/inc/Makefile.o.vars
#### The .o action is here.
include $(DTOOL)/inc/Makefile.o.rules
#### Pull in standard binary make variables.
include $(DTOOL)/inc/Makefile.bin.vars
#### The .a action is here.
include $(DTOOL)/inc/Makefile.a.rules
#end Makefile.$[TARGET].a
#end static_lib_target
// And also generate a suitable Makefile for each binary target.
#forscopes bin_target noinst_bin_target test_bin_target
// Get the full set of sources for this target.
#call get_sources
#call get_libs
#output Makefile.$[TARGET]
#format makefile
#### Makefile for binaries. Any fields commented out are optional.
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
################################# DO NOT EDIT ###########################
#### Target's name:
TARGET = $[TARGET]
# Standard .o file conversion information.
#### Lex files
LFILES = $[filter %.lxx,$[sources]]
LEX = flex
LFLAGS = $[LFLAGS] $[YACC_PREFIX:%=-P%] -olex.yy.c
LEXTENSION = yy.cxx
# LSUBST =
#### Yacc files
YFILES = $[filter %.yxx,$[sources]]
YACC = bison
YFLAGS = -y -d $[patsubst %,--name-prefix=%,$[YACC_PREFIX]]
YEXTENSION = tab.cxx
# YSUBST =
#### C files
CFILES = $[filter %.c,$[sources]]
CFLAGS = $[building_var:%=-D%] $[alt_cflags] $[CFLAGS]
#### C++ files
C++FILES = $[filter %.cxx,$[sources]]
C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[C++FLAGS]
#### Additional search directories for C/C++ header files:
IPATH = $[alt_ipath]
#### Location to put .o files:
# ODIR =
#### Source file dependencies (unnecessary with clearmake)
# foo.c: foo.h
#### Other files and lib. Include $(ODIR) in any .o names.
# OFILES =
WHEN_NO_DEFER_LIBS = $[when_no_defer:%=-l%]
WHEN_DEFER_LIBS = $[when_defer:%=-l%]
LIBS = $[when_either:%=-l%]
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
#### Additional search directories for lib:
LPATH = $[alt_lpath]
#### Other linker flags.
#if $[ne $[alt_ld],]
LD = $[alt_ld]
#endif
# LDFLAGS =
#### Pull in standard .o make variables
include $(DTOOL)/inc/Makefile.o.vars
#### The .o action is here.
include $(DTOOL)/inc/Makefile.o.rules
#### Pull in standard binary make variables.
include $(DTOOL)/inc/Makefile.bin.vars
#### The bin action is here.
include $(DTOOL)/inc/Makefile.bin.rules
#end Makefile.$[TARGET]
#end bin_target noinst_bin_target test_bin_target
// Finally, generate the special scripts from the sed_bin_targets. Hopefully
// there won't be too many of these in the tree, since these are fairly
// Unix-specific.
#forscopes sed_bin_target
#output Makefile.$[TARGET]
#format makefile
#### This is a special makefile just to generate the $[TARGET] script.
$[TARGET] : $[SOURCE]
sed $[COMMAND] $^ >$@
chmod +x $@
clean :
cleanall :
rm -f $[TARGET]
#end Makefile.$[TARGET]
#end sed_bin_target
//////////////////////////////////////////////////////////////////////
#elif $[eq $[DIR_TYPE], metalib]
//////////////////////////////////////////////////////////////////////
// A metalib directory is similar to a regular source directory,
// but a little simpler.
#define submakes $[TARGET(metalib_target):%=%.so]
// This map variable lets us identify which metalib, if any, is
// including each library built here.
#map module COMPONENT_LIBS(*/metalib_target)
// Get the full set of libraries we depend on.
#call get_depend_libs
// Also get the targets we'll be installing.
#define install_libs $[TARGET(metalib_target):%=lib%.so]
#define install_headers $[INSTALL_HEADERS(metalib_target)]
#define install_data $[INSTALL_DATA(metalib_target)]
#output Makefile
#format makefile
#### Meta Makefile.
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
################################# DO NOT EDIT ###########################
#### Sub make targets (extension of sub Makefile, eg 'foo' for Makefile.foo):
SUBMAKES = $[submakes]
#### List the minimal set of sub makes on the list above required to install.
INSTALL = $[submakes]
#### Location of sub Makefiles.
MAKEDIR = .
#### The action is here.
include $(DTOOL)/inc/Makefile.meta.rules
#### Sub-make build order dependencies:
# foo: bar
#end Makefile
#output Makefile.install
#format makefile
#### Installation makefile
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
################################# DO NOT EDIT ###########################
# 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)):
PACKAGE = $[DIRNAME]
PKGROOT = $[PATH]
ifneq (,$(PACKAGE))
#### Package dependencies (USESOTHER needs relative paths from project root):
USESLIBS = $[depend_libs]
# USESINCLUDE =
# USESOTHER =
#### Installed files:
LIBS = $[install_libs]
INCLUDE = $[install_headers]
# BINS =
# SS =
# STK =
# MODELS =
# ETC =
# DOC =
# MAN =
# 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
#end Makefile.install
// Now generate a suitable Makefile for each metalib target.
#forscopes metalib_target
#define building_var $[BUILDING_DLL]
// Get the full set of sources for this target.
#call get_sources
#call get_libs
#if $[HAVE_PYTHON]
#map components TARGET(*/lib_target */noinst_lib_target)
#if $[ne $[components $[IGATESCAN],$[COMPONENT_LIBS]],]
#define igatemscan $[TARGET]
#endif
#endif
#output Makefile.$[TARGET].so
#format makefile
#### Makefile for DSO's. Any fields commented out are optional.
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
################################# DO NOT EDIT ###########################
#### Target's name:
TARGET = lib$[TARGET].so
# Standard .o file conversion information.
#### Lex files
LFILES = $[filter %.lxx,$[sources]]
LEX = flex
LFLAGS = $[LFLAGS] $[YACC_PREFIX:%=-P%] -olex.yy.c
LEXTENSION = yy.cxx
# LSUBST =
#### Yacc files
YFILES = $[filter %.yxx,$[sources]]
YACC = bison
YFLAGS = -y -d $[patsubst %,--name-prefix=%,$[YACC_PREFIX]]
YEXTENSION = tab.cxx
# YSUBST =
#### C files
CFILES = $[filter %.c,$[sources]]
CFLAGS = $[building_var:%=-D%] $[alt_cflags] $[CFLAGS]
#### C++ files
C++FILES = $[filter %.cxx,$[sources]]
C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[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
IGATEMSCAN = $[igatemscan]
#### Pull in deferred-target files built in other packages
DEFERRED_FILES = $[TARGET]
#### Additional search directories for C/C++ header files:
IPATH = $[alt_ipath]
#### Location to put .o files:
# ODIR =
#### Source file dependencies (unnecessary with clearmake)
# foo.c: foo.h
#### Other files and lib. Include $(ODIR) in any .o names.
# OFILES =
WHEN_NO_DEFER_LIBS = $[when_no_defer:%=-l%]
WHEN_DEFER_LIBS = $[when_defer:%=-l%]
LIBS = $[when_either:%=-l%]
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
#### Additional search directories for lib:
LPATH = $[alt_lpath]
#### Other linker flags.
#if $[ne $[alt_ld],]
LD = $[alt_ld]
#endif
# LDFLAGS =
#### Pull in standard .o make variables
include $(DTOOL)/inc/Makefile.o.vars
#### The .o action is here.
include $(DTOOL)/inc/Makefile.o.rules
#### Pull in standard binary make variables.
include $(DTOOL)/inc/Makefile.bin.vars
#### The .so action is here.
include $(DTOOL)/inc/Makefile.so.rules
#end Makefile.$[TARGET].so
#end metalib_target
//////////////////////////////////////////////////////////////////////
#elif $[eq $[DIR_TYPE], group]
//////////////////////////////////////////////////////////////////////
// This is a group directory: a directory above a collection of source
// directories, e.g. $DTOOL/src. We don't need to output anything in
// this directory.
//////////////////////////////////////////////////////////////////////
#elif $[eq $[DIR_TYPE], toplevel]
//////////////////////////////////////////////////////////////////////
// This is the toplevel directory, e.g. $DTOOL. Here we build the
// root makefile and also synthesize the dtool_config.h (or whichever
// file) we need.
#output Makefile
#format makefile
#### Generated automatically by $[PROGRAM] $[PROGVER] from $[SOURCEFILE].
################################# DO NOT EDIT ###########################
# Specify project name and project root directory.
CTPROJECT = $[PACKAGE]
CTPROJROOT = $($[upcase $[PACKAGE]])
include $(DTOOL)/inc/Makefile.project.vars
// Iterate through all of our known source files. Each src and
// metalib type file gets its corresponding Makefile.install listed
// here. However, we test for $[DIR_TYPE] of toplevel, because the
// source directories typically don't define their own DIR_TYPE
// variable, and they end up inheriting this one dynamically.
#forscopes */
#if $[or $[eq $[DIR_TYPE], src],$[eq $[DIR_TYPE], metalib],$[and $[eq $[DIR_TYPE], toplevel],$[ne $[DIRNAME],top]]]
#if $[build_directory]
include $[PATH]/Makefile.install
#endif
#endif
#end */
#end Makefile
// If there is a file called LocalSetup.pp in the package's top
// directory, then invoke that. It might contain some further setup
// instructions.
#sinclude $[TOPDIRPREFIX]LocalSetup.stopgap.pp
#sinclude $[TOPDIRPREFIX]LocalSetup.pp
//////////////////////////////////////////////////////////////////////
#endif // DIR_TYPE

39
ppremake/acconfig.h Normal file
View File

@@ -0,0 +1,39 @@
/* 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
/* Define if we're compiling for a Windows platform. */
#undef PLATFORM_WIN32
/* The current version number. */
#define VERSION 0.0
/* The platform ppremake is compiled for. This primarily controls the
initial setting of the $[PLATFORM] variable. */
#define PLATFORM ""
/* 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). */

405
ppremake/acinclude.m4 Normal file
View File

@@ -0,0 +1,405 @@
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 empty string if the library cannot be found.
AC_DEFUN(AC_SEARCH_LIB, [
ac_found_lib=""
for ac_check_dir in $1; do
if test "$ac_found_lib" = ""; then
AC_CHECK_LIB_LOC($ac_check_dir, $2, $3, [ ac_found_lib="$ac_check_dir"; ],, $5)
fi
done
$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 empty string if the header cannot be found.
AC_DEFUN(AC_SEARCH_HEADER, [
ac_found_header=""
for ac_check_dir in $1; do
if test "$ac_found_header" = ""; then
AC_CHECK_HEADER_LOC($ac_check_dir, $2, [ ac_found_header="$ac_check_dir";])
fi
done
$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=""
$6_INCLUDE=""
$6_PKG="no"
dnl Look for the library.
for ac_sp_dir in $1; do
if test "[$]$6_LIB" = ""; 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" = ""; 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" != ""; 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" = ""; then
for ac_sp_dir in $1; do
if test "[$]$6_INCLUDE" = ""; then
AC_SEARCH_HEADER("$ac_sp_dir" "$ac_sp_dir/include", $3, $6)
for ac_sp_pkg in $2; do
if test "[$]$6_INCLUDE" = ""; 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" != ""; then
$6_PKG="yes"
fi
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
])

76
ppremake/configure.in Normal file
View File

@@ -0,0 +1,76 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(ppremake.cxx)
AM_INIT_AUTOMAKE(ppremake, 0.25a)
AM_CONFIG_HEADER(config.h)
AC_PREFIX_DEFAULT(/usr/local/panda)
AC_PROG_MAKE_SET
AC_CANONICAL_HOST
# If we have a CFLAGS variable but not a CXXFLAGS variable, let them
# be the same.
if test "${CXXFLAGS+set}" != set -a "${CFLAGS+set}" = set; then
CXXFLAGS=$CFLAGS
fi
# Save these variables for later, so we can easily append to them or
# change them.
user_ldflags=${LDFLAGS-}
user_cflags=${CFLAGS-}
user_cxxflags=${CXXFLAGS-}
dnl Checks for programs.
AC_PROG_CC
AC_PROG_CXX
dnl First, we'll test for C-specific features.
AC_LANG_C
dnl Checks for libraries.
libdl=
libm=
AC_CHECK_LIB(m, sin, libm=-lm)
AC_SUBST(libm)
dnl Checks for header files.
AC_HEADER_STDC
AC_CHECK_HEADERS(malloc.h alloca.h unistd.h io.h minmax.h sys/types.h)
dnl Checks for typedefs, structures, and compiler characteristics.
dnl Checks for library functions.
AC_CHECK_FUNCS(getopt)
dnl Now we can test some C++-specific features.
AC_LANG_CPLUSPLUS
AC_HEADER_IOSTREAM
AC_NAMESPACE
AC_LANG_C
AC_ARG_WITH(platform,
[ --with-platform=platform Set the $[PLATFORM] predefined variable.])
if test "${with_platform-no}" != "no"; then
PLATFORM=$with_platform
else
case "$host_os" in
irix*) PLATFORM=Irix;;
linux*) PLATFORM=Linux;;
cygwin*) PLATFORM=Win32;;
*) echo "Cannot determine platform; use --with-platform=name."
exit 1;;
esac
fi
if test "$PLATFORM" = "Win32"; then
AC_DEFINE(PLATFORM_WIN32)
fi
AC_DEFINE_UNQUOTED(PLATFORM, "$PLATFORM")
AC_OUTPUT(Makefile)

View File

@@ -0,0 +1,22 @@
// Filename: find_searchpath.cxx
// Created by: drose (09Oct00)
//
////////////////////////////////////////////////////////////////////
#include "find_searchpath.h"
#include <unistd.h>
string
find_searchpath(const vector<string> &directories, const string &filename) {
vector<string>::const_iterator di;
for (di = directories.begin(); di != directories.end(); ++di) {
string path = (*di) + "/" + filename;
if (access(path.c_str(), F_OK) == 0) {
return path;
}
}
return string();
}

View File

@@ -0,0 +1,20 @@
// Filename: find_searchpath.h
// Created by: drose (09Oct00)
//
////////////////////////////////////////////////////////////////////
#ifndef FIND_SEARCHPATH_H
#define FIND_SEARCHPATH_H
#include "ppremake.h"
#include <vector>
// Searchs for the given filename along the indicated set of
// directories, and returns the first place in which it is found, or
// empty string if it is not found.
string find_searchpath(const vector<string> &directories,
const string &filename);
#endif

755
ppremake/gnu_getopt.c Normal file
View File

@@ -0,0 +1,755 @@
/* Getopt for GNU.
NOTE: getopt is now part of the C library, so if you don't know what
"Keep this file name-space clean" means, talk to roland@gnu.ai.mit.edu
before changing it!
Copyright (C) 1987, 88, 89, 90, 91, 92, 93, 94
Free Software Foundation, Inc.
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, 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. */
#include <ppremake.h>
#if !defined(HAVE_GETOPT)
#ifdef WIN32_VC
/* This file seems particularly egregious with this particular warning,
but it's not clear why. Disable. */
/* C4028: formal parameter N different from declaration */
#pragma warning (disable : 4028)
#endif
/* This tells Alpha OSF/1 not to define a getopt prototype in <stdio.h>.
Ditto for AIX 3.2 and <stdlib.h>. */
#ifndef _NO_PROTO
#define _NO_PROTO
#endif
#ifndef __STDC__
/* This is a separate conditional since some stdc systems
reject `defined (const)'. */
#ifndef const
#define const
#endif
#endif
#include <stdio.h>
#include <string.h>
/* Comment out all this code if we are using the GNU C Library, and are not
actually compiling the library itself. This code is part of the GNU C
Library, but also included in many other GNU distributions. Compiling
and linking in this code is a waste when using the GNU C library
(especially if it is a shared library). Rather than having every GNU
program understand `configure --with-gnu-libc' and omit the object files,
it is simpler to just do this in the source for each such file. */
#if defined (_LIBC) || !defined (__GNU_LIBRARY__)
/* This needs to come after some library #include
to get __GNU_LIBRARY__ defined. */
#ifdef __GNU_LIBRARY__
/* Don't include stdlib.h for non-GNU C libraries because some of them
contain conflicting prototypes for getopt. */
#include <stdlib.h>
#endif /* GNU C library. */
/* This version of `getopt' appears to the caller like standard Unix `getopt'
but it behaves differently for the user, since it allows the user
to intersperse the options with the other arguments.
As `getopt' works, it permutes the elements of ARGV so that,
when it is done, all the options precede everything else. Thus
all application programs are extended to handle flexible argument order.
Setting the environment variable POSIXLY_CORRECT disables permutation.
Then the behavior is completely standard.
GNU application programs can use a third alternative mode in which
they can distinguish the relative order of options and other arguments. */
#include "gnu_getopt.h"
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
char *optarg = NULL;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
/* XXX 1003.2 says this must be 1 before any call. */
int optind = 0;
/* The next char to be scanned in the option-element
in which the last option character we returned was found.
This allows us to pick up the scan where we left off.
If this is zero, or a null string, it means resume the scan
by advancing to the next ARGV-element. */
static char *nextchar;
/* Callers store zero here to inhibit the error message
for unrecognized options. */
int opterr = 1;
/* Set to an option character which was unrecognized.
This must be initialized on some systems to avoid linking in the
system's own getopt implementation. */
int optopt = '?';
/* Describe how to deal with options that follow non-option ARGV-elements.
If the caller did not specify anything,
the default is REQUIRE_ORDER if the environment variable
POSIXLY_CORRECT is defined, PERMUTE otherwise.
REQUIRE_ORDER means don't recognize them as options;
stop option processing when the first non-option is seen.
This is what Unix does.
This mode of operation is selected by either setting the environment
variable POSIXLY_CORRECT, or using `+' as the first character
of the list of option characters.
PERMUTE is the default. We permute the contents of ARGV as we scan,
so that eventually all the non-options are at the end. This allows options
to be given in any order, even with programs that were not written to
expect this.
RETURN_IN_ORDER is an option available to programs that were written
to expect options and other ARGV-elements in any order and that care about
the ordering of the two. We describe each non-option ARGV-element
as if it were the argument of an option with character code 1.
Using `-' as the first character of the list of option characters
selects this mode of operation.
The special argument `--' forces an end of option-scanning regardless
of the value of `ordering'. In the case of RETURN_IN_ORDER, only
`--' can cause `getopt' to return EOF with `optind' != ARGC. */
static enum
{
REQUIRE_ORDER, PERMUTE, RETURN_IN_ORDER
} ordering;
/* Value of POSIXLY_CORRECT environment variable. */
static char *posixly_correct;
#ifdef __GNU_LIBRARY__
/* We want to avoid inclusion of string.h with non-GNU libraries
because there are many ways it can cause trouble.
On some systems, it contains special magic macros that don't work
in GCC. */
#include <string.h>
#define my_index strchr
#else
/* Avoid depending on library functions or files
whose names are inconsistent. */
char *getenv ();
static char *
my_index (str, chr)
const char *str;
int chr;
{
while (*str)
{
if (*str == chr)
return (char *) str;
str++;
}
return 0;
}
/* If using GCC, we can safely declare strlen this way.
If not using GCC, it is ok not to declare it. */
#ifdef __GNUC__
/* Note that Motorola Delta 68k R3V7 comes with GCC but not stddef.h.
That was relevant to code that was here before. */
#ifndef __STDC__
/* gcc with -traditional declares the built-in strlen to return int,
and has done so at least since version 2.4.5. -- rms. */
extern int strlen (const char *);
#endif /* not __STDC__ */
#endif /* __GNUC__ */
#endif /* not __GNU_LIBRARY__ */
/* Handle permutation of arguments. */
/* Describe the part of ARGV that contains non-options that have
been skipped. `first_nonopt' is the index in ARGV of the first of them;
`last_nonopt' is the index after the last of them. */
static int first_nonopt;
static int last_nonopt;
/* Exchange two adjacent subsequences of ARGV.
One subsequence is elements [first_nonopt,last_nonopt)
which contains all the non-options that have been skipped so far.
The other is elements [last_nonopt,optind), which contains all
the options processed since those non-options were skipped.
`first_nonopt' and `last_nonopt' are relocated so that they describe
the new indices of the non-options in ARGV after they are moved. */
static void
exchange (argv)
char **argv;
{
int bottom = first_nonopt;
int middle = last_nonopt;
int top = optind;
char *tem;
/* Exchange the shorter segment with the far end of the longer segment.
That puts the shorter segment into the right place.
It leaves the longer segment in the right place overall,
but it consists of two parts that need to be swapped next. */
while (top > middle && middle > bottom)
{
if (top - middle > middle - bottom)
{
/* Bottom segment is the short one. */
int len = middle - bottom;
register int i;
/* Swap it with the top part of the top segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[top - (middle - bottom) + i];
argv[top - (middle - bottom) + i] = tem;
}
/* Exclude the moved bottom segment from further swapping. */
top -= len;
}
else
{
/* Top segment is the short one. */
int len = top - middle;
register int i;
/* Swap it with the bottom part of the bottom segment. */
for (i = 0; i < len; i++)
{
tem = argv[bottom + i];
argv[bottom + i] = argv[middle + i];
argv[middle + i] = tem;
}
/* Exclude the moved top segment from further swapping. */
bottom += len;
}
}
/* Update records for the slots the non-options now occupy. */
first_nonopt += (optind - last_nonopt);
last_nonopt = optind;
}
/* Initialize the internal data when the first call is made. */
static const char *
_getopt_initialize (optstring)
const char *optstring;
{
/* Start processing options with ARGV-element 1 (since ARGV-element 0
is the program name); the sequence of previously skipped
non-option ARGV-elements is empty. */
first_nonopt = last_nonopt = optind = 1;
nextchar = NULL;
posixly_correct = getenv ("POSIXLY_CORRECT");
/* Determine how to handle the ordering of options and nonoptions. */
if (optstring[0] == '-')
{
ordering = RETURN_IN_ORDER;
++optstring;
}
else if (optstring[0] == '+')
{
ordering = REQUIRE_ORDER;
++optstring;
}
else if (posixly_correct != NULL)
ordering = REQUIRE_ORDER;
else
ordering = PERMUTE;
return optstring;
}
/* Scan elements of ARGV (whose length is ARGC) for option characters
given in OPTSTRING.
If an element of ARGV starts with '-', and is not exactly "-" or "--",
then it is an option element. The characters of this element
(aside from the initial '-') are option characters. If `getopt'
is called repeatedly, it returns successively each of the option characters
from each of the option elements.
If `getopt' finds another option character, it returns that character,
updating `optind' and `nextchar' so that the next call to `getopt' can
resume the scan with the following option character or ARGV-element.
If there are no more option characters, `getopt' returns `EOF'.
Then `optind' is the index in ARGV of the first ARGV-element
that is not an option. (The ARGV-elements have been permuted
so that those that are not options now come last.)
OPTSTRING is a string containing the legitimate option characters.
If an option character is seen that is not listed in OPTSTRING,
return '?' after printing an error message. If you set `opterr' to
zero, the error message is suppressed but we still return '?'.
If a char in OPTSTRING is followed by a colon, that means it wants an arg,
so the following text in the same ARGV-element, or the text of the following
ARGV-element, is returned in `optarg'. Two colons mean an option that
wants an optional arg; if there is text in the current ARGV-element,
it is returned in `optarg', otherwise `optarg' is set to zero.
If OPTSTRING starts with `-' or `+', it requests different methods of
handling the non-option ARGV-elements.
See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
Long-named options begin with `--' instead of `-'.
Their names may be abbreviated as long as the abbreviation is unique
or is an exact match for some defined option. If they have an
argument, it follows the option name in the same ARGV-element, separated
from the option name by a `=', or else the in next ARGV-element.
When `getopt' finds a long-named option, it returns 0 if that option's
`flag' field is nonzero, the value of the option's `val' field
if the `flag' field is zero.
The elements of ARGV aren't really const, because we permute them.
But we pretend they're const in the prototype to be compatible
with other systems.
LONGOPTS is a vector of `struct option' terminated by an
element containing a name which is zero.
LONGIND returns the index in LONGOPT of the long-named option found.
It is only valid when a long-named option has been found by the most
recent call.
If LONG_ONLY is nonzero, '-' as well as '--' can introduce
long-named options. */
int
_getopt_internal (argc, argv, optstring, longopts, longind, long_only)
int argc;
char *const *argv;
const char *optstring;
const struct option *longopts;
int *longind;
int long_only;
{
optarg = NULL;
if (optind == 0)
optstring = _getopt_initialize (optstring);
if (nextchar == NULL || *nextchar == '\0')
{
/* Advance to the next ARGV-element. */
if (ordering == PERMUTE)
{
/* If we have just processed some options following some non-options,
exchange them so that the options come first. */
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (last_nonopt != optind)
first_nonopt = optind;
/* Skip any additional non-options
and extend the range of non-options previously skipped. */
while (optind < argc
&& (argv[optind][0] != '-' || argv[optind][1] == '\0'))
optind++;
last_nonopt = optind;
}
/* The special ARGV-element `--' means premature end of options.
Skip it like a null option,
then exchange with previous non-options as if it were an option,
then skip everything else like a non-option. */
if (optind != argc && !strcmp (argv[optind], "--"))
{
optind++;
if (first_nonopt != last_nonopt && last_nonopt != optind)
exchange ((char **) argv);
else if (first_nonopt == last_nonopt)
first_nonopt = optind;
last_nonopt = argc;
optind = argc;
}
/* If we have done all the ARGV-elements, stop the scan
and back over any non-options that we skipped and permuted. */
if (optind == argc)
{
/* Set the next-arg-index to point at the non-options
that we previously skipped, so the caller will digest them. */
if (first_nonopt != last_nonopt)
optind = first_nonopt;
return EOF;
}
/* If we have come to a non-option and did not permute it,
either stop the scan or describe it to the caller and pass it by. */
if ((argv[optind][0] != '-' || argv[optind][1] == '\0'))
{
if (ordering == REQUIRE_ORDER)
return EOF;
optarg = argv[optind++];
return 1;
}
/* We have found another option-ARGV-element.
Skip the initial punctuation. */
nextchar = (argv[optind] + 1
+ (longopts != NULL && argv[optind][1] == '-'));
}
/* Decode the current option-ARGV-element. */
/* Check whether the ARGV-element is a long option.
If long_only and the ARGV-element has the form "-f", where f is
a valid short option, don't consider it an abbreviated form of
a long option that starts with f. Otherwise there would be no
way to give the -f short option.
On the other hand, if there's a long option "fubar" and
the ARGV-element is "-fu", do consider that an abbreviation of
the long option, just like "--fu", and not "-f" with arg "u".
This distinction seems to be the most useful approach. */
if (longopts != NULL
&& (argv[optind][1] == '-'
|| (long_only && (argv[optind][2] || !my_index (optstring, argv[optind][1])))))
{
char *nameend;
const struct option *p;
const struct option *pfound = NULL;
int exact = 0;
int ambig = 0;
int indfound;
int option_index;
for (nameend = nextchar; *nameend && *nameend != '='; nameend++)
/* Do nothing. */ ;
/* Test all long options for either exact match
or abbreviated matches. */
for (p = longopts, option_index = 0; p->name; p++, option_index++)
if (!strncmp (p->name, nextchar, nameend - nextchar))
{
if (nameend - nextchar == (int) strlen (p->name))
{
/* Exact match found. */
pfound = p;
indfound = option_index;
exact = 1;
break;
}
else if (pfound == NULL)
{
/* First nonexact match found. */
pfound = p;
indfound = option_index;
}
else
/* Second or later nonexact match found. */
ambig = 1;
}
if (ambig && !exact)
{
if (opterr)
fprintf (stderr, "%s: option `%s' is ambiguous\n",
argv[0], argv[optind]);
nextchar += strlen (nextchar);
optind++;
return '?';
}
if (pfound != NULL)
{
option_index = indfound;
optind++;
if (*nameend)
{
/* Don't test has_arg with >, because some C compilers don't
allow it to be used on enums. */
if (pfound->has_arg)
optarg = nameend + 1;
else
{
if (opterr)
{
if (argv[optind - 1][1] == '-')
/* --option */
fprintf (stderr,
"%s: option `--%s' doesn't allow an argument\n",
argv[0], pfound->name);
else
/* +option or -option */
fprintf (stderr,
"%s: option `%c%s' doesn't allow an argument\n",
argv[0], argv[optind - 1][0], pfound->name);
}
nextchar += strlen (nextchar);
return '?';
}
}
else if (pfound->has_arg == 1)
{
if (optind < argc)
optarg = argv[optind++];
else
{
if (opterr)
fprintf (stderr, "%s: option `%s' requires an argument\n",
argv[0], argv[optind - 1]);
nextchar += strlen (nextchar);
return optstring[0] == ':' ? ':' : '?';
}
}
nextchar += strlen (nextchar);
if (longind != NULL)
*longind = option_index;
if (pfound->flag)
{
*(pfound->flag) = pfound->val;
return 0;
}
return pfound->val;
}
/* Can't find it as a long option. If this is not getopt_long_only,
or the option starts with '--' or is not a valid short
option, then it's an error.
Otherwise interpret it as a short option. */
if (!long_only || argv[optind][1] == '-'
|| my_index (optstring, *nextchar) == NULL)
{
if (opterr)
{
if (argv[optind][1] == '-')
/* --option */
fprintf (stderr, "%s: unrecognized option `--%s'\n",
argv[0], nextchar);
else
/* +option or -option */
fprintf (stderr, "%s: unrecognized option `%c%s'\n",
argv[0], argv[optind][0], nextchar);
}
nextchar = (char *) "";
optind++;
return '?';
}
}
/* Look at and handle the next short option-character. */
{
char c = *nextchar++;
char *temp = my_index (optstring, c);
/* Increment `optind' when we start to process its last character. */
if (*nextchar == '\0')
++optind;
if (temp == NULL || c == ':')
{
if (opterr)
{
if (posixly_correct)
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: illegal option -- %c\n", argv[0], c);
else
fprintf (stderr, "%s: invalid option -- %c\n", argv[0], c);
}
optopt = c;
return '?';
}
if (temp[1] == ':')
{
if (temp[2] == ':')
{
/* This is an option that accepts an argument optionally. */
if (*nextchar != '\0')
{
optarg = nextchar;
optind++;
}
else
optarg = NULL;
nextchar = NULL;
}
else
{
/* This is an option that requires an argument. */
if (*nextchar != '\0')
{
optarg = nextchar;
/* If we end this ARGV-element by taking the rest as an arg,
we must advance to the next element now. */
optind++;
}
else if (optind == argc)
{
if (opterr)
{
/* 1003.2 specifies the format of this message. */
fprintf (stderr, "%s: option requires an argument -- %c\n",
argv[0], c);
}
optopt = c;
if (optstring[0] == ':')
c = ':';
else
c = '?';
}
else
/* We already incremented `optind' once;
increment it again when taking next ARGV-elt as argument. */
optarg = argv[optind++];
nextchar = NULL;
}
}
return c;
}
}
int
getopt (argc, argv, optstring)
int argc;
char *const *argv;
const char *optstring;
{
return _getopt_internal (argc, argv, optstring,
(const struct option *) 0,
(int *) 0,
0);
}
#endif /* _LIBC or not __GNU_LIBRARY__. */
#ifdef TEST
/* Compile with -DTEST to make an executable for use in testing
the above definition of `getopt'. */
int
main (argc, argv)
int argc;
char **argv;
{
int c;
int digit_optind = 0;
while (1)
{
int this_option_optind = optind ? optind : 1;
c = getopt (argc, argv, "abc:d:0123456789");
if (c == EOF)
break;
switch (c)
{
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if (digit_optind != 0 && digit_optind != this_option_optind)
printf ("digits occur in two different argv-elements.\n");
digit_optind = this_option_optind;
printf ("option %c\n", c);
break;
case 'a':
printf ("option a\n");
break;
case 'b':
printf ("option b\n");
break;
case 'c':
printf ("option c with value `%s'\n", optarg);
break;
case '?':
break;
default:
printf ("?? getopt returned character code 0%o ??\n", c);
}
}
if (optind < argc)
{
printf ("non-option ARGV-elements: ");
while (optind < argc)
printf ("%s ", argv[optind++]);
printf ("\n");
}
exit (0);
}
#endif /* TEST */
#endif /* HAVE_GETOPT */

125
ppremake/gnu_getopt.h Normal file
View File

@@ -0,0 +1,125 @@
/* Declarations for getopt.
Copyright (C) 1989, 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
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, 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. */
#ifndef _GNU_GETOPT_H
#define _GNU_GETOPT_H 1
/* We don't want to collide with a system getopt() it if it exists.
Redefine our symbols accordingly. */
#define getopt gnu_getopt
#define optind gnu_optind
#define opterr gnu_opterr
#define optopt gnu_optopt
#define optarg gnu_optarg
#define getopt_long gnu_getopt_long
#define getopt_long_only gnu_getopt_long_only
#ifdef __cplusplus
extern "C" {
#endif
/* For communication from `getopt' to the caller.
When `getopt' finds an option that takes an argument,
the argument value is returned here.
Also, when `ordering' is RETURN_IN_ORDER,
each non-option ARGV-element is returned here. */
extern char EXPCL_DTOOL *optarg;
/* Index in ARGV of the next element to be scanned.
This is used for communication to and from the caller
and for communication between successive calls to `getopt'.
On entry to `getopt', zero means this is the first call; initialize.
When `getopt' returns EOF, this is the index of the first of the
non-option elements that the caller should itself scan.
Otherwise, `optind' communicates from one call to the next
how much of ARGV has been scanned so far. */
extern int EXPCL_DTOOL optind;
/* Callers store zero here to inhibit the error message `getopt' prints
for unrecognized options. */
extern int opterr;
/* Set to an option character which was unrecognized. */
extern int optopt;
/* Describe the long-named options requested by the application.
The LONG_OPTIONS argument to getopt_long or getopt_long_only is a vector
of `struct option' terminated by an element containing a name which is
zero.
The field `has_arg' is:
no_argument (or 0) if the option does not take an argument,
required_argument (or 1) if the option requires an argument,
optional_argument (or 2) if the option takes an optional argument.
If the field `flag' is not NULL, it points to a variable that is set
to the value given in the field `val' when the option is found, but
left unchanged if the option is not found.
To have a long-named option do something other than set an `int' to
a compiled-in constant, such as set a value from `optarg', set the
option's `flag' field to zero and its `val' field to a nonzero
value (the equivalent single-letter option character, if there is
one). For long options that have a zero `flag' field, `getopt'
returns the contents of the `val' field. */
struct option
{
#if __STDC__
const char *name;
#else
char *name;
#endif
/* has_arg can't be an enum because some compilers complain about
type mismatches in all the code that assumes it is an int. */
int has_arg;
int *flag;
int val;
};
/* Names for the values of the `has_arg' field of `struct option'. */
#define no_argument 0
#define required_argument 1
#define optional_argument 2
extern EXPCL_DTOOL int
getopt (int argc, char *const *argv, const char *shortopts);
extern EXPCL_DTOOL int
getopt_long (int argc, char *const *argv, const char *shortopts,
const struct option *long_options, int *opt_index);
extern EXPCL_DTOOL int
getopt_long_only (int argc, char *const *argv,
const char *shortopts,
const struct option *long_options,
int *opt_index);
/* Internal only. Users should not call this directly. */
extern int _getopt_internal (int argc, char *const *argv,
const char *shortopts,
const struct option *longopts, int *longind,
int long_only);
#ifdef __cplusplus
}
#endif
#endif /* _GETOPT_H */

1365
ppremake/ppCommandFile.cxx Normal file

File diff suppressed because it is too large Load Diff

153
ppremake/ppCommandFile.h Normal file
View File

@@ -0,0 +1,153 @@
// Filename: ppCommandFile.h
// Created by: drose (25Sep00)
//
////////////////////////////////////////////////////////////////////
#ifndef PPCOMMANDFILE_H
#define PPCOMMANDFILE_H
#include "ppremake.h"
#include <map>
#include <vector>
class PPScope;
///////////////////////////////////////////////////////////////////
// Class : PPCommandFile
// Description : This encapsulates a file that contains #commands to
// execute (like #define, #if, #begin .. #end),
// $[variables] to expand, and plain text to output.
////////////////////////////////////////////////////////////////////
class PPCommandFile {
public:
PPCommandFile(PPScope *scope);
~PPCommandFile();
void set_scope(PPScope *scope);
PPScope *get_scope() const;
bool read_file(const string &filename);
bool read_stream(istream &in);
void begin_read();
bool read_line(string line);
bool end_read();
protected:
bool handle_command(const string &line);
bool handle_if_command();
bool handle_elif_command();
bool handle_else_command();
bool handle_endif_command();
bool handle_begin_command();
bool handle_forscopes_command();
bool handle_foreach_command();
bool handle_format_command();
bool handle_output_command();
bool handle_defsub_command();
bool handle_end_command();
bool handle_include_command();
bool handle_sinclude_command();
bool handle_call_command();
bool handle_error_command();
bool handle_defer_command();
bool handle_define_command();
bool handle_set_command();
bool handle_map_command();
bool include_file(const string &filename);
bool replay_forscopes(const string &name);
bool replay_foreach(const string &varname, const vector<string> &words);
bool compare_output(const string &temp_name, const string &true_name);
bool failed_if() const;
private:
class PushFilename {
public:
PushFilename(PPScope *scope, const string &filename);
~PushFilename();
PPScope *_scope;
string _old_thisdirprefix;
string _old_thisfilename;
};
private:
PPScope *_native_scope;
PPScope *_scope;
enum IfState {
IS_on, // e.g. a passed #if
IS_else, // after matching an #else
IS_off, // e.g. a failed #if
IS_done // e.g. after reaching an #else or #elif for a passed #if.
};
class IfNesting {
public:
IfState _state;
IfNesting *_next;
};
enum BlockState {
BS_begin,
BS_forscopes,
BS_nested_forscopes,
BS_foreach,
BS_nested_foreach,
BS_defsub,
BS_output
};
enum WriteFormat {
WF_straight, // write lines directly as they come in
WF_collapse, // collapse out consecutive blank lines
WF_makefile // fancy makefile formatting
};
class WriteState {
public:
WriteState();
WriteState(const WriteState &copy);
bool write_line(const string &line);
bool write_collapse_line(const string &line);
bool write_makefile_line(const string &line);
ostream *_out;
WriteFormat _format;
bool _last_blank;
};
class BlockNesting {
public:
BlockState _state;
string _name;
WriteState *_write_state;
PPScope *_scope;
string _true_name;
char *_tempnam;
ofstream _output;
vector<string> _words;
BlockNesting *_next;
};
bool _got_command;
bool _in_for;
IfNesting *_if_nesting;
BlockNesting *_block_nesting;
string _command;
string _params;
WriteState *_write_state;
vector<string> _saved_lines;
friend PPCommandFile::IfNesting;
friend PPCommandFile::WriteState;
friend PPCommandFile::BlockNesting;
};
#endif

View File

@@ -0,0 +1,550 @@
// Filename: ppDirectoryTree.cxx
// Created by: drose (28Sep00)
//
////////////////////////////////////////////////////////////////////
#include "ppDirectoryTree.h"
#include "ppScope.h"
#include "ppNamedScopes.h"
#include "ppCommandFile.h"
#include "tokenize.h"
#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
#include <algorithm>
PPDirectoryTree *current_output_directory = (PPDirectoryTree *)NULL;
// An STL object to sort directories in order by dependency and then
// by name, used in get_child_dirnames().
class SortDirectoriesByDependencyAndName {
public:
bool operator () (const PPDirectoryTree *a, const PPDirectoryTree *b) const {
if (a->get_depends_index() != b->get_depends_index()) {
return a->get_depends_index() < b->get_depends_index();
}
return a->get_dirname() < b->get_dirname();
}
};
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::Constructor
// Access: Public
// Description: Creates the root level of the PPDirectoryTree.
////////////////////////////////////////////////////////////////////
PPDirectoryTree::
PPDirectoryTree() {
_scope = (PPScope *)NULL;
_source = (PPCommandFile *)NULL;
_parent = (PPDirectoryTree *)NULL;
_depth = 0;
_depends_index = 0;
_computing_depends_index = false;
_dirnames = new Dirnames;
_dirname = "top";
(*_dirnames).insert(Dirnames::value_type(_dirname, this));
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::Destructor
// Access: Public
// Description: When a tree root destructs, all of its children are
// also destroyed.
////////////////////////////////////////////////////////////////////
PPDirectoryTree::
~PPDirectoryTree() {
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
delete (*ci);
}
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::Constructor
// Access: Protected
// Description: Creates a new directory level that automatically adds
// itself to its parent's children list.
////////////////////////////////////////////////////////////////////
PPDirectoryTree::
PPDirectoryTree(const string &dirname, PPDirectoryTree *parent) :
_dirname(dirname),
_parent(parent)
{
assert(_parent != (PPDirectoryTree *)NULL);
_scope = (PPScope *)NULL;
_source = (PPCommandFile *)NULL;
_parent->_children.push_back(this);
_depth = _parent->_depth + 1;
_depends_index = 0;
_computing_depends_index = false;
_dirnames = _parent->_dirnames;
bool inserted =
(*_dirnames).insert(Dirnames::value_type(_dirname, this)).second;
if (!inserted) {
cerr << "Warning: multiple directories encountered named "
<< _dirname << "\n";
}
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::scan
// Access: Public
// Description: Reads in the complete hierarchy of source files.
// prefix is the pathname to the directory on disk,
// ending in slash.
////////////////////////////////////////////////////////////////////
bool PPDirectoryTree::
scan(const string &prefix, PPNamedScopes *named_scopes) {
if (!r_scan(prefix)) {
return false;
}
if (!read_source_file(prefix, named_scopes)) {
return false;
}
if (!read_depends_file(named_scopes)) {
return false;
}
if (!resolve_dependencies()) {
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::count_source_files
// Access: Public
// Description: Returns the number of directories within the tree
// that actually have a Sources.pp file that was read.
////////////////////////////////////////////////////////////////////
int PPDirectoryTree::
count_source_files() const {
int count = 0;
if (_source != (PPCommandFile *)NULL) {
count++;
}
Children::const_iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
count += (*ci)->count_source_files();
}
return count;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::get_dirname
// Access: Public
// Description: Returns the name of this particular directory level.
////////////////////////////////////////////////////////////////////
const string &PPDirectoryTree::
get_dirname() const {
return _dirname;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::get_depends_index
// Access: Public
// Description: Returns the dependency index associated with this
// directory. It is generally true that if directory A
// depends on B, then A.get_depends_index() >
// B.get_depends_index().
////////////////////////////////////////////////////////////////////
int PPDirectoryTree::
get_depends_index() const {
return _depends_index;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::get_path
// Access: Public
// Description: Returns the relative path from the root to this
// particular directory. This does not include the root
// name itself, and does not include a trailing slash.
////////////////////////////////////////////////////////////////////
string PPDirectoryTree::
get_path() const {
if (_parent == (PPDirectoryTree *)NULL) {
return ".";
}
if (_parent->_parent == (PPDirectoryTree *)NULL) {
return _dirname;
}
return _parent->get_path() + "/" + _dirname;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::get_rel_to
// Access: Public
// Description: Returns the relative path to the other directory from
// this one. This does not include a trailing slash.
////////////////////////////////////////////////////////////////////
string PPDirectoryTree::
get_rel_to(const PPDirectoryTree *other) const {
const PPDirectoryTree *a = this;
const PPDirectoryTree *b = other;
if (a == b) {
return ".";
}
string prefix, postfix;
while (a->_depth > b->_depth) {
prefix += "../";
a = a->_parent;
assert(a != (PPDirectoryTree *)NULL);
}
while (b->_depth > a->_depth) {
postfix = b->_dirname + "/" + postfix;
b = b->_parent;
assert(b != (PPDirectoryTree *)NULL);
}
while (a != b) {
prefix += "../";
postfix = b->_dirname + "/" + postfix;
a = a->_parent;
b = b->_parent;
assert(a != (PPDirectoryTree *)NULL);
assert(b != (PPDirectoryTree *)NULL);
}
string result = prefix + postfix;
assert(!result.empty());
return result.substr(0, result.length() - 1);
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::find_dirname
// Access: Public
// Description: Searches for the first subdirectory found with the
// matching dirname. This is just the name of the
// directory itself, not the relative path to the
// directory.
////////////////////////////////////////////////////////////////////
PPDirectoryTree *PPDirectoryTree::
find_dirname(const string &dirname) {
assert(_dirnames != (Dirnames *)NULL);
Dirnames::const_iterator di;
di = _dirnames->find(dirname);
if (di != _dirnames->end()) {
return (*di).second;
}
// No such dirname; too bad.
return (PPDirectoryTree *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::get_source
// Access: Public
// Description: Returns the source file associated with this level
// of the directory hierarchy. This *might* be NULL.
////////////////////////////////////////////////////////////////////
PPCommandFile *PPDirectoryTree::
get_source() const {
return _source;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::get_num_children
// Access: Public
// Description: Returns the number of subdirectories below this
// level.
////////////////////////////////////////////////////////////////////
int PPDirectoryTree::
get_num_children() const {
return _children.size();
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::get_child
// Access: Public
// Description: Returns the nth subdirectory below this level.
////////////////////////////////////////////////////////////////////
PPDirectoryTree *PPDirectoryTree::
get_child(int n) const {
assert(n >= 0 && n < (int)_children.size());
return _children[n];
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::get_child_dirnames
// Access: Public
// Description: Returns a single string listing the names of all the
// subdirectories of this level, delimited by spaces.
//
// The list is sorted in dependency order such that a
// directory is listed after the other directories it
// might depend on.
////////////////////////////////////////////////////////////////////
string PPDirectoryTree::
get_child_dirnames() const {
Children copy_children = _children;
sort(copy_children.begin(), copy_children.end(),
SortDirectoriesByDependencyAndName());
vector<string> words;
Children::const_iterator ci;
for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
words.push_back((*ci)->get_dirname());
}
string result = repaste(words, " ");
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::get_complete_subtree
// Access: Public
// Description: Returns a single string listing the relative path
// from the source root to each source directory at this
// level and below, delimited by spaces.
////////////////////////////////////////////////////////////////////
string PPDirectoryTree::
get_complete_subtree() const {
Children copy_children = _children;
sort(copy_children.begin(), copy_children.end(),
SortDirectoriesByDependencyAndName());
vector<string> words;
words.push_back(get_path());
Children::const_iterator ci;
for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
words.push_back((*ci)->get_complete_subtree());
}
string result = repaste(words, " ");
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::r_scan
// Access: Private
// Description: The recursive implementation of scan().
////////////////////////////////////////////////////////////////////
bool PPDirectoryTree::
r_scan(const string &prefix) {
string root_name = ".";
if (!prefix.empty()) {
root_name = prefix.substr(0, prefix.length() - 1);
}
DIR *root = opendir(root_name.c_str());
if (root == (DIR *)NULL) {
cerr << "Unable to scan directory " << root_name << "\n";
return false;
}
struct dirent *d;
d = readdir(root);
while (d != (struct dirent *)NULL) {
string dirname = d->d_name;
if (!dirname.empty() && dirname[0] != '.') {
// Do we have a source file in this subdirectory (if it is a
// subdirectory)?
string next_prefix = prefix + dirname + "/";
string source_filename = next_prefix + SOURCE_FILENAME;
if (access(source_filename.c_str(), F_OK) == 0) {
PPDirectoryTree *subtree = new PPDirectoryTree(dirname, this);
if (!subtree->r_scan(next_prefix)) {
return false;
}
}
}
d = readdir(root);
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::read_source_file
// Access: Private
// Description: Recursively reads in the source file at each level,
// if defined.
////////////////////////////////////////////////////////////////////
bool PPDirectoryTree::
read_source_file(const string &prefix, PPNamedScopes *named_scopes) {
string source_filename = prefix + SOURCE_FILENAME;
ifstream in(source_filename.c_str());
if (in) {
// cerr << "Reading " << source_filename << "\n";
named_scopes->set_current(_dirname);
_scope = named_scopes->make_scope("");
_scope->define_variable("SOURCEFILE", SOURCE_FILENAME);
_scope->define_variable("DIRNAME", _dirname);
_scope->define_variable("DIRPREFIX", prefix);
_scope->define_variable("PATH", get_path());
_scope->define_variable("SUBDIRS", get_child_dirnames());
_scope->define_variable("SUBTREE", get_complete_subtree());
_scope->set_directory(this);
_source = new PPCommandFile(_scope);
if (!_source->read_stream(in)) {
cerr << "Error when reading " << source_filename << "\n";
return false;
}
}
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
if (!(*ci)->read_source_file(prefix + (*ci)->get_dirname() + "/",
named_scopes)) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::read_depends_file
// Access: Private
// Description: Recursively reads in the dependency definition file
// for each source file.
////////////////////////////////////////////////////////////////////
bool PPDirectoryTree::
read_depends_file(PPNamedScopes *named_scopes) {
if (_scope != (PPScope *)NULL) {
// Read the depends file, so we can determine the relationship
// between this source file and all of the other source files.
string depends_filename = _scope->expand_variable("DEPENDS_FILE");
if (depends_filename.empty()) {
cerr << "No definition given for $[DEPENDS_FILE], cannot process.\n";
return false;
}
named_scopes->set_current(_dirname);
PPCommandFile depends(_scope);
if (!depends.read_file(depends_filename)) {
cerr << "Error reading dependency definition file "
<< depends_filename << ".\n";
return false;
}
// This should have defined the variable DEPENDS, which lists the
// various dirnames this source file depends on.
vector<string> dirnames;
tokenize_whitespace(_scope->expand_variable("DEPENDS"), dirnames);
vector<string>::const_iterator ni;
for (ni = dirnames.begin(); ni != dirnames.end(); ++ni) {
const string &dirname = (*ni);
PPDirectoryTree *dir = find_dirname(dirname);
if (dir == (PPDirectoryTree *)NULL) {
cerr << "Could not find dependent dirname " << dirname << "\n";
} else {
if (dir != this) {
_i_depend_on.insert(dir);
dir->_depends_on_me.insert(this);
}
}
}
}
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
if (!(*ci)->read_depends_file(named_scopes)) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::resolve_dependencies
// Access: Private
// Description: Visits each directory and assigns a correct
// _depends_index to each one, such that if directory A
// depends on directory B then A._depends_index >
// B._depends_index.
//
// This also detects cycles in the directory dependency
// graph.
////////////////////////////////////////////////////////////////////
bool PPDirectoryTree::
resolve_dependencies() {
if (!compute_depends_index()) {
return false;
}
Children::iterator ci;
for (ci = _children.begin(); ci != _children.end(); ++ci) {
if (!(*ci)->resolve_dependencies()) {
return false;
}
}
// Now that we've resolved all of our children's dependencies,
// redefine our SUBDIRS and SUBTREE variables to put things in the
// right order.
if (_scope != (PPScope *)NULL) {
_scope->define_variable("SUBDIRS", get_child_dirnames());
_scope->define_variable("SUBTREE", get_complete_subtree());
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::compute_depends_index
// Access: Private
// Description: Computes the dependency score for a particular
// directory. See resolve_dependencies().
////////////////////////////////////////////////////////////////////
bool PPDirectoryTree::
compute_depends_index() {
if (_depends_index != 0) {
return true;
}
if (_i_depend_on.empty()) {
_depends_index = 1;
return true;
}
_computing_depends_index = true;
int max_index = 0;
Depends::iterator di;
for (di = _i_depend_on.begin(); di != _i_depend_on.end(); ++di) {
if ((*di)->_computing_depends_index) {
// Oops, we have a cycle!
cerr << "Cycle detected in inter-directory dependencies!\n"
<< _dirname << " depends on " << (*di)->_dirname << "\n";
return false;
}
if (!(*di)->compute_depends_index()) {
// Keep reporting the cycle as we unroll the recursion.
cerr << _dirname << " depends on " << (*di)->_dirname << "\n";
return false;
}
max_index = max(max_index, (*di)->_depends_index);
}
_computing_depends_index = false;
_depends_index = max_index + 1;
return true;
}

View File

@@ -0,0 +1,83 @@
// Filename: ppDirectoryTree.h
// Created by: drose (28Sep00)
//
////////////////////////////////////////////////////////////////////
#ifndef PPDIRECTORYTREE_H
#define PPDIRECTORYTREE_H
#include "ppremake.h"
#include <vector>
#include <map>
#include <set>
class PPCommandFile;
class PPScope;
class PPNamedScopes;
///////////////////////////////////////////////////////////////////
// Class : PPDirectoryTree
// Description : Stores the directory hierarchy relationship of the
// source tree. Each PPDirectoryTree object is
// one-to-one associated with a PPCommandFile object,
// that corresponds to the source file found within this
// directory.
////////////////////////////////////////////////////////////////////
class PPDirectoryTree {
public:
PPDirectoryTree();
~PPDirectoryTree();
protected:
PPDirectoryTree(const string &dirname, PPDirectoryTree *parent);
public:
bool scan(const string &prefix, PPNamedScopes *named_scopes);
int count_source_files() const;
const string &get_dirname() const;
int get_depends_index() const;
string get_path() const;
string get_rel_to(const PPDirectoryTree *other) const;
PPDirectoryTree *find_dirname(const string &dirname);
PPCommandFile *get_source() const;
int get_num_children() const;
PPDirectoryTree *get_child(int n) const;
string get_child_dirnames() const;
string get_complete_subtree() const;
private:
bool r_scan(const string &prefix);
bool read_source_file(const string &prefix, PPNamedScopes *named_scopes);
bool read_depends_file(PPNamedScopes *named_scopes);
bool resolve_dependencies();
bool compute_depends_index();
string _dirname;
PPScope *_scope;
PPCommandFile *_source;
PPDirectoryTree *_parent;
typedef vector<PPDirectoryTree *> Children;
Children _children;
int _depth;
typedef set<PPDirectoryTree *> Depends;
Depends _i_depend_on;
Depends _depends_on_me;
int _depends_index;
bool _computing_depends_index;
typedef map<string, PPDirectoryTree *> Dirnames;
Dirnames *_dirnames;
};
extern PPDirectoryTree *current_output_directory;
#endif

View File

@@ -0,0 +1,176 @@
// Filename: ppFilenamePattern.cxx
// Created by: drose (25Sep00)
//
////////////////////////////////////////////////////////////////////
#include "ppFilenamePattern.h"
#include <assert.h>
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PPFilenamePattern::
PPFilenamePattern(const string &pattern) {
size_t pct = pattern.find(PATTERN_WILDCARD);
_has_wildcard = (pct != string::npos);
if (_has_wildcard) {
_prefix = pattern.substr(0, pct);
_suffix = pattern.substr(pct + 1);
} else {
_prefix = pattern;
}
}
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::Copy Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PPFilenamePattern::
PPFilenamePattern(const PPFilenamePattern &copy) :
_has_wildcard(copy._has_wildcard),
_prefix(copy._prefix),
_suffix(copy._suffix)
{
}
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::Copy Assignment Operator
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
void PPFilenamePattern::
operator = (const PPFilenamePattern &copy) {
_has_wildcard = copy._has_wildcard;
_prefix = copy._prefix;
_suffix = copy._suffix;
}
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::has_wildcard
// Access: Public
// Description: Returns true if the filename pattern contained a
// wildcard (and hence represents a pattern and not
// just a single particular filename), or false if it
// did not.
////////////////////////////////////////////////////////////////////
bool PPFilenamePattern::
has_wildcard() const {
return _has_wildcard;
}
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::get_pattern
// Access: Public
// Description: Returns the filename pattern.
////////////////////////////////////////////////////////////////////
string PPFilenamePattern::
get_pattern() const {
if (_has_wildcard) {
return _prefix + PATTERN_WILDCARD + _suffix;
} else {
return _prefix;
}
}
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::get_prefix
// Access: Public
// Description: Returns the part of the filename pattern before the
// wildcard. If the filename did not contain a
// wildcard, this returns the entire filename.
////////////////////////////////////////////////////////////////////
const string &PPFilenamePattern::
get_prefix() const {
return _prefix;
}
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::get_suffix
// Access: Public
// Description: Returns the part of the filename pattern after the
// wildcard. If the filename did not contain a
// wildcard, this returns the empty string.
////////////////////////////////////////////////////////////////////
const string &PPFilenamePattern::
get_suffix() const {
return _suffix;
}
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::matches_filename
// Access: Public
// Description: Returns true if the given filename matches the
// pattern, false otherwise.
////////////////////////////////////////////////////////////////////
bool PPFilenamePattern::
matches(const string &filename) const {
if (_has_wildcard) {
return
(filename.length() >= _prefix.length() + _suffix.length()) &&
(filename.substr(0, _prefix.length()) == _prefix) &&
(filename.substr(filename.length() - _suffix.length()) == _suffix);
} else {
return (filename == _prefix);
}
}
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::extract_body
// Access: Public
// Description: If the filename matches the pattern
// (e.g. matches_filename() returns true), return the
// portion of the filename that corresponds to the
// wildcard in the pattern: the part of the filename
// between the prefix and the suffix. If the filename
// does not match the pattern, or the pattern does not
// contain a wildcard, returns empty string.
////////////////////////////////////////////////////////////////////
string PPFilenamePattern::
extract_body(const string &filename) const {
if (_has_wildcard) {
size_t outside_length = _prefix.length() + _suffix.length();
if ((filename.length() >= outside_length) &&
(filename.substr(0, _prefix.length()) == _prefix) &&
(filename.substr(filename.length() - _suffix.length()) == _suffix)) {
return filename.substr(_prefix.length(), filename.length() - outside_length);
}
}
return string();
}
////////////////////////////////////////////////////////////////////
// Function: PPFilenamePattern::transform_filename
// Access: Public
// Description: Transforms a filename by replacing the parts of the
// filename described in the pattern transform_from with
// the corresponding parts of the filename described in
// this pattern. If the filename does not match
// transform_from, returns the untransformed filename.
//
// It is an error to call this unless both this pattern
// and transform_from include a wildcard.
////////////////////////////////////////////////////////////////////
string PPFilenamePattern::
transform(const string &filename,
const PPFilenamePattern &transform_from) const {
assert(transform_from._has_wildcard);
if (transform_from.matches(filename)) {
if (!_has_wildcard) {
return _prefix;
} else {
string body = transform_from.extract_body(filename);
return _prefix + body + _suffix;
}
}
return filename;
}

View File

@@ -0,0 +1,45 @@
// Filename: ppFilenamePattern.h
// Created by: drose (25Sep00)
//
////////////////////////////////////////////////////////////////////
#ifndef PPFILENAMEPATTERN_H
#define PPFILENAMEPATTERN_H
#include "ppremake.h"
///////////////////////////////////////////////////////////////////
// Class : PPFilenamePattern
// Description : This is a string that represents a filename, or a
// family of filenames, using the make convention that a
// wildcard sign (PATTERN_WILDCARD, typically '%') in
// the filename represents any sequence of characters.
////////////////////////////////////////////////////////////////////
class PPFilenamePattern {
public:
PPFilenamePattern(const string &pattern);
PPFilenamePattern(const PPFilenamePattern &copy);
void operator = (const PPFilenamePattern &copy);
bool has_wildcard() const;
string get_pattern() const;
const string &get_prefix() const;
const string &get_suffix() const;
bool matches(const string &filename) const;
string extract_body(const string &filename) const;
string transform(const string &filename,
const PPFilenamePattern &transform_from) const;
private:
bool _has_wildcard;
string _prefix;
string _suffix;
};
inline ostream &
operator << (ostream &out, const PPFilenamePattern &pattern) {
return out << pattern.get_pattern();
}
#endif

193
ppremake/ppMain.cxx Normal file
View File

@@ -0,0 +1,193 @@
// Filename: ppMain.cxx
// Created by: drose (28Sep00)
//
////////////////////////////////////////////////////////////////////
#include "ppMain.h"
#include "ppScope.h"
#include "ppCommandFile.h"
#include <unistd.h>
////////////////////////////////////////////////////////////////////
// Function: PPMain::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PPMain::
PPMain(PPScope *global_scope) {
_global_scope = global_scope;
PPScope::push_scope(_global_scope);
_def_scope = (PPScope *)NULL;
_defs = (PPCommandFile *)NULL;
}
////////////////////////////////////////////////////////////////////
// Function: PPMain::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PPMain::
~PPMain() {
if (_def_scope != (PPScope *)NULL) {
delete _def_scope;
}
if (_defs != (PPCommandFile *)NULL) {
delete _defs;
}
}
////////////////////////////////////////////////////////////////////
// Function: PPMain::read_source
// Access: Public
// Description: Reads the directory hierarchy of Sources.pp files, at
// the indicated directory and below.
////////////////////////////////////////////////////////////////////
bool PPMain::
read_source(const string &root) {
// First, read the package file. We find this either in this
// directory, or in some directory above us.
string search = root + "/";
if (root == ".") {
search = "";
}
string package_file = search + PACKAGE_FILENAME;
while (access(package_file.c_str(), F_OK) != 0) {
// We continue to walk up directories as long as we see a source
// file in each directory. When we stop seeing source files, we
// stop walking upstairs.
string source_file = search + SOURCE_FILENAME;
if (access(source_file.c_str(), F_OK) != 0) {
cerr << "Could not find ppremake package file " << PACKAGE_FILENAME
<< ".\n\n"
<< "This file should be present in the top of the source directory tree;\n"
<< "it defines implementation-specific variables to control the output\n"
<< "of ppremake, as well as pointing out the installed location of\n"
<< "important ppremake config files.\n\n";
return false;
}
search += "../";
package_file = search + PACKAGE_FILENAME;
}
_def_scope = new PPScope(&_named_scopes);
_def_scope->define_variable("PACKAGEFILE", package_file);
_def_scope->define_variable("TOPDIRPREFIX", search);
_defs = new PPCommandFile(_def_scope);
// cerr << "Reading " << package_file << "\n";
if (!_defs->read_file(package_file)) {
cerr << "Error reading package file " << package_file << ".\n";
return false;
}
PPScope::push_scope(_def_scope);
if (!_tree.scan(search, &_named_scopes)) {
return false;
}
_def_scope->define_variable("TREE", _tree.get_complete_subtree());
if (_tree.count_source_files() == 0) {
cerr << "Could not find any source definition files named " << SOURCE_FILENAME
<< ".\n\n"
<< "A file by this name should be present in each directory of the source\n"
<< "hierarchy; it defines the source files and targets that should be\n"
<< "built in each directory, as well as the relationships between the\n"
<< "directories.\n\n";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPMain::process_all
// Access: Public
// Description: Does all the processing on all known directories.
// See process().
////////////////////////////////////////////////////////////////////
bool PPMain::
process_all() {
return r_process_all(&_tree);
}
////////////////////////////////////////////////////////////////////
// Function: PPMain::process
// Access: Public
// Description: Does the processing associated with the source file
// in the indicated subdirectory name. This involves
// reading in the template file and generating whatever
// output the template file indicates.
////////////////////////////////////////////////////////////////////
bool PPMain::
process(const string &dirname) {
PPDirectoryTree *dir = _tree.find_dirname(dirname);
if (dir == (PPDirectoryTree *)NULL) {
cerr << "Unknown directory: " << dirname << "\n";
return false;
}
if (dir->get_source() == (PPCommandFile *)NULL) {
cerr << "No source file in " << dirname << "\n";
return false;
}
return p_process(dir);
}
////////////////////////////////////////////////////////////////////
// Function: PPMain::r_process_all
// Access: Private
// Description: The recursive implementation of process_all().
////////////////////////////////////////////////////////////////////
bool PPMain::
r_process_all(PPDirectoryTree *dir) {
if (dir->get_source() != (PPCommandFile *)NULL) {
if (!p_process(dir)) {
return false;
}
}
int num_children = dir->get_num_children();
for (int i = 0; i < num_children; i++) {
if (!r_process_all(dir->get_child(i))) {
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPMain::p_process
// Access: Private
// Description: The private implementation of process().
////////////////////////////////////////////////////////////////////
bool PPMain::
p_process(PPDirectoryTree *dir) {
current_output_directory = dir;
_named_scopes.set_current(dir->get_dirname());
PPCommandFile *source = dir->get_source();
assert(source != (PPCommandFile *)NULL);
PPScope *scope = source->get_scope();
string template_filename = scope->expand_variable("TEMPLATE_FILE");
if (template_filename.empty()) {
cerr << "No definition given for $[TEMPLATE_FILE], cannot process.\n";
return false;
}
PPCommandFile template_file(scope);
if (!template_file.read_file(template_filename)) {
cerr << "Error reading template file " << template_filename << ".\n";
return false;
}
return true;
}

47
ppremake/ppMain.h Normal file
View File

@@ -0,0 +1,47 @@
// Filename: ppMain.h
// Created by: drose (28Sep00)
//
////////////////////////////////////////////////////////////////////
#ifndef PPMAIN_H
#define PPMAIN_H
#include "ppremake.h"
#include "ppDirectoryTree.h"
#include "ppNamedScopes.h"
class PPScope;
class PPCommandFile;
///////////////////////////////////////////////////////////////////
// Class : PPMain
// Description : Handles the toplevel processing in this program:
// holds the tree of source files, and all the scopes,
// etc. Generally get the ball rolling.
////////////////////////////////////////////////////////////////////
class PPMain {
public:
PPMain(PPScope *global_scope);
~PPMain();
bool read_source(const string &root);
bool process_all();
bool process(const string &dirname);
private:
bool r_process_all(PPDirectoryTree *dir);
bool p_process(PPDirectoryTree *dir);
PPScope *_global_scope;
PPScope *_def_scope;
PPCommandFile *_defs;
PPDirectoryTree _tree;
PPNamedScopes _named_scopes;
PPScope *_parent_scope;
};
#endif

112
ppremake/ppNamedScopes.cxx Normal file
View File

@@ -0,0 +1,112 @@
// Filename: ppNamedScopes.cxx
// Created by: drose (27Sep00)
//
////////////////////////////////////////////////////////////////////
#include "ppNamedScopes.h"
#include "ppScope.h"
////////////////////////////////////////////////////////////////////
// Function: PPNamedScopes::Constructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PPNamedScopes::
PPNamedScopes() {
}
////////////////////////////////////////////////////////////////////
// Function: PPNamedScopes::Destructor
// Access: Public
// Description:
////////////////////////////////////////////////////////////////////
PPNamedScopes::
~PPNamedScopes() {
}
////////////////////////////////////////////////////////////////////
// Function: PPNamedScopes::make_scope
// Access: Public
// Description: Creates a new scope in the current directory name
// with the indicated scope name.
////////////////////////////////////////////////////////////////////
PPScope *PPNamedScopes::
make_scope(const string &name) {
PPScope *scope = new PPScope(this);
_directories[_current][name].push_back(scope);
return scope;
}
////////////////////////////////////////////////////////////////////
// Function: PPNamedScopes::get_scopes
// Access: Public
// Description: Returns a list of all the named scopes matching the
// given scope name. The scope name may be of the form
// "dirname/scopename", in which case the dirname may be
// another directory name, or "." or "*". If the
// dirname is ".", it is the same as the current
// directory name; if it is "*", it represents all
// directory names. If omitted, the current directory
// name is implied.
//
// It is the responsibility of the user to ensure that
// scopes is empty before calling this function; this
// will append to the existing vector without first
// clearing it.
////////////////////////////////////////////////////////////////////
void PPNamedScopes::
get_scopes(const string &name, Scopes &scopes) const {
string dirname = _current;
string scopename = name;
size_t slash = name.find(SCOPE_DIRNAME_SEPARATOR);
if (slash != string::npos) {
dirname = name.substr(0, slash);
scopename = name.substr(slash + 1);
if (dirname == SCOPE_DIRNAME_CURRENT) {
dirname = _current;
}
}
Directories::const_iterator di;
if (dirname == SCOPE_DIRNAME_WILDCARD) {
for (di = _directories.begin(); di != _directories.end(); ++di) {
p_get_scopes((*di).second, scopename, scopes);
}
} else {
di = _directories.find(dirname);
if (di != _directories.end()) {
p_get_scopes((*di).second, scopename, scopes);
}
}
}
////////////////////////////////////////////////////////////////////
// Function: PPNamedScopes::set_current
// Access: Public
// Description: Changes the currently-active directory, i.e. the
// dirname represented by ".".
////////////////////////////////////////////////////////////////////
void PPNamedScopes::
set_current(const string &dirname) {
_current = dirname;
}
////////////////////////////////////////////////////////////////////
// Function: PPNamedScopes::p_get_scopes
// Access: Private
// Description: Adds the scopes from the given directory with the
// matching name into the returned vector.
////////////////////////////////////////////////////////////////////
void PPNamedScopes::
p_get_scopes(const PPNamedScopes::Named &named, const string &name,
Scopes &scopes) const {
Named::const_iterator ni;
ni = named.find(name);
if (ni != named.end()) {
const Scopes &s = (*ni).second;
scopes.insert(scopes.end(), s.begin(), s.end());
}
}

47
ppremake/ppNamedScopes.h Normal file
View File

@@ -0,0 +1,47 @@
// Filename: ppNamedScopes.h
// Created by: drose (27Sep00)
//
////////////////////////////////////////////////////////////////////
#ifndef PPNAMEDSCOPES_H
#define PPNAMEDSCOPES_H
#include "ppremake.h"
#include <map>
#include <vector>
class PPScope;
///////////////////////////////////////////////////////////////////
// Class : PPNamedScopes
// Description : A collection of named scopes, as defined by #begin
// .. #end sequences within a series of command files,
// each associated with the directory name of the
// command file in which it was read.
////////////////////////////////////////////////////////////////////
class PPNamedScopes {
public:
PPNamedScopes();
~PPNamedScopes();
typedef vector<PPScope *> Scopes;
PPScope *make_scope(const string &name);
void get_scopes(const string &name, Scopes &scopes) const;
void set_current(const string &dirname);
private:
typedef map<string, Scopes> Named;
void p_get_scopes(const Named &named, const string &name,
Scopes &scopes) const;
typedef map<string, Named> Directories;
Directories _directories;
string _current;
};
#endif

1805
ppremake/ppScope.cxx Normal file

File diff suppressed because it is too large Load Diff

123
ppremake/ppScope.h Normal file
View File

@@ -0,0 +1,123 @@
// Filename: ppScope.h
// Created by: drose (25Sep00)
//
////////////////////////////////////////////////////////////////////
#ifndef PPSCOPE_H
#define PPSCOPE_H
#include "ppremake.h"
#include <map>
#include <vector>
class PPNamedScopes;
class PPDirectoryTree;
///////////////////////////////////////////////////////////////////
// Class : PPScope
// Description : Defines a (possibly nested) scope for variable
// definitions. Variables may be defined in a
// system-wide variable file, in a template file, or in
// an individual source file.
////////////////////////////////////////////////////////////////////
class PPScope {
public:
PPScope(PPNamedScopes *named_scopes);
PPNamedScopes *get_named_scopes() const;
void set_parent(PPScope *parent);
PPScope *get_parent() const;
void define_variable(const string &varname, const string &definition);
bool set_variable(const string &varname, const string &definition);
void define_map_variable(const string &varname, const string &definition);
void define_map_variable(const string &varname, const string &key_varname,
const string &scope_names);
string get_variable(const string &varname) const;
string expand_variable(const string &varname) const;
PPDirectoryTree *get_directory() const;
void set_directory(PPDirectoryTree *directory);
string expand_string(const string &str) const;
string expand_self_reference(const string &str, const string &varname) const;
static void push_scope(PPScope *scope);
static PPScope *pop_scope();
static PPScope *get_bottom_scope();
private:
class ExpandedVariable {
public:
string _varname;
ExpandedVariable *_next;
};
typedef map<string, PPScope *> MapVariableDefinition;
bool p_set_variable(const string &varname, const string &definition);
bool p_get_variable(const string &varname, string &result) const;
void tokenize_params(const string &str, vector<string> &tokens,
bool expand) const;
string r_expand_string(const string &str, ExpandedVariable *expanded) const;
string r_scan_variable(const string &str, size_t &vp) const;
string r_expand_variable(const string &str, size_t &vp,
PPScope::ExpandedVariable *expanded) const;
string expand_variable_nested(const string &varname,
const string &scope_names) const;
string expand_wildcard(const string &params) const;
string expand_isdir(const string &params) const;
string expand_libtest(const string &params) const;
string expand_bintest(const string &params) const;
string expand_shell(const string &params) const;
string expand_firstword(const string &params) const;
string expand_patsubst(const string &params) const;
string expand_filter(const string &params) const;
string expand_filter_out(const string &params) const;
string expand_subst(const string &params) const;
string expand_sort(const string &params) const;
string expand_unique(const string &params) const;
string expand_if(const string &params) const;
string expand_eq(const string &params) const;
string expand_ne(const string &params) const;
string expand_not(const string &params) const;
string expand_or(const string &params) const;
string expand_and(const string &params) const;
string expand_upcase(const string &params) const;
string expand_downcase(const string &params) const;
string expand_closure(const string &params) const;
string expand_map_variable(const string &varname, const string &params) const;
string expand_map_variable(const string &varname, const string &expression,
const vector<string> &keys) const;
const MapVariableDefinition &
find_map_variable(const string &varname) const;
const MapVariableDefinition &
p_find_map_variable(const string &varname) const;
void glob_string(const string &str, vector<string> &results) const;
PPNamedScopes *_named_scopes;
PPDirectoryTree *_directory;
typedef map<string, string> Variables;
Variables _variables;
typedef map<string, MapVariableDefinition> MapVariables;
MapVariables _map_variables;
static MapVariableDefinition _null_map_def;
PPScope *_parent_scope;
typedef vector<PPScope *> ScopeStack;
static ScopeStack _scope_stack;
};
#endif

48
ppremake/ppSubroutine.cxx Normal file
View File

@@ -0,0 +1,48 @@
// Filename: ppSubroutine.cxx
// Created by: drose (10Oct00)
//
////////////////////////////////////////////////////////////////////
#include "ppSubroutine.h"
PPSubroutine::Subroutines PPSubroutine::_subroutines;
////////////////////////////////////////////////////////////////////
// Function: PPSubroutine::define_sub
// Access: Public, Static
// Description: Adds a subroutine to the global list with the
// indicated name. The subroutine pointer must have
// been recently allocated, and ownership of the pointer
// will be passed to the global list; it may later
// delete it if another subroutine is defined with the
// same name.
////////////////////////////////////////////////////////////////////
void PPSubroutine::
define_sub(const string &name, PPSubroutine *sub) {
Subroutines::iterator si;
si = _subroutines.find(name);
if (si == _subroutines.end()) {
_subroutines.insert(Subroutines::value_type(name, sub));
} else {
delete (*si).second;
(*si).second = sub;
}
}
////////////////////////////////////////////////////////////////////
// Function: PPSubroutine::get_sub
// Access: Public, Static
// Description: Returns the previously-defined subroutine with the
// given name, or NULL if there is no such subroutine
// with that name.
////////////////////////////////////////////////////////////////////
const PPSubroutine *PPSubroutine::
get_sub(const string &name) {
Subroutines::const_iterator si;
si = _subroutines.find(name);
if (si == _subroutines.end()) {
return NULL;
} else {
return (*si).second;
}
}

34
ppremake/ppSubroutine.h Normal file
View File

@@ -0,0 +1,34 @@
// Filename: ppSubroutine.h
// Created by: drose (10Oct00)
//
////////////////////////////////////////////////////////////////////
#ifndef PPSUBROUTINE_H
#define PPSUBROUTINE_H
#include "ppremake.h"
#include <vector>
#include <map>
///////////////////////////////////////////////////////////////////
// Class : PPSubroutine
// Description : This represents a named subroutine defined via the
// #defsub .. #end sequence that may be invoked at any
// time via #call. All subroutine definitions are
// global.
////////////////////////////////////////////////////////////////////
class PPSubroutine {
public:
vector<string> _lines;
public:
static void define_sub(const string &name, PPSubroutine *sub);
static const PPSubroutine *get_sub(const string &name);
typedef map<string, PPSubroutine *> Subroutines;
static Subroutines _subroutines;
};
#endif

124
ppremake/ppremake.cxx Normal file
View File

@@ -0,0 +1,124 @@
// Filename: ppremake.cxx
// Created by: drose (25Sep00)
//
////////////////////////////////////////////////////////////////////
#include "ppremake.h"
#include "ppMain.h"
#include "ppScope.h"
#ifdef HAVE_GETOPT
#include <getopt.h>
#else
#include <gnu_getopt.h>
#endif
static void
usage() {
cerr <<
"\n"
"ppremake [opts] subdir-name [subdir-name..]\n"
"ppremake\n"
"\n"
"This is Panda pre-make: a script preprocessor that scans the directory\n"
"hierarchy beginning at root-directory, looking for directories that\n"
"contain a file called " SOURCE_FILENAME ". At the top of the directory\n"
"tree must be a file called " PACKAGE_FILENAME ", which should define\n"
"key variable definitions for processing, as well as pointing out the\n"
"locations of further config files.\n\n"
"The package file is read and interpreted, followed by each source file\n"
"in turn; after each source file is read, the template file (specified in\n"
"the config file) is read. The template file contains the actual statements\n"
"to be output and will typically be set up to generate Makefiles or whatever\n"
"is equivalent and appropriate to the particular build environment in use.\n\n"
"The parameters are the names of the subdirectories (their local names, not\n"
"the relative or full paths to them) that are to be processed. All\n"
"subdirectories (that contain a file named " SOURCE_FILENAME ") will be\n"
"scanned, but only the named subdirectories will have output files\n"
"generated. If no parameter is given, then all directories will be\n"
"processed.\n\n"
"Options:\n\n"
" -h Display this page.\n"
" -V Report the version of ppremake, and exit.\n"
" -P Report the current platform name, and exit.\n\n"
" -p platform Build as if for the indicated platform name.\n\n";
}
static void
report_version() {
cerr << "This is " << PACKAGE << " version " << VERSION << ".\n";
}
static void
report_platform() {
cerr << "ppremake built for platform " << PLATFORM << ".\n";
}
int
main(int argc, char *argv[]) {
extern char *optarg;
extern int optind;
const char *optstr = "hVPp:";
string platform = PLATFORM;
int flag = getopt(argc, argv, optstr);
while (flag != EOF) {
switch (flag) {
case 'h':
usage();
exit(0);
case 'V':
report_version();
exit(0);
break;
case 'P':
report_platform();
exit(0);
break;
case 'p':
platform = optarg;
break;
default:
exit(1);
}
flag = getopt(argc, argv, optstr);
}
argc -= (optind-1);
argv += (optind-1);
PPScope global_scope((PPNamedScopes *)NULL);
global_scope.define_variable("PROGRAM", PACKAGE);
global_scope.define_variable("PROGVER", VERSION);
global_scope.define_variable("PLATFORM", platform);
PPMain ppmain(&global_scope);
if (!ppmain.read_source(".")) {
exit(1);
}
if (argc < 2) {
if (!ppmain.process_all()) {
exit(1);
}
} else {
for (int i = 1; i < argc; i++) {
if (!ppmain.process(argv[i])) {
cerr << "Unable to process " << argv[i] << ".\n";
exit(1);
}
}
}
cerr << "No errors.\n";
return (0);
}

51
ppremake/ppremake.h Normal file
View File

@@ -0,0 +1,51 @@
/*
// Filename: ppremake.h
// Created by: drose (25Sep00)
//
////////////////////////////////////////////////////////////////////
*/
#ifndef PPREMAKE_H
#define PPREMAKE_H
#include "config.h"
#ifdef __cplusplus
#ifdef HAVE_IOSTREAM
#include <iostream>
#include <fstream>
#else
#include <iostream.h>
#include <fstream.h>
#endif
#include <string>
#ifdef HAVE_NAMESPACE
using namespace std;
#endif
#endif /* __cplusplus */
#define PACKAGE_FILENAME "Package.pp"
#define SOURCE_FILENAME "Sources.pp"
#define DIRECTORY_SEPARATOR '/'
#define COMMAND_PREFIX '#'
#define VARIABLE_PREFIX '$'
#define VARIABLE_OPEN_BRACE '['
#define VARIABLE_CLOSE_BRACE ']'
#define PATTERN_WILDCARD '%'
#define BEGIN_COMMENT "//"
#define FUNCTION_PARAMETER_SEPARATOR ','
#define VARIABLE_OPEN_NESTED '('
#define VARIABLE_CLOSE_NESTED ')'
#define VARIABLE_PATSUBST ":"
#define VARIABLE_PATSUBST_DELIM "="
#define SCOPE_DIRNAME_SEPARATOR '/'
#define SCOPE_DIRNAME_WILDCARD "*"
#define SCOPE_DIRNAME_CURRENT "."
#endif

134
ppremake/tokenize.cxx Normal file
View File

@@ -0,0 +1,134 @@
// Filename: tokenize.cxx
// Created by: drose (25Sep00)
//
////////////////////////////////////////////////////////////////////
#include "tokenize.h"
#include <ctype.h>
////////////////////////////////////////////////////////////////////
// Function: tokenize
// Description: Chops the source string up into pieces delimited by
// any of the characters specified in delimiters.
// Repeated delimiter characters represent zero-length
// tokens.
//
// It is the user's responsibility to ensure the output
// vector is cleared before calling this function; the
// results will simply be appended to the end of the
// vector.
////////////////////////////////////////////////////////////////////
void
tokenize(const string &source, vector<string> &tokens,
const string &delimiters) {
size_t p = 0;
while (p < source.length()) {
size_t q = source.find_first_of(delimiters, p);
if (q == string::npos) {
tokens.push_back(source.substr(p));
return;
}
tokens.push_back(source.substr(p, q - p));
p = q + 1;
}
tokens.push_back(string());
}
////////////////////////////////////////////////////////////////////
// Function: tokenize_whitespace
// Description: Chops the source string up into pieces delimited by
// whitespace characters. It is different from
// tokenize() in that repeated whitespace characters are
// not significant.
//
// It is the user's responsibility to ensure the output
// vector is cleared before calling this function; the
// results will simply be appended to the end of the
// vector.
////////////////////////////////////////////////////////////////////
void
tokenize_whitespace(const string &source, vector<string> &tokens) {
// First, start at the first non-whitespace character.
size_t p = 0;
while (p < source.length() && isspace(source[p])) {
p++;
}
while (p < source.length()) {
// Now scan to the end of the word.
size_t q = p;
while (q < source.length() && !isspace(source[q])) {
q++;
}
tokens.push_back(source.substr(p, q - p));
p = q;
while (p < source.length() && isspace(source[p])) {
p++;
}
}
}
////////////////////////////////////////////////////////////////////
// Function: repaste
// Description: Returns a string representing the given sequence of
// tokens concatenated together with the separator
// string between them.
////////////////////////////////////////////////////////////////////
string
repaste(const vector<string> &tokens, const string &separator) {
string result;
if (!tokens.empty()) {
vector<string>::const_iterator ti;
ti = tokens.begin();
result += (*ti);
++ti;
while (ti != tokens.end()) {
result += separator;
result += (*ti);
++ti;
}
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: trim_blanks
// Description: Returns a new string, equivalent to the source
// string, but with the leading and trailing whitespace
// removed.
////////////////////////////////////////////////////////////////////
string
trim_blanks(const string &str) {
size_t p = 0;
while (p < str.length() && isspace(str[p])) {
p++;
}
size_t q = str.length();
while (q > p && isspace(str[q - 1])) {
q--;
}
return str.substr(p, q - p);
}
////////////////////////////////////////////////////////////////////
// Function: contains_whitespace
// Description: Returns true if the string contains any whitespace
// characters, false if it does not.
////////////////////////////////////////////////////////////////////
bool
contains_whitespace(const string &str) {
string::const_iterator si;
for (si = str.begin(); si != str.end(); ++si) {
if (isspace(*si)) {
return true;
}
}
return false;
}

30
ppremake/tokenize.h Normal file
View File

@@ -0,0 +1,30 @@
// Filename: tokenize.h
// Created by: drose (25Sep00)
//
////////////////////////////////////////////////////////////////////
#ifndef TOKENIZE_H
#define TOKENIZE_H
#include "ppremake.h"
#include <vector>
// A couple of handy functions for breaking up a string into tokens,
// and repasting the tokens back into a string.
void tokenize(const string &source, vector<string> &tokens,
const string &delimiters);
void tokenize_whitespace(const string &source, vector<string> &tokens);
string repaste(const vector<string> &tokens, const string &separator);
// And this is just handy to have.
string trim_blanks(const string &str);
// So is this.
bool contains_whitespace(const string &str);
#endif