*** empty log message ***

This commit is contained in:
David Rose 2000-10-15 18:59:20 +00:00
parent c601286b46
commit 97cc7e6be8
19 changed files with 1089 additions and 439 deletions

View File

@ -6,19 +6,33 @@
// determining build order.
//
#if $[eq $[DIR_TYPE], src]
#if $[or $[eq $[DIR_TYPE], src], $[eq $[DIR_TYPE], metalib]]
#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
#forscopes metalib_target static_lib_target lib_target noinst_lib_target bin_target noinst_bin_target
// We can optimize quite a bit by evaluating now several of the key
// deferred variables defined in Globals.pp. This way they won't need
// to get repeatedly reevaluated as each directory examines each
// other.
#define build_directory $[build_directory]
#define build_target $[build_target]
#define active_local_libs $[active_local_libs]
#define active_component_libs $[active_component_libs]
#define active_libs $[active_libs]
#define get_sources $[get_sources]
// Report a warning for nonexisting dependencies.
#define nonexisting $[unmapped all_libs,$[LOCAL_LIBS]]
#if $[ne $[nonexisting],]
Warning: Lib(s) $[nonexisting], referenced in $[DIRNAME]/$[TARGET], not found.
#endif
#set DEPENDS $[DEPENDS] $[all_libs $[DIRNAME],$[LOCAL_LIBS] $[COMPONENT_LIBS]] $[LOCAL_INCS]
#end metalib_target static_lib_target lib_target noinst_lib_target bin_target noinst_bin_target
#set DEPENDS $[sort $[DEPENDS]]
#endif

View File

@ -6,196 +6,36 @@
// 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.
// This subroutine fills sources, alt_cflags, alt_ipath, alt_lpath,
// alt_libs, and alt_ld as appropriate for the current target.
#define sources
#define alt_cflags
#define alt_ipath
#define alt_lpath
#define alt_libs
#define alt_ld
#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
#set sources $[get_sources]
#set alt_cflags $[get_cflags]
#set alt_ipath $[get_ipath]
#set alt_lpath $[get_lpath]
#set alt_libs $[get_libs]
#set alt_ld $[get_ld]
#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
// correctly to the set of libs we should link with for the current
// target.
#define when_defer
#define when_no_defer
#define when_either
#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
#set when_defer
#foreach lib $[LOCAL_LIBS]
// Only consider libraries that we're actually building.
#if $[all_libs $[build_directory],$[lib]]
@ -211,7 +51,7 @@
// 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
#set when_no_defer
#foreach lib $[COMPONENT_LIBS] $[LOCAL_LIBS]
#if $[all_libs $[build_directory],$[lib]]
#set when_no_defer $[when_no_defer] $[lib]
@ -222,7 +62,7 @@
// 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]]
#set when_either $[filter-out %:m %:c,$[OTHER_LIBS]]
#end get_libs
@ -230,9 +70,6 @@
// 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.
@ -258,10 +95,9 @@
// 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.
#define depend_libs
#defsub get_depend_libs
#map module COMPONENT_LIBS(*/metalib_target)
#define depend_libs
#set depend_libs
#forscopes lib_target noinst_lib_target
#define metalib $[module $[TARGET],$[TARGET]]
#if $[ne $[metalib],]
@ -314,9 +150,6 @@
// 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.

View File

@ -12,9 +12,11 @@ ppremake_SOURCES = \
tokenize.h
data_DATA = \
System.pp Depends.pp Template.autoconf.pp \
Global.stopgap.pp Template.stopgap.pp
System.pp Depends.pp Global.pp Template.autoconf.pp \
Global.stopgap.pp Template.stopgap.pp \
Global.unix.pp Template.unix.pp
EXTRA_DIST =\
System.pp Depends.pp Template.autoconf.pp \
Global.stopgap.pp Template.stopgap.pp
System.pp Depends.pp Global.pp Template.autoconf.pp \
Global.stopgap.pp Template.stopgap.pp \
Global.unix.pp Template.unix.pp

View File

@ -21,14 +21,13 @@
#endif
#if $[eq $[GLOBAL_FILE],]
#define GLOBAL_FILE $[PPREMAKE_DIR]/Global.$[BUILD_TYPE].pp
#define GLOBAL_FILE $[PPREMAKE_DIR]/Global.pp
#endif
#if $[eq $[GLOBAL_TYPE_FILE],]
#define GLOBAL_TYPE_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

