mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-30 00:32:57 -04:00
*** empty log message ***
This commit is contained in:
parent
c601286b46
commit
97cc7e6be8
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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]
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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 ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) const {
|
||||
@ -1424,7 +1650,7 @@ expand_if(const string ¶ms) 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 ¶ms) 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 ¶ms) const {
|
||||
@ -1525,10 +1752,10 @@ expand_or(const string ¶ms) 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 ¶ms) 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 ¶ms) const {
|
||||
@ -1546,10 +1774,15 @@ expand_and(const string ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) 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 ¶ms) 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;
|
||||
|
@ -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 ¶ms) const;
|
||||
string expand_isdir(const string ¶ms) const;
|
||||
string expand_isfile(const string ¶ms) const;
|
||||
string expand_libtest(const string ¶ms) const;
|
||||
string expand_bintest(const string ¶ms) const;
|
||||
string expand_shell(const string ¶ms) const;
|
||||
string expand_standardize(const string ¶ms) const;
|
||||
string expand_firstword(const string ¶ms) const;
|
||||
string expand_patsubst(const string ¶ms) const;
|
||||
string expand_filter(const string ¶ms) const;
|
||||
@ -91,14 +101,16 @@ private:
|
||||
string expand_and(const string ¶ms) const;
|
||||
string expand_upcase(const string ¶ms) const;
|
||||
string expand_downcase(const string ¶ms) const;
|
||||
string expand_cdefine(const string ¶ms) const;
|
||||
string expand_closure(const string ¶ms) const;
|
||||
string expand_unmapped(const string ¶ms) const;
|
||||
string expand_function(const string &funcname, const PPSubroutine *sub,
|
||||
const string ¶ms) const;
|
||||
string expand_map_variable(const string &varname, const string ¶ms) 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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user