@ -16,11 +16,6 @@
#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.
@ -40,7 +35,7 @@
#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]]
#define install_data $[sort $[INSTALL_DATA(static_lib_target lib_target sed_bin_target bin_target)] $[INSTALL_DATA]] $[sort $[INSTALL_CONFIG(static_lib_target lib_target sed_bin_target bin_target)] $[INSTALL_CONFIG]]
// Collect the set of interrogate database files we'll install,
// possibly one for each library we build.
@ -71,7 +66,7 @@ INSTALL = $[install]
MAKEDIR = .
#### The action is here.
include $(DTOOL)/inc/Makefile.meta.rules
include $(DTOOL)/include/Makefile.meta.rules
#### Sub-make build order dependencies:
# foo: bar
@ -123,14 +118,14 @@ IGATEDB =$[install_igatedb]
#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))
INST_PARSER_INC = $(addprefix include/parser-inc/,$(PARSER_INC))
OTHER = $(INST_PARSER_INC)
#else
# OTHER =
#endif
#### Where the action happens.
include $(DTOOL)/inc/Makefile.install.rules
include $(DTOOL)/include/Makefile.install.rules
#### Install actions for OTHER files (source must be in $(PKGROOT)):
# [ installed file ] : $(PKGROOT)/[ source file ] # Files must have same name
@ -140,7 +135,7 @@ include $(DTOOL)/inc/Makefile.install.rules
# $(MKINSTALL) # Also makes directory if needed
#if $[ne $[INSTALL_PARSER_INC],]
$(INST_PARSER_INC) : inc/parser-inc/% : $(PKGROOT)/%
$(INST_PARSER_INC) : include/parser-inc/% : $(PKGROOT)/%
$(MKINSTALL)
#endif
@ -226,11 +221,11 @@ C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[C++FLAGS]
#### Interrogate info
IGATESCAN = $[igatescan]
IGATEFLAGS = $[alt_ipath]
IGATEFLAGS = $[alt_ipath:%=-I%]
# IGATEFILE = # Specify only if you want a specific name
#### Additional search directories for C/C++ header files:
IPATH = $[alt_ipath]
IPATH = $[alt_ipath:%=-I%]
#### Location to put .o files:
# ODIR =
@ -246,7 +241,7 @@ LIBS = $[when_either:%=-l%]
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
#### Additional search directories for lib:
LPATH = $[alt_lpath]
LPATH = $[alt_lpath:%=-L%]
#### Other linker flags.
#if $[ne $[alt_ld],]
@ -255,16 +250,16 @@ LD = $[alt_ld]
# LDFLAGS =
#### Pull in standard .o make variables
include $(DTOOL)/inc/Makefile.o.vars
include $(DTOOL)/include/Makefile.o.vars
#### The .o action is here.
include $(DTOOL)/inc/Makefile.o.rules
include $(DTOOL)/include/Makefile.o.rules
#### Pull in standard binary make variables.
include $(DTOOL)/inc/Makefile.bin.vars
include $(DTOOL)/include/Makefile.bin.vars
#### The .so action is here.
include $(DTOOL)/inc/Makefile.so.rules
include $(DTOOL)/include/Makefile.so.rules
#end Makefile.$[TARGET].so
#end lib_target noinst_lib_target
@ -314,7 +309,7 @@ C++FLAGS = $[building_var:%=-D%] $[alt_cflags] $[C++FLAGS]
# PTREPOSITORY = # Specify only if you want a specific name
#### Additional search directories for C/C++ header files:
IPATH = $[alt_ipath]
IPATH = $[alt_ipath:%=-I%]
#### Location to put .o files:
# ODIR =
@ -332,22 +327,22 @@ LIBS = $[when_either:%=-l%]
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
#### Additional search directories for lib:
LPATH = $[alt_lpath]
LPATH = $[alt_lpath:%=-L%]
#### Archiver flags
# ARFLAGS =
#### Pull in standard .o make variables
include $(DTOOL)/inc/Makefile.o.vars
include $(DTOOL)/include/Makefile.o.vars
#### The .o action is here.
include $(DTOOL)/inc/Makefile.o.rules
include $(DTOOL)/include/Makefile.o.rules
#### Pull in standard binary make variables.
include $(DTOOL)/inc/Makefile.bin.vars
include $(DTOOL)/include/Makefile.bin.vars
#### The .a action is here.
include $(DTOOL)/inc/Makefile.a.rules
include $(DTOOL)/include/Makefile.a.rules
#end Makefile.$[TARGET].a
#end static_lib_target
@ -395,7 +390,7 @@ 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]
IPATH = $[alt_ipath:%=-I%]
#### Location to put .o files:
# ODIR =
@ -411,7 +406,7 @@ LIBS = $[when_either:%=-l%]
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
#### Additional search directories for lib:
LPATH = $[alt_lpath]
LPATH = $[alt_lpath:%=-L%]
#### Other linker flags.
#if $[ne $[alt_ld],]
@ -420,16 +415,16 @@ LD = $[alt_ld]
# LDFLAGS =
#### Pull in standard .o make variables
include $(DTOOL)/inc/Makefile.o.vars
include $(DTOOL)/include/Makefile.o.vars
#### The .o action is here.
include $(DTOOL)/inc/Makefile.o.rules
include $(DTOOL)/include/Makefile.o.rules
#### Pull in standard binary make variables.
include $(DTOOL)/inc/Makefile.bin.vars
include $(DTOOL)/include/Makefile.bin.vars
#### The bin action is here.
include $(DTOOL)/inc/Makefile.bin.rules
include $(DTOOL)/include/Makefile.bin.rules
#end Makefile.$[TARGET]
#end bin_target noinst_bin_target test_bin_target
@ -465,17 +460,13 @@ cleanall :
#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)]
#define install_data $[INSTALL_DATA(metalib_target)] $[INSTALL_CONFIG(metalib_target)]
#output Makefile
@ -495,7 +486,7 @@ INSTALL = $[submakes]
MAKEDIR = .
#### The action is here.
include $(DTOOL)/inc/Makefile.meta.rules
include $(DTOOL)/include/Makefile.meta.rules
#### Sub-make build order dependencies:
# foo: bar
@ -544,7 +535,7 @@ INCLUDE = $[install_headers]
# OTHER =
#### Where the action happens.
include $(DTOOL)/inc/Makefile.install.rules
include $(DTOOL)/include/Makefile.install.rules
#### Install actions for OTHER files (source must be in $(PKGROOT)):
# [ installed file ] : $(PKGROOT)/[ source file ] # Files must have same name
@ -576,7 +567,6 @@ endif
#call get_libs
#if $[HAVE_PYTHON]
#map components TARGET(*/lib_target */noinst_lib_target)
#if $[ne $[components $[IGATESCAN],$[COMPONENT_LIBS]],]
#define igatemscan $[TARGET]
#endif
@ -627,7 +617,7 @@ IGATEMSCAN = $[igatemscan]
DEFERRED_FILES = $[TARGET]
#### Additional search directories for C/C++ header files:
IPATH = $[alt_ipath]
IPATH = $[alt_ipath:%=-I%]
#### Location to put .o files:
# ODIR =
@ -643,7 +633,7 @@ LIBS = $[when_either:%=-l%]
SYSLIBS = $[patsubst %.lib,%.lib,%,-l%,$[unique $[alt_libs]]]
#### Additional search directories for lib:
LPATH = $[alt_lpath]
LPATH = $[alt_lpath:%=-L%]
#### Other linker flags.
#if $[ne $[alt_ld],]
@ -652,16 +642,16 @@ LD = $[alt_ld]
# LDFLAGS =
#### Pull in standard .o make variables
include $(DTOOL)/inc/Makefile.o.vars
include $(DTOOL)/include/Makefile.o.vars
#### The .o action is here.
include $(DTOOL)/inc/Makefile.o.rules
include $(DTOOL)/include/Makefile.o.rules
#### Pull in standard binary make variables.
include $(DTOOL)/inc/Makefile.bin.vars
include $(DTOOL)/include/Makefile.bin.vars
#### The .so action is here.
include $(DTOOL)/inc/Makefile.so.rules
include $(DTOOL)/include/Makefile.so.rules
#end Makefile.$[TARGET].so
#end metalib_target
@ -694,7 +684,7 @@ include $(DTOOL)/inc/Makefile.so.rules
CTPROJECT = $[PACKAGE]
CTPROJROOT = $($[upcase $[PACKAGE]])
include $(DTOOL)/inc/Makefile.project.vars
include $(DTOOL)/include/Makefile.project.vars
// Iterate through all of our known source files. Each src and
// metalib type file gets its corresponding Makefile.install listed

View File

@ -1,6 +1,6 @@
dnl Process this file with autoconf to produce a configure script.
AC_INIT(ppremake.cxx)
AM_INIT_AUTOMAKE(ppremake, 0.25a)
AM_INIT_AUTOMAKE(ppremake, 0.26)
AM_CONFIG_HEADER(config.h)
AC_PREFIX_DEFAULT(/usr/local/panda)

View File

@ -152,6 +152,18 @@ PPCommandFile::
delete _write_state;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::set_output
// Access: Public
// Description: Changes the main output stream that will be written
// to when text appears outside of a #output .. #end
// block. This is cout by default.
////////////////////////////////////////////////////////////////////
void PPCommandFile::
set_output(ostream *out) {
_write_state->_out = out;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::set_scope
// Access: Public
@ -343,10 +355,19 @@ end_read() {
cerr << "Unclosed foreach " << _block_nesting->_name << "\n";
break;
case BS_formap:
case BS_nested_formap:
cerr << "Unclosed formap " << _block_nesting->_name << "\n";
break;
case BS_defsub:
cerr << "Unclosed defsub " << _block_nesting->_name << "\n";
break;
case BS_defun:
cerr << "Unclosed defun " << _block_nesting->_name << "\n";
break;
case BS_output:
cerr << "Unclosed output " << _block_nesting->_name << "\n";
break;
@ -424,14 +445,23 @@ handle_command(const string &line) {
} else if (_command == "foreach") {
return handle_foreach_command();
} else if (_command == "formap") {
return handle_formap_command();
} else if (_command == "format") {
return handle_format_command();
} else if (_command == "output") {
return handle_output_command();
} else if (_command == "print") {
return handle_print_command();
} else if (_command == "defsub") {
return handle_defsub_command();
return handle_defsub_command(true);
} else if (_command == "defun") {
return handle_defsub_command(false);
} else if (_command == "end") {
return handle_end_command();
@ -464,6 +494,9 @@ handle_command(const string &line) {
} else if (_command == "map") {
return handle_map_command();
} else if (_command == "addmap") {
return handle_addmap_command();
}
cerr << "Invalid command: " << COMMAND_PREFIX << _command << "\n";
@ -700,6 +733,7 @@ handle_foreach_command() {
nest->_scope = _scope;
nest->_next = _block_nesting;
// We insert in all but the first word in the words vector.
nest->_words.insert(nest->_words.end(), words.begin() + 1, words.end());
_block_nesting = nest;
@ -712,6 +746,49 @@ handle_foreach_command() {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_formap_command
// Access: Protected
// Description: Handles the #formap command: interpret all the lines
// between this command and the corresponding #end
// command once for each key in the map, and also within
// the corresponding scope of that particular key.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
handle_formap_command() {
// Get the parameters of the formap command. The first word is the
// name of the variable to substitute in (and which should appear on
// the matching #end command), and the second word is the name of
// the map variable.
vector<string> words;
tokenize_whitespace(_scope->expand_string(_params), words);
if (words.size() != 2) {
cerr << "#formap requires exactly two parameters.\n";
return false;
}
string variable_name = words.front();
BlockNesting *nest = new BlockNesting;
nest->_state = _in_for ? BS_nested_formap : BS_formap;
nest->_name = words[0];
nest->_write_state = _write_state;
nest->_scope = _scope;
nest->_next = _block_nesting;
nest->_words.push_back(words[1]);
_block_nesting = nest;
if (!_in_for) {
_in_for = true;
_saved_lines.clear();
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_format_command
// Access: Protected
@ -802,35 +879,74 @@ handle_output_command() {
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_defsub_command
// Function: PPCommandFile::handle_print_command
// Access: Protected
// Description: Handles the #defsub command: save all the lines
// between this command and the matching #end as a
// callable subroutine to be invoked by a later #call
// command.
// Description: Handles the #print command: immediately output the
// arguments to this line to standard error.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
handle_defsub_command() {
// The only parameter of #defsub is the name of the subroutine.
string subroutine_name = trim_blanks(_scope->expand_string(_params));
handle_print_command() {
if (!_in_for) {
cerr << _scope->expand_string(_params) << "\n";
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_defsub_command
// Access: Protected
// Description: Handles the #defsub (or #defun) command: save all the
// lines between this command and the matching #end as a
// callable subroutine to be invoked by a later #call
// command. If is_defsub is false, it means this
// subroutine was actually defined via a #defun command,
// so it is to be invoked by a later variable reference,
// instead of by a #call command.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
handle_defsub_command(bool is_defsub) {
string command = (is_defsub) ? "#defsub" : "#defun";
// The first word of the parameter list is the subroutine name; the
// rest is the comma-separated list of formal parameter names.
// Pull off the first word and the rest of the params.
size_t p = 0;
while (p < _params.length() && !isspace(_params[p])) {
p++;
}
string subroutine_name = trim_blanks(_params.substr(0, p));
if (subroutine_name.empty()) {
cerr << "#defsub requires at least one parameter.\n";
cerr << command << " requires at least one parameter.\n";
return false;
}
vector<string> formals;
_scope->tokenize_params(_params.substr(p), formals, false);
vector<string>::const_iterator fi;
for (fi = formals.begin(); fi != formals.end(); ++fi) {
if (!is_valid_formal(*fi)) {
cerr << command << " " << subroutine_name
<< ": invalid formal parameter name '" << (*fi) << "'\n";
return false;
}
}
if (_in_for) {
cerr << "#defsub may not appear within a #forscopes or #foreach block,\n"
<< "or within another #defsub block.\n";
cerr << command << " may not appear within another block scoping command like\n"
<< "#forscopes, #foreach, #formap, #defsub, or #defun.\n";
return false;
}
BlockNesting *nest = new BlockNesting;
nest->_state = BS_defsub;
nest->_state = is_defsub ? BS_defsub : BS_defun;
nest->_name = subroutine_name;
nest->_write_state = _write_state;
nest->_scope = _scope;
nest->_next = _block_nesting;
nest->_words.swap(formals);
_block_nesting = nest;
@ -884,10 +1000,19 @@ handle_end_command() {
return false;
}
} else if (nest->_state == BS_defsub) {
} else if (nest->_state == BS_formap) {
// Now replay all of the saved lines.
_in_for = false;
assert(nest->_words.size() == 1);
if (!replay_formap(nest->_name, nest->_words[0])) {
return false;
}
} else if (nest->_state == BS_defsub || nest->_state == BS_defun) {
// Save all of the saved lines as a named subroutine.
_in_for = false;
PPSubroutine *sub = new PPSubroutine;
sub->_formals.swap(nest->_words);
sub->_lines.swap(_saved_lines);
// Remove the #end command. This will fail if someone makes an
@ -895,7 +1020,11 @@ handle_end_command() {
assert(!sub->_lines.empty());
sub->_lines.pop_back();
PPSubroutine::define_sub(nest->_name, sub);
if (nest->_state == BS_defsub) {
PPSubroutine::define_sub(nest->_name, sub);
} else {
PPSubroutine::define_func(nest->_name, sub);
}
} else if (nest->_state == BS_output) {
if (!_in_for) {
@ -976,10 +1105,21 @@ handle_sinclude_command() {
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
handle_call_command() {
string subroutine_name = trim_blanks(_scope->expand_string(_params));
// The first word is the name of the subroutine; the rest is the
// comma-separated list of expressions to substitute in for the
// subroutine's formal parameters.
// Pull off the first word and the rest of the params.
size_t p = 0;
while (p < _params.length() && !isspace(_params[p])) {
p++;
}
string subroutine_name = trim_blanks(_params.substr(0, p));
string params = _params.substr(p);
if (subroutine_name.empty()) {
cerr << "#call with no parameter.\n";
cerr << "#call requires at least one parameter.\n";
return false;
}
const PPSubroutine *sub = PPSubroutine::get_sub(subroutine_name);
@ -987,13 +1127,23 @@ handle_call_command() {
cerr << "Attempt to call undefined subroutine " << subroutine_name << "\n";
}
PPScope *old_scope = _scope;
PPScope::push_scope(_scope);
PPScope nested_scope(_scope->get_named_scopes());
_scope = &nested_scope;
nested_scope.define_formals(subroutine_name, sub->_formals, params);
vector<string>::const_iterator li;
for (li = sub->_lines.begin(); li != sub->_lines.end(); ++li) {
if (!read_line(*li)) {
PPScope::pop_scope();
_scope = old_scope;
return false;
}
}
PPScope::pop_scope();
_scope = old_scope;
return true;
}
@ -1005,8 +1155,10 @@ handle_call_command() {
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
handle_error_command() {
if (!_params.empty()) {
cerr << _params << "\n";
string message = trim_blanks(_scope->expand_string(_params));
if (!message.empty()) {
cerr << message << "\n";
}
return false;
}
@ -1031,6 +1183,11 @@ handle_defer_command() {
p++;
}
string varname = _params.substr(0, p);
if (PPSubroutine::get_func(varname) != (const PPSubroutine *)NULL) {
cerr << "Warning: variable " << varname
<< " shadowed by function definition.\n";
}
// Skip whitespace between the variable name and its definition.
while (p < _params.length() && isspace(_params[p])) {
@ -1065,6 +1222,11 @@ handle_define_command() {
p++;
}
string varname = _params.substr(0, p);
if (PPSubroutine::get_func(varname) != (const PPSubroutine *)NULL) {
cerr << "Warning: variable " << varname
<< " shadowed by function definition.\n";
}
// Skip whitespace between the variable name and its definition.
while (p < _params.length() && isspace(_params[p])) {
@ -1099,6 +1261,11 @@ handle_set_command() {
p++;
}
string varname = _params.substr(0, p);
if (PPSubroutine::get_func(varname) != (const PPSubroutine *)NULL) {
cerr << "Warning: variable " << varname
<< " shadowed by function definition.\n";
}
// Skip whitespace between the variable name and its definition.
while (p < _params.length() && isspace(_params[p])) {
@ -1136,18 +1303,37 @@ handle_map_command() {
while (p < _params.length() && isspace(_params[p])) {
p++;
}
string def = _params.substr(p);
// We don't expand the variable's definition immediately; it will be
// expanded when the variable is referenced later. However, we
// should expand any simple self-reference immediately, to allow for
// recursive definitions.
def = _scope->expand_string(def);
string def = trim_blanks(_params.substr(p));
_scope->define_map_variable(varname, def);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_addmap_command
// Access: Protected
// Description: Handles the #addmap command: add a new key/scope pair
// to an existing map variable.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
handle_addmap_command() {
// Pull off the first word and the rest of the params.
size_t p = 0;
while (p < _params.length() && !isspace(_params[p])) {
p++;
}
string varname = _params.substr(0, p);
// Skip whitespace between the variable name and the key.
while (p < _params.length() && isspace(_params[p])) {
p++;
}
string key = trim_blanks(_scope->expand_string(_params.substr(p)));
_scope->add_to_map_variable(varname, key, _scope);
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::include_file
@ -1208,23 +1394,24 @@ replay_forscopes(const string &name) {
vector<string> words;
tokenize_whitespace(name, words);
// Now traverse the named scopes with these names.
// Now build up the list of scopes with these names.
PPNamedScopes::Scopes scopes;
vector<string>::const_iterator wi;
for (wi = words.begin(); wi != words.end(); ++wi) {
PPNamedScopes::Scopes scopes;
named_scopes->get_scopes(*wi, scopes);
}
PPNamedScopes::sort_by_dependency(scopes);
PPNamedScopes::Scopes::const_iterator si;
for (si = scopes.begin(); si != scopes.end(); ++si) {
PPScope::push_scope(_scope);
_scope = (*si);
vector<string>::const_iterator li;
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
okflag = read_line(*li);
}
_scope = PPScope::pop_scope();
PPNamedScopes::Scopes::const_iterator si;
for (si = scopes.begin(); si != scopes.end(); ++si) {
PPScope::push_scope(_scope);
_scope = (*si);
vector<string>::const_iterator li;
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
okflag = read_line(*li);
}
_scope = PPScope::pop_scope();
}
return okflag;
@ -1261,6 +1448,51 @@ replay_foreach(const string &varname, const vector<string> &words) {
return okflag;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::replay_formap
// Access: Protected
// Description: Replays all the lines that were saved during a
// previous #formap..#end block.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
replay_formap(const string &varname, const string &mapvar) {
bool okflag = true;
vector<string> lines;
lines.swap(_saved_lines);
// Remove the #end command. This will fail if someone makes an #end
// command that spans multiple lines. Don't do that.
assert(!lines.empty());
lines.pop_back();
// Now look up the map variable.
PPScope::MapVariableDefinition &def = _scope->find_map_variable(mapvar);
if (&def == &PPScope::_null_map_def) {
cerr << "Undefined map variable: #formap " << varname << " "
<< mapvar << "\n";
return false;
}
// Now traverse through the map definition.
PPScope::MapVariableDefinition::const_iterator di;
for (di = def.begin(); di != def.end() && okflag; ++di) {
_scope->define_variable(varname, (*di).first);
PPScope::push_scope(_scope);
_scope = (*di).second;
vector<string>::const_iterator li;
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
okflag = read_line(*li);
}
_scope = PPScope::pop_scope();
}
return okflag;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::compare_output
// Access: Protected
@ -1324,6 +1556,39 @@ failed_if() const {
(_if_nesting->_state == IS_off || _if_nesting->_state == IS_done));
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::is_valid_formal_parameter_name
// Access: Protected
// Description: Returns true if the indicated name is an acceptable
// name for a formal parameter. This means it includes
// no whitespace or crazy punctuation. Mainly this is
// to protect the user from making some stupid syntax
// mistake.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
is_valid_formal(const string &formal_parameter_name) const {
if (formal_parameter_name.empty()) {
return false;
}
string::const_iterator si;
for (si = formal_parameter_name.begin();
si != formal_parameter_name.end();
++si) {
switch (*si) {
case ' ':
case '\n':
case '\t':
case '$':
case '[':
case ']':
case ',':
return false;
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::PushFilename::Constructor

View File

@ -24,6 +24,8 @@ public:
PPCommandFile(PPScope *scope);
~PPCommandFile();
void set_output(ostream *out);
void set_scope(PPScope *scope);
PPScope *get_scope() const;
@ -43,9 +45,11 @@ protected:
bool handle_begin_command();
bool handle_forscopes_command();
bool handle_foreach_command();
bool handle_formap_command();
bool handle_format_command();
bool handle_output_command();
bool handle_defsub_command();
bool handle_print_command();
bool handle_defsub_command(bool is_defsub);
bool handle_end_command();
bool handle_include_command();
@ -57,13 +61,17 @@ protected:
bool handle_define_command();
bool handle_set_command();
bool handle_map_command();
bool handle_addmap_command();
bool include_file(const string &filename);
bool replay_forscopes(const string &name);
bool replay_foreach(const string &varname, const vector<string> &words);
bool replay_formap(const string &varname, const string &mapvar);
bool compare_output(const string &temp_name, const string &true_name);
bool failed_if() const;
bool is_valid_formal(const string &formal_parameter_name) const;
private:
class PushFilename {
public:
@ -98,7 +106,10 @@ private:
BS_nested_forscopes,
BS_foreach,
BS_nested_foreach,
BS_formap,
BS_nested_formap,
BS_defsub,
BS_defun,
BS_output
};

View File

@ -90,22 +90,32 @@ PPDirectoryTree(const string &dirname, PPDirectoryTree *parent) :
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::scan
// Function: PPDirectoryTree::scan_source
// Access: Public
// Description: Reads in the complete hierarchy of source files.
// prefix is the pathname to the directory on disk,
// ending in slash.
// Description: Reads in the complete hierarchy of source files,
// beginning at the current directory.
////////////////////////////////////////////////////////////////////
bool PPDirectoryTree::
scan(const string &prefix, PPNamedScopes *named_scopes) {
if (!r_scan(prefix)) {
scan_source(PPNamedScopes *named_scopes) {
if (!r_scan("")) {
return false;
}
if (!read_source_file(prefix, named_scopes)) {
if (!read_source_file("", named_scopes)) {
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPDirectoryTree::scan_depends
// Access: Public
// Description: Reads in the depends file for each source file, and
// then sorts the files into dependency order.
////////////////////////////////////////////////////////////////////
bool PPDirectoryTree::
scan_depends(PPNamedScopes *named_scopes) {
if (!read_depends_file(named_scopes)) {
return false;
}

View File

@ -33,7 +33,8 @@ protected:
PPDirectoryTree(const string &dirname, PPDirectoryTree *parent);
public:
bool scan(const string &prefix, PPNamedScopes *named_scopes);
bool scan_source(PPNamedScopes *named_scopes);
bool scan_depends(PPNamedScopes *named_scopes);
int count_source_files() const;

View File

@ -8,6 +8,9 @@
#include "ppCommandFile.h"
#include <unistd.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h> // for perror
////////////////////////////////////////////////////////////////////
// Function: PPMain::Constructor
@ -46,20 +49,17 @@ PPMain::
////////////////////////////////////////////////////////////////////
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 = "";
}
// First, find the top of the source tree, as indicated by the
// presence of a Package.pp file.
string trydir = root;
string package_file = search + PACKAGE_FILENAME;
string package_file = trydir + "/" + 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;
string source_file = trydir + "/" + SOURCE_FILENAME;
if (access(source_file.c_str(), F_OK) != 0) {
cerr << "Could not find ppremake package file " << PACKAGE_FILENAME
<< ".\n\n"
@ -69,24 +69,31 @@ read_source(const string &root) {
<< "important ppremake config files.\n\n";
return false;
}
search += "../";
package_file = search + PACKAGE_FILENAME;
trydir += "/..";
package_file = trydir + "/" + PACKAGE_FILENAME;
}
// Now cd to the source root and get the actual path.
if (chdir(trydir.c_str()) < 0) {
perror("chdir");
return false;
}
string cwd = get_cwd();
cerr << "Root is " << cwd << "\n";
_def_scope = new PPScope(&_named_scopes);
_def_scope->define_variable("PACKAGEFILE", package_file);
_def_scope->define_variable("TOPDIRPREFIX", search);
_def_scope->define_variable("TOPDIR", cwd);
_defs = new PPCommandFile(_def_scope);
// cerr << "Reading " << package_file << "\n";
if (!_defs->read_file(package_file)) {
cerr << "Error reading package file " << package_file << ".\n";
if (!_defs->read_file(PACKAGE_FILENAME)) {
return false;
}
PPScope::push_scope(_def_scope);
if (!_tree.scan(search, &_named_scopes)) {
if (!_tree.scan_source(&_named_scopes)) {
return false;
}
@ -102,6 +109,17 @@ read_source(const string &root) {
return false;
}
cerr << "Read " << _tree.count_source_files() << " " << SOURCE_FILENAME
<< " files.\n";
if (!read_global_file()) {
return false;
}
if (!_tree.scan_depends(&_named_scopes)) {
return false;
}
return true;
}
@ -191,3 +209,58 @@ p_process(PPDirectoryTree *dir) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPMain::read_global_file
// Access: Private
// Description: Reads in the Global.pp file after all sources files
// have been read and sorted into dependency order.
////////////////////////////////////////////////////////////////////
bool PPMain::
read_global_file() {
assert(_def_scope != (PPScope *)NULL);
string global_filename = _def_scope->expand_variable("GLOBAL_FILE");
if (global_filename.empty()) {
cerr << "No definition given for $[GLOBAL_FILE], cannot process.\n";
return false;
}
PPCommandFile global(_def_scope);
if (!global.read_file(global_filename)) {
cerr << "Error reading global definition file "
<< global_filename << ".\n";
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPMain::get_cwd
// Access: Private, Static
// Description: Calls the system getcwd(), automatically allocating a
// large enough string.
////////////////////////////////////////////////////////////////////
string PPMain::
get_cwd() {
static size_t bufsize = 1024;
static char *buffer = NULL;
if (buffer == (char *)NULL) {
buffer = new char[bufsize];
}
while (getcwd(buffer, bufsize) == (char *)NULL) {
if (errno != ERANGE) {
perror("getcwd");
return string();
}
delete[] buffer;
bufsize = bufsize * 2;
buffer = new char[bufsize];
assert(buffer != (char *)NULL);
}
return string(buffer);
}

View File

@ -32,6 +32,8 @@ public:
private:
bool r_process_all(PPDirectoryTree *dir);
bool p_process(PPDirectoryTree *dir);
bool read_global_file();
static string get_cwd();
PPScope *_global_scope;

View File

@ -5,6 +5,43 @@
#include "ppNamedScopes.h"
#include "ppScope.h"
#include "ppDirectoryTree.h"
#include <assert.h>
#include <algorithm>
// An STL object to sort named scopes in order by dependency and then
// by directory name, used in sort_by_dependency().
class SortScopesByDependencyAndName {
public:
bool operator () (const PPScope *a, const PPScope *b) const {
PPDirectoryTree *da = a->get_directory();
PPDirectoryTree *db = b->get_directory();
// Scopes without associated directories appear first in the list.
bool da_is_null = (da == (PPDirectoryTree *)NULL);
bool db_is_null = (db == (PPDirectoryTree *)NULL);
if (da_is_null != db_is_null) {
return da_is_null > db_is_null;
} else if (da_is_null) {
// If two scopes have no associated directories (!) they are
// considered equivalent.
return false;
} else {
// Otherwise, both scopes have associated directories, and we
// can properly put them in order by dependencies.
assert(da != (PPDirectoryTree *)NULL);
assert(db != (PPDirectoryTree *)NULL);
if (da->get_depends_index() != db->get_depends_index()) {
return da->get_depends_index() < db->get_depends_index();
}
return da->get_dirname() < db->get_dirname();
}
}
};
////////////////////////////////////////////////////////////////////
// Function: PPNamedScopes::Constructor
@ -83,6 +120,18 @@ get_scopes(const string &name, Scopes &scopes) const {
}
}
////////////////////////////////////////////////////////////////////
// Function: PPNamedScopes::sort_by_dependency
// Access: Public, Static
// Description: Sorts the previously-generated list of scopes into
// order such that the later scopes depend on the
// earlier scopes.
////////////////////////////////////////////////////////////////////
void PPNamedScopes::
sort_by_dependency(PPNamedScopes::Scopes &scopes) {
sort(scopes.begin(), scopes.end(), SortScopesByDependencyAndName());
}
////////////////////////////////////////////////////////////////////
// Function: PPNamedScopes::set_current
// Access: Public

View File

@ -29,6 +29,7 @@ public:
PPScope *make_scope(const string &name);
void get_scopes(const string &name, Scopes &scopes) const;
static void sort_by_dependency(Scopes &scopes);
void set_current(const string &dirname);

View File

@ -7,6 +7,8 @@
#include "ppNamedScopes.h"
#include "ppFilenamePattern.h"
#include "ppDirectoryTree.h"
#include "ppSubroutine.h"
#include "ppCommandFile.h"
#include "tokenize.h"
#include "find_searchpath.h"
@ -16,7 +18,7 @@
#include <glob.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h> // for perror().
#include <stdio.h> // for perror() and sprintf().
#include <errno.h>
#include <signal.h>
#include <sys/types.h>
@ -175,6 +177,10 @@ define_map_variable(const string &varname, const string &key_varname,
return;
}
if (key_varname.empty()) {
return;
}
vector<string> names;
tokenize_whitespace(scope_names, names);
@ -214,6 +220,71 @@ define_map_variable(const string &varname, const string &key_varname,
define_variable(varname, repaste(results, " "));
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::add_to_map_variable
// Access: Public
// Description: Adds a new key/scope pair to a previous map variable
// definition.
////////////////////////////////////////////////////////////////////
void PPScope::
add_to_map_variable(const string &varname, const string &key,
PPScope *scope) {
MapVariableDefinition &def = find_map_variable(varname);
if (&def == &_null_map_def) {
cerr << "Warning: undefined map variable: " << varname << "\n";
return;
}
def[key] = scope;
// We need to do all this work to define the traditional expansion.
// Maybe not a great idea.
vector<string> results;
MapVariableDefinition::const_iterator di;
for (di = def.begin(); di != def.end(); ++di) {
results.push_back((*di).first);
}
set_variable(varname, repaste(results, " "));
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::define_formals
// Access: Public
// Description: Supplies values to a slew of variables at once,
// typically to define actual values for a list of
// formal parameters to a user-defined subroutine or
// function.
//
// Formals is a vector of variable names to be defined,
// and actuals is a comma-separated list of expressions
// to be substituted in, one-per-one. The
// subroutine_name is used only for error reporting.
////////////////////////////////////////////////////////////////////
void PPScope::
define_formals(const string &subroutine_name,
const vector<string> &formals, const string &actuals) {
vector<string> actual_words;
tokenize_params(actuals, actual_words, true);
if (actual_words.size() < formals.size()) {
cerr << "Warning: not all parameters defined for " << subroutine_name
<< ": " << actuals << "\n";
} else if (actual_words.size() > formals.size()) {
cerr << "Warning: more parameters defined for " << subroutine_name
<< " than actually exist: " << actuals << "\n";
}
for (int i = 0; i < (int)formals.size(); i++) {
if (i < (int)actual_words.size()) {
define_variable(formals[i], actual_words[i]);
} else {
define_variable(formals[i], string());
}
}
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::get_variable
// Access: Public
@ -222,6 +293,12 @@ define_map_variable(const string &varname, const string &key_varname,
////////////////////////////////////////////////////////////////////
string PPScope::
get_variable(const string &varname) const {
// Is it a user-defined function?
const PPSubroutine *sub = PPSubroutine::get_func(varname);
if (sub != (const PPSubroutine *)NULL) {
return expand_function(varname, sub, string());
}
string result;
if (p_get_variable(varname, result)) {
return result;
@ -256,6 +333,34 @@ expand_variable(const string &varname) const {
return expand_string(get_variable(varname));
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::find_map_variable
// Access: Public
// Description: Looks for the map variable definition in this scope
// or some ancestor scope. Returns the map variable
// definition if it is found, or _null_map_def if it is
// not.
////////////////////////////////////////////////////////////////////
PPScope::MapVariableDefinition &PPScope::
find_map_variable(const string &varname) const {
MapVariableDefinition &def = p_find_map_variable(varname);
if (&def != &_null_map_def) {
return def;
}
// No such map variable. Check the stack.
ScopeStack::reverse_iterator si;
for (si = _scope_stack.rbegin(); si != _scope_stack.rend(); ++si) {
MapVariableDefinition &def = (*si)->p_find_map_variable(varname);
if (&def != &_null_map_def) {
return def;
}
}
// Nada.
return _null_map_def;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::get_directory
// Access: Public
@ -384,66 +489,9 @@ get_bottom_scope() {
return _scope_stack.front();
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::p_set_variable
// Access: Private
// Description: The private implementation of p_set_variable.
// Returns true if the variable's definition is found
// and set, false otherwise.
////////////////////////////////////////////////////////////////////
bool PPScope::
p_set_variable(const string &varname, const string &definition) {
Variables::iterator vi;
vi = _variables.find(varname);
if (vi != _variables.end()) {
(*vi).second = definition;
return true;
}
if (_parent_scope != (PPScope *)NULL) {
return _parent_scope->p_set_variable(varname, definition);
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::p_get_variable
// Access: Private
// Description: The private implementation of get_variable(). This
// checks the local scope only; it does not check the
// stack. It returns true if the variable is defined,
// false otherwise..
////////////////////////////////////////////////////////////////////
bool PPScope::
p_get_variable(const string &varname, string &result) const {
Variables::const_iterator vi;
vi = _variables.find(varname);
if (vi != _variables.end()) {
result = (*vi).second;
return true;
}
if (varname == "RELDIR" &&
_directory != (PPDirectoryTree *)NULL &&
current_output_directory != (PPDirectoryTree *)NULL) {
// $[RELDIR] is a special variable name that evaluates to the
// relative directory of the current scope to the current output
// directory.
result = current_output_directory->get_rel_to(_directory);
return true;
}
if (_parent_scope != (PPScope *)NULL) {
return _parent_scope->p_get_variable(varname, result);
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::tokenize_params
// Access: Private
// Access: Public
// Description: Separates a string into tokens based on comma
// delimiters, e.g. for parameters to a function.
// Nested variable references are skipped correctly,
@ -497,6 +545,75 @@ tokenize_params(const string &str, vector<string> &tokens,
}
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::p_set_variable
// Access: Private
// Description: The private implementation of p_set_variable.
// Returns true if the variable's definition is found
// and set, false otherwise.
////////////////////////////////////////////////////////////////////
bool PPScope::
p_set_variable(const string &varname, const string &definition) {
Variables::iterator vi;
vi = _variables.find(varname);
if (vi != _variables.end()) {
(*vi).second = definition;
return true;
}
if (_parent_scope != (PPScope *)NULL) {
return _parent_scope->p_set_variable(varname, definition);
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::p_get_variable
// Access: Private
// Description: The private implementation of get_variable(). This
// checks the local scope only; it does not check the
// stack. It returns true if the variable is defined,
// false otherwise..
////////////////////////////////////////////////////////////////////
bool PPScope::
p_get_variable(const string &varname, string &result) const {
Variables::const_iterator vi;
vi = _variables.find(varname);
if (vi != _variables.end()) {
result = (*vi).second;
return true;
}
if (varname == "RELDIR" &&
_directory != (PPDirectoryTree *)NULL &&
current_output_directory != (PPDirectoryTree *)NULL) {
// $[RELDIR] is a special variable name that evaluates to the
// relative directory of the current scope to the current output
// directory.
result = current_output_directory->get_rel_to(_directory);
return true;
}
if (varname == "DEPENDS_INDEX" &&
_directory != (PPDirectoryTree *)NULL) {
// $[DEPENDS_INDEX] is another special variable name that
// evaluates to the numeric sorting index assigned to this
// directory based on its dependency relationship with other
// directories. It's useful primarily for debugging.
char buffer[32];
sprintf(buffer, "%d", _directory->get_depends_index());
result = buffer;
return true;
}
if (_parent_scope != (PPScope *)NULL) {
return _parent_scope->p_get_variable(varname, result);
}
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::r_expand_string
// Access: Private
@ -639,18 +756,27 @@ r_expand_variable(const string &str, size_t &vp,
}
string params = varname.substr(p);
// Is it a built-in function?
// Is it a user-defined function?
const PPSubroutine *sub = PPSubroutine::get_func(funcname);
if (sub != (const PPSubroutine *)NULL) {
return expand_function(funcname, sub, params);
}
// Is it a built-in function?
if (funcname == "wildcard") {
return expand_wildcard(params);
} else if (funcname == "isdir") {
return expand_isdir(params);
} else if (funcname == "isfile") {
return expand_isfile(params);
} else if (funcname == "libtest") {
return expand_libtest(params);
} else if (funcname == "bintest") {
return expand_bintest(params);
} else if (funcname == "shell") {
return expand_shell(params);
} else if (funcname == "standardize") {
return expand_standardize(params);
} else if (funcname == "firstword") {
return expand_firstword(params);
} else if (funcname == "patsubst") {
@ -681,8 +807,12 @@ r_expand_variable(const string &str, size_t &vp,
return expand_upcase(params);
} else if (funcname == "downcase") {
return expand_downcase(params);
} else if (funcname == "cdefine") {
return expand_cdefine(params);
} else if (funcname == "closure") {
return expand_closure(params);
} else if (funcname == "unmapped") {
return expand_unmapped(params);
}
// It must be a map variable.
@ -700,6 +830,7 @@ r_expand_variable(const string &str, size_t &vp,
}
// And now expand the variable.
string expansion;
// Check for a special inline patsubst operation, like GNU make:
@ -866,6 +997,39 @@ expand_isdir(const string &params) const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_isfile
// Access: Private
// Description: Expands the "isfile" function variable. This
// returns true if the parameter exists and is a
// regular file, or false otherwise. This actually
// expands the parameter(s) with shell globbing
// characters, similar to the "wildcard" function, and
// looks only at the first expansion.
////////////////////////////////////////////////////////////////////
string PPScope::
expand_isfile(const string &params) const {
vector<string> results;
glob_string(expand_string(params), results);
if (results.empty()) {
// No matching file, too bad.
return string();
}
const string &filename = results[0];
struct stat stbuf;
string result;
if (stat(filename.c_str(), &stbuf) == 0) {
if (S_ISREG(stbuf.st_mode)) {
result = filename;
}
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_libtest
// Access: Private
@ -1109,6 +1273,64 @@ expand_shell(const string &params) const {
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_standardize
// Access: Private
// Description: Expands the "standardize" function variable. This
// converts the filename to standard form by removing
// consecutive repeated slashes and collapsing /../
// where possible.
////////////////////////////////////////////////////////////////////
string PPScope::
expand_standardize(const string &params) const {
string filename = expand_string(params);
if (filename.empty()) {
return string();
}
vector<string> components;
// Pull off the components of the filename one at a time.
bool global = (filename[0] == '/');
size_t p = 0;
while (p < filename.length() && filename[p] == '/') {
p++;
}
while (p < filename.length()) {
size_t slash = filename.find('/', p);
string component = filename.substr(p, slash - p);
if (component == ".") {
// Ignore /./.
} else if (component == ".." && !components.empty() &&
!(components.back() == "..")) {
// Back up.
components.pop_back();
} else {
components.push_back(component);
}
p = slash;
while (p < filename.length() && filename[p] == '/') {
p++;
}
}
// Now reassemble the filename.
string result;
if (global) {
result = "/";
}
if (!components.empty()) {
result += components[0];
for (int i = 1; i < (int)components.size(); i++) {
result += "/" + components[i];
}
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_firstword
// Access: Private
@ -1408,9 +1630,13 @@ expand_unique(const string &params) const {
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_eq
// Function: PPScope::expand_if
// Access: Private
// Description: Expands the "if" function variable.
// Description: Expands the "if" function variable. This evaluates
// the first parameter and returns the second parameter
// if the result is true (i.e. nonempty) and the third
// parameter (if present) if the result is faluse
// (i.e. empty).
////////////////////////////////////////////////////////////////////
string PPScope::
expand_if(const string &params) const {
@ -1424,7 +1650,7 @@ expand_if(const string &params) const {
} else {
return "";
}
} else if (tokens.size() == 2) {
} else if (tokens.size() == 3) {
if (!tokens[0].empty()) {
return tokens[1];
} else {
@ -1515,6 +1741,7 @@ expand_not(const string &params) const {
// Access: Private
// Description: Expands the "or" function variable. This returns
// nonempty if any of its arguments are nonempty.
// Specifically, it returns the first nonempty argument.
////////////////////////////////////////////////////////////////////
string PPScope::
expand_or(const string &params) const {
@ -1525,10 +1752,10 @@ expand_or(const string &params) const {
vector<string>::const_iterator ti;
for (ti = tokens.begin(); ti != tokens.end(); ++ti) {
if (!(*ti).empty()) {
return "1";
return (*ti);
}
}
return "";
return string();
}
////////////////////////////////////////////////////////////////////
@ -1536,6 +1763,7 @@ expand_or(const string &params) const {
// Access: Private
// Description: Expands the "and" function variable. This returns
// nonempty if all of its arguments are nonempty.
// Specifically, it returns the last argument.
////////////////////////////////////////////////////////////////////
string PPScope::
expand_and(const string &params) const {
@ -1546,10 +1774,15 @@ expand_and(const string &params) const {
vector<string>::const_iterator ti;
for (ti = tokens.begin(); ti != tokens.end(); ++ti) {
if ((*ti).empty()) {
return "";
return string();
}
}
return "1";
if (tokens.empty()) {
return "1";
} else {
return tokens.back();
}
}
////////////////////////////////////////////////////////////////////
@ -1582,6 +1815,33 @@ expand_downcase(const string &params) const {
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_cdefine
// Access: Private
// Description: Expands the "cdefine" function variable. This is a
// convenience function to output a C-style #define or
// #undef statement based on the value of the named
// variable. If the named string is a variable whose
// definition is nonempty, this returns "#define varname
// definition". Otherwise, it returns "#undef varname".
// This is particularly useful for building up a
// config.h file.
////////////////////////////////////////////////////////////////////
string PPScope::
expand_cdefine(const string &params) const {
string varname = trim_blanks(params);
string expansion = trim_blanks(expand_variable(varname));
string result;
if (expansion.empty()) {
result = "#undef " + varname;
} else {
result = "#define " + varname + " " + expansion;
}
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_closure
// Access: Private
@ -1596,15 +1856,21 @@ expand_closure(const string &params) const {
vector<string> tokens;
tokenize_params(params, tokens, false);
if (tokens.size() != 2) {
cerr << "closure requires two parameters.\n";
if (tokens.size() != 2 && tokens.size() != 3) {
cerr << "closure requires two or three parameters.\n";
return string();
}
// The first parameter is the map variable name, the second
// parameter is the expression to close.
// parameter is the expression to evaluate, and the third parameter
// (if present) is the expression that leads to the recursive
// evaluation of the map variable.
string varname = expand_string(tokens[0]);
string expression = tokens[1];
string close_on = expression;
if (tokens.size() > 2) {
close_on = tokens[2];
}
const MapVariableDefinition &def = find_map_variable(varname);
if (&def == &_null_map_def) {
@ -1619,16 +1885,21 @@ expand_closure(const string &params) const {
// we also need to keep track of all the partial results we have yet
// to evaluate (hence the vector of strings).
set<string> closure;
vector<string> partial_results;
vector<string> results;
vector<string> next_pass;
partial_results.push_back(expand_string(expression));
// Start off with the expression evaluated within the starting
// scope.
results.push_back(expand_string(expression));
while (!partial_results.empty()) {
next_pass.push_back(expand_string(close_on));
while (!next_pass.empty()) {
// Pull off one of the partial results (it doesn't matter which
// one), and chop it up into its constituent words.
vector<string> pass;
tokenize_whitespace(partial_results.back(), pass);
partial_results.pop_back();
tokenize_whitespace(next_pass.back(), pass);
next_pass.pop_back();
// And then map each of those words into scopes.
vector<string>::const_iterator wi;
@ -1636,30 +1907,121 @@ expand_closure(const string &params) const {
const string &word = (*wi);
bool inserted = closure.insert(word).second;
if (inserted) {
// This is a new word, which presumably maps to a scope. What
// does the expression evaluate to within that scope?
MapVariableDefinition::const_iterator mvi;
mvi = def.find(word);
if (mvi != def.end()) {
PPScope *scope = (*mvi).second;
partial_results.push_back(scope->expand_string(expression));
// This is a new word, which presumably maps to a scope.
MapVariableDefinition::const_iterator di;
di = def.find(word);
if (di != def.end()) {
PPScope *scope = (*di).second;
// Evaluate the expression within this scope.
results.push_back(scope->expand_string(expression));
// What does close_on evaluate to within this scope? That
// points us to the next scope(s).
next_pass.push_back(scope->expand_string(close_on));
}
}
}
}
// Now we have the complete transitive closure of $[mapvar expression].
// Now we have the complete transitive closure of $[mapvar close_on].
string result = repaste(results, " ");
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_unmapped
// Access: Private
// Description: Expands the "closure" function variable. This is a
// special function that returns all the arguments to a
// map variable, unchanged, that did *not* match any of
// the keys in the map.
////////////////////////////////////////////////////////////////////
string PPScope::
expand_unmapped(const string &params) const {
// Split the string up into tokens based on the commas.
vector<string> tokens;
tokenize_params(params, tokens, false);
if (tokens.size() != 2) {
cerr << "unmapped requires two parameters.\n";
return string();
}
// The first parameter is the map variable name, and the second
// parameter is the space-separated list of arguments to the map.
string varname = expand_string(tokens[0]);
vector<string> keys;
tokenize_whitespace(expand_string(tokens[1]), keys);
const MapVariableDefinition &def = find_map_variable(varname);
if (&def == &_null_map_def) {
cerr << "Warning: undefined map variable: " << varname << "\n";
return string();
}
vector<string> results;
set<string>::const_iterator ci;
for (ci = closure.begin(); ci != closure.end(); ++ci) {
results.push_back(*ci);
vector<string>::const_iterator ki;
for (ki = keys.begin(); ki != keys.end(); ++ki) {
MapVariableDefinition::const_iterator di;
di = def.find(*ki);
if (di == def.end()) {
// This key was undefined.
results.push_back(*ki);
}
}
string result = repaste(results, " ");
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_function
// Access: Private
// Description: Expands the user-defined function reference. This
// invokes the nested commands within the function body,
// and returns all the output text as one line. Quite a
// job, really.
////////////////////////////////////////////////////////////////////
string PPScope::
expand_function(const string &funcname,
const PPSubroutine *sub, const string &params) const {
PPScope::push_scope((PPScope *)this);
PPScope nested_scope(_named_scopes);
nested_scope.define_formals(funcname, sub->_formals, params);
// This won't compile on VC++. It has only ostringstream, which is
// functionally equivalent but has a slightly different interface.
ostrstream ostr;
PPCommandFile command(&nested_scope);
command.set_output(&ostr);
command.begin_read();
bool okflag = true;
vector<string>::const_iterator li;
for (li = sub->_lines.begin(); li != sub->_lines.end() && okflag; ++li) {
okflag = command.read_line(*li);
}
if (okflag) {
okflag = command.end_read();
}
PPScope::pop_scope();
// Now get the output. We split it into words and then reconnect
// it, to replace all whitespace with spaces.
ostr << ends;
char *str = ostr.str();
vector<string> results;
tokenize_whitespace(str, results);
string result = repaste(results, " ");
delete[] str;
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::expand_map_variable
// Access: Private
@ -1725,48 +2087,22 @@ expand_map_variable(const string &varname, const string &expression,
return result;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::find_map_variable
// Access: Private
// Description: Looks for the map variable definition in this scope
// or some ancestor scope.
////////////////////////////////////////////////////////////////////
const PPScope::MapVariableDefinition &PPScope::
find_map_variable(const string &varname) const {
const MapVariableDefinition &def = p_find_map_variable(varname);
if (&def != &_null_map_def) {
return def;
}
// No such map variable. Check the stack.
ScopeStack::reverse_iterator si;
for (si = _scope_stack.rbegin(); si != _scope_stack.rend(); ++si) {
const MapVariableDefinition &def = (*si)->p_find_map_variable(varname);
if (&def != &_null_map_def) {
return def;
}
}
// Nada.
return _null_map_def;
}
////////////////////////////////////////////////////////////////////
// Function: PPScope::p_find_map_variable
// Access: Private
// Description: The implementation of find_map_variable() for a
// particular static scope, without checking the stack.
////////////////////////////////////////////////////////////////////
const PPScope::MapVariableDefinition &PPScope::
PPScope::MapVariableDefinition &PPScope::
p_find_map_variable(const string &varname) const {
MapVariables::const_iterator mvi;
mvi = _map_variables.find(varname);
if (mvi != _map_variables.end()) {
return (*mvi).second;
return (MapVariableDefinition &)(*mvi).second;
}
if (_parent_scope != (PPScope *)NULL) {
return _parent_scope->find_map_variable(varname);
return _parent_scope->p_find_map_variable(varname);
}
return _null_map_def;

View File

@ -13,6 +13,7 @@
class PPNamedScopes;
class PPDirectoryTree;
class PPSubroutine;
///////////////////////////////////////////////////////////////////
// Class : PPScope
@ -23,6 +24,8 @@ class PPDirectoryTree;
////////////////////////////////////////////////////////////////////
class PPScope {
public:
typedef map<string, PPScope *> MapVariableDefinition;
PPScope(PPNamedScopes *named_scopes);
PPNamedScopes *get_named_scopes() const;
@ -35,9 +38,14 @@ public:
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);
void add_to_map_variable(const string &varname, const string &key,
PPScope *scope);
void define_formals(const string &subroutine_name,
const vector<string> &formals, const string &actuals);
string get_variable(const string &varname) const;
string expand_variable(const string &varname) const;
MapVariableDefinition &find_map_variable(const string &varname) const;
PPDirectoryTree *get_directory() const;
void set_directory(PPDirectoryTree *directory);
@ -49,6 +57,11 @@ public:
static PPScope *pop_scope();
static PPScope *get_bottom_scope();
void tokenize_params(const string &str, vector<string> &tokens,
bool expand) const;
static MapVariableDefinition _null_map_def;
private:
class ExpandedVariable {
public:
@ -56,14 +69,9 @@ private:
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,
@ -73,9 +81,11 @@ private:
string expand_wildcard(const string &params) const;
string expand_isdir(const string &params) const;
string expand_isfile(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_standardize(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;
@ -91,14 +101,16 @@ private:
string expand_and(const string &params) const;
string expand_upcase(const string &params) const;
string expand_downcase(const string &params) const;
string expand_cdefine(const string &params) const;
string expand_closure(const string &params) const;
string expand_unmapped(const string &params) const;
string expand_function(const string &funcname, const PPSubroutine *sub,
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 &
MapVariableDefinition &
p_find_map_variable(const string &varname) const;
void glob_string(const string &str, vector<string> &results) const;
@ -112,7 +124,6 @@ private:
typedef map<string, MapVariableDefinition> MapVariables;
MapVariables _map_variables;
static MapVariableDefinition _null_map_def;
PPScope *_parent_scope;
typedef vector<PPScope *> ScopeStack;

View File

@ -6,6 +6,7 @@
#include "ppSubroutine.h"
PPSubroutine::Subroutines PPSubroutine::_subroutines;
PPSubroutine::Subroutines PPSubroutine::_functions;
////////////////////////////////////////////////////////////////////
// Function: PPSubroutine::define_sub
@ -46,3 +47,48 @@ get_sub(const string &name) {
return (*si).second;
}
}
////////////////////////////////////////////////////////////////////
// Function: PPSubroutine::define_func
// Access: Public, Static
// Description: Adds a function to the global list with the
// indicated name. This is similar to a subroutine
// except it is to be invoked via a variable reference,
// instead of by a #call function. It cannot be
// shadowed by a local variable; it will always override
// any variable definition.
//
// 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_func(const string &name, PPSubroutine *sub) {
Subroutines::iterator si;
si = _functions.find(name);
if (si == _functions.end()) {
_functions.insert(Subroutines::value_type(name, sub));
} else {
delete (*si).second;
(*si).second = sub;
}
}
////////////////////////////////////////////////////////////////////
// Function: PPSubroutine::get_func
// Access: Public, Static
// Description: Returns the previously-defined function with the
// given name, or NULL if there is no such function
// with that name.
////////////////////////////////////////////////////////////////////
const PPSubroutine *PPSubroutine::
get_func(const string &name) {
Subroutines::const_iterator si;
si = _functions.find(name);
if (si == _functions.end()) {
return NULL;
} else {
return (*si).second;
}
}

View File

@ -20,14 +20,19 @@
////////////////////////////////////////////////////////////////////
class PPSubroutine {
public:
vector<string> _formals;
vector<string> _lines;
public:
static void define_sub(const string &name, PPSubroutine *sub);
static const PPSubroutine *get_sub(const string &name);
static void define_func(const string &name, PPSubroutine *sub);
static const PPSubroutine *get_func(const string &name);
typedef map<string, PPSubroutine *> Subroutines;
static Subroutines _subroutines;
static Subroutines _functions;
};
#endif

View File

@ -14,9 +14,11 @@
#ifdef HAVE_IOSTREAM
#include <iostream>
#include <fstream>
#include <strstream>
#else
#include <iostream.h>
#include <fstream.h>
#include <strstream.h>
#endif
#include <string>