diff --git a/dtool/pptempl/Global.msvc.pp b/dtool/pptempl/Global.msvc.pp index 91f615e485..4ca02150de 100644 --- a/dtool/pptempl/Global.msvc.pp +++ b/dtool/pptempl/Global.msvc.pp @@ -36,36 +36,40 @@ #defun decygwin frompat,topath,path #foreach file $[path] - #if $[eq $[substr 1,1,$[file]],/] - $[patsubst $[frompat],$[topath],$[shell cygpath -w $[file]]] + #if $[isfullpath $[file]] + $[patsubst $[frompat],$[topath],$[cygpath_w $[file]]] #else - $[patsubst $[frompat],$[topath],$[file]] + $[patsubst $[frompat],$[topath],$[osfilename $[file]]] #endif #end file #end decygwin // Define this if we want to make .sbr files. -#defer BROWSEINFO_FLAG -Fr$[target:%.obj=%.sbr] +#defer BROWSEINFO_FLAG /Fr"$[osfilename $[target:%.obj=%.sbr]]" +#defer CFLAGS_SHARED -#defer CFLAGS_OPT1 -MDd -GZ -Zi $[BROWSEINFO_FLAG] -Fd$[target:%.obj=%.pdb] -D_DEBUG -#defer CFLAGS_OPT2 -MDd -Zi -Fd$[target:%.obj=%.pdb] -D_DEBUG -O2 -Ob1 -Ogity -G6 -#defer CFLAGS_OPT3 -MD -DOPTIMIZE -O2 -Ob1 -Ogity -G6 -Gi- -#defer CFLAGS_OPT4 -MD -DOPTIMIZE -DNDEBUG -O2 -Ob1 -Ogity -G6 -Gi- +#defer CFLAGS_OPT1 /MDd /GZ /Zi $[BROWSEINFO_FLAG] /Fd"$[osfilename $[target:%.obj=%.pdb]]" /D_DEBUG +#defer CFLAGS_OPT2 /MDd /Zi /Fd"$[osfilename $[target:%.obj=%.pdb]]" /D_DEBUG /O2 /Ob1 /Ogity /G6 +#defer CFLAGS_OPT3 /MD /DOPTIMIZE /O2 /Ob1 /Ogity /G6 /Gi- +#defer CFLAGS_OPT4 /MD /DOPTIMIZE /DNDEBUG /O2 /Ob1 /Ogity /G6 /Gi- -#defer LFLAGS_OPT1 -debug -incremental:no -#defer LFLAGS_OPT2 -debug -incremental:no -#defer LFLAGS_OPT3 -fixed:no -#defer LFLAGS_OPT4 -fixed:no +#defer LFLAGS_OPT1 /debug /incremental:no +#defer LFLAGS_OPT2 /debug /incremental:no +#defer LFLAGS_OPT3 /fixed:no +#defer LFLAGS_OPT4 /fixed:no -#defer extra_cflags -nologo -W3 -EHsc -Zm250 -D_WINDOWS -DWIN32 -D_WINDLL -DSTRICT -DPENV_WIN32 -DWIN32_VC -#defer extra_so_lflags -DLL -NOLOGO -#defer extra_bin_lflags -NOLOGO +#defer interrogate_ipath $[decygwin %,-I"%",$[target_ipath]] +#defer interrogate_spath $[decygwin %,-S"%",$[install_parser_inc_dir]] -#defer COMPILE_C cl -c -Fo$[target] $[decygwin %,-I"%",$[ipath]] $[flags] $[extra_cflags] $[source] +#defer extra_cflags /nologo /W3 /EHsc /Zm250 /D_WINDOWS /DWIN32 /D_WINDLL /DSTRICT /DPENV_WIN32 /DWIN32_VC +#defer extra_so_lflags /DLL /NOLOGO +#defer extra_bin_lflags /NOLOGO + +#defer COMPILE_C cl /c /Fo"$[osfilename $[target]]" $[decygwin %,/I"%",$[ipath]] $[flags] $[extra_cflags] $[source] #defer COMPILE_C++ $[COMPILE_C] -#defer SHARED_LIB_C link $[LFLAGS_OPT$[OPTIMIZE]] $[extra_so_lflags] $[sources] $[decygwin %,-LIBPATH:"%",$[lpath]] $[patsubst %.lib,%.lib,%,lib%.lib,$[libs]] -OUT:$[target] +#defer SHARED_LIB_C link $[LFLAGS_OPT$[OPTIMIZE]] $[extra_so_lflags] $[sources] $[decygwin %,-LIBPATH:"%",$[lpath]] $[patsubst %.lib,%.lib,%,lib%.lib,$[libs]] /OUT:"$[osfilename $[target]]" #defer SHARED_LIB_C++ $[SHARED_LIB_C] -#defer LINK_BIN_C link $[LFLAGS_OPT$[OPTIMIZE]] $[extra_bin_lflags] $[sources] $[decygwin %,-LIBPATH:"%",$[lpath]] $[patsubst %.lib,%.lib,%,lib%.lib,$[libs]] -OUT:$[target] +#defer LINK_BIN_C link $[LFLAGS_OPT$[OPTIMIZE]] $[extra_bin_lflags] $[sources] $[decygwin %,-LIBPATH:"%",$[lpath]] $[patsubst %.lib,%.lib,%,lib%.lib,$[libs]] /OUT:"$[osfilename $[target]]" #defer LINK_BIN_C++ $[LINK_BIN_C] diff --git a/dtool/pptempl/Global.pp b/dtool/pptempl/Global.pp index f0f342a5cc..879d91f1c4 100644 --- a/dtool/pptempl/Global.pp +++ b/dtool/pptempl/Global.pp @@ -221,6 +221,13 @@ $[if $[and $[run_interrogate],$[IGATESCAN]], \ lib$[TARGET].in] +// This variable returns the name of the interrogate code file +// that will be generated for a particular target, or empty string if +// the target is not to be interrogated. +#defer get_igateoutput \ + $[if $[and $[run_interrogate],$[IGATESCAN]], \ + lib$[TARGET]_igate.cxx] + // This variable returns the name of the interrogate module, if the // current metalib target should include one, or empty string if it // should not. @@ -493,9 +500,11 @@ Warning: Variable $[upcase $[tree]]_INSTALL is not set! // Set up the correct interrogate options. +#defer interrogate_ipath $[target_ipath:%=-I%] +#defer interrogate_spath $[install_parser_inc_dir:%=-S%] #defer interrogate_options \ -DCPPPARSER -D__cplusplus $[SYSTEM_IGATE_FLAGS] \ - -S$[install_parser_inc_dir] $[target_ipath:%=-I%] \ + $[interrogate_spath] $[interrogate_ipath] \ $[filter -D%,$[get_cflags] $[C++FLAGS]] \ $[INTERROGATE_OPTIONS] \ $[if $[INTERROGATE_PYTHON_INTERFACE],-python] \ diff --git a/dtool/pptempl/Template.msvc.pp b/dtool/pptempl/Template.msvc.pp index 09275d74c5..784fdfb250 100644 --- a/dtool/pptempl/Template.msvc.pp +++ b/dtool/pptempl/Template.msvc.pp @@ -42,7 +42,8 @@ #else // This library is on a metalib, so we can't build it, but we // should build all the obj's that go into it. - #set deferred_objs $[deferred_objs] $[patsubst %.c %.cxx %.yxx %.lxx,$[so_dir]/%.obj,%,,$[SOURCES]] + #set deferred_objs $[deferred_objs] \ + $[patsubst %.c %.cxx %.yxx %.lxx,$[so_dir]/%.obj,%,,$[get_sources] $[get_igateoutput]] #endif #end lib_target @@ -145,7 +146,7 @@ #defer lpath $[other_trees:%=%/lib] $[sort $[complete_lpath]] $[get_lpath] // And $[libs] is the set of libraries we will link with. -#defer libs $[unique $[actual_local_libs] $[patsubst %:m,,%:c %,%,$[OTHER_LIBS]] $[get_libs]] +#defer libs $[unique $[actual_local_libs] $[patsubst %:c,,%:m %,%,$[OTHER_LIBS]] $[get_libs]] // Okay, we're ready. Start outputting the Makefile now. #output Makefile @@ -210,8 +211,7 @@ cleanall : clean $[if $[install_config],$[install_config_dir]] \ $[if $[install_igatedb],$[install_igatedb_dir]] \ ] \ - $[TARGET(metalib_target static_lib_target):%=install-lib%] \ - $[real_lib_targets:%=install-lib%] \ + $[TARGET(metalib_target lib_target static_lib_target):%=install-lib%] \ $[TARGET(bin_target):%=install-%] \ $[installed_files] install : all $[install_targets] @@ -253,6 +253,11 @@ $[directory] : #forscopes metalib_target lib_target +// In Windows, we don't actually build all the libraries. In +// particular, we don't build any libraries that are listed on a +// metalib. Is this one such library? +#define build_it $[eq $[module $[TARGET],$[TARGET]],] + // We might need to define a BUILDING_ symbol for win32. We use the // BUILDING_DLL variable name, defined typically in the metalib, for // this; but in some cases, where the library isn't part of a metalib, @@ -266,7 +271,7 @@ $[directory] : // generated .in file that interrogate will produce (and which should // be installed into the /etc directory). #define igatescan $[get_igatescan] -#define igateoutput $[if $[igatescan],lib$[TARGET]_igate.cxx] +#define igateoutput $[get_igateoutput] #define igatedb $[get_igatedb] // If this is a metalib, it may have a number of components that @@ -283,26 +288,30 @@ $[directory] : #define igatemscan $[components $[get_igatedb:%=$[RELDIR]/$[so_dir]/%],$[active_component_libs]] #define igatemout $[if $[igatemscan],lib$[TARGET]_module.cxx] -// Now output the rule to actually link the library from all of its -// various .obj files. -#define sources \ - $[unique $[patsubst %.cxx %.c %.yxx %.lxx,$[so_dir]/%.obj,%,,$[get_sources] $[igateoutput] $[igatemout]]] \ - $[components $[unique $[patsubst %.cxx %.c %.yxx %.lxx,$[RELDIR]/$[so_dir]/%.obj,%,,$[get_sources] $[igateoutput] $[igatemout]]],$[COMPONENT_LIBS]] +#if $[build_it] + // Now output the rule to actually link the library from all of its + // various .obj files. + #define sources \ + $[unique $[patsubst %.cxx %.c %.yxx %.lxx,$[so_dir]/%.obj,%,,$[get_sources] $[igateoutput] $[igatemout]]] \ + $[components $[unique $[patsubst %.cxx %.c %.yxx %.lxx,$[RELDIR]/$[so_dir]/%.obj,%,,$[get_sources] $[get_igateoutput]]],$[active_component_libs]] lib_$[TARGET]_so = $[sources] -#define target $[so_dir]/lib$[TARGET].dll -#define sources $(lib_$[TARGET]_so) + #define target $[so_dir]/lib$[TARGET].dll + #define sources $(lib_$[TARGET]_so) $[target] : $[sources] -#if $[filter %.cxx %.yxx %.lxx,$[get_sources]] + #if $[filter %.cxx %.yxx %.lxx,$[get_sources]] $[SHARED_LIB_C++] -#else + #else $[SHARED_LIB_C] + #endif #endif // Here are the rules to install and uninstall the library and // everything that goes along with it. #define installed_files \ - $[install_lib_dir]/lib$[TARGET].dll \ - $[install_lib_dir]/lib$[TARGET].lib \ + $[if $[build_it], \ + $[install_lib_dir]/lib$[TARGET].dll \ + $[install_lib_dir]/lib$[TARGET].lib \ + ] \ $[INSTALL_SCRIPTS:%=$[install_bin_dir]/%] \ $[INSTALL_HEADERS:%=$[install_headers_dir]/%] \ $[INSTALL_DATA:%=$[install_data_dir]/%] \ @@ -351,7 +360,7 @@ $[so_dir]/$[igatedb] $[so_dir]/$[igateoutput] : $[filter-out .c .cxx,$[igatescan #define target $[igateoutput:%.cxx=$[so_dir]/%.obj] #define source $[so_dir]/$[igateoutput] #define ipath . $[target_ipath] -#define flags $[get_cflags] $[C++FLAGS] $[CFLAGS_OPT$[OPTIMIZE]] $[CFLAGS_SHARED] $[all_sources $[building_var:%=-D%],$[file]] +#define flags $[get_cflags] $[C++FLAGS] $[CFLAGS_OPT$[OPTIMIZE]] $[CFLAGS_SHARED] $[building_var:%=-D%] $[target] : $[source] $[COMPILE_C++] #endif // $[igatescan] @@ -373,7 +382,7 @@ $[target] : $[sources] #define target $[igatemout:%.cxx=$[so_dir]/%.obj] #define source $[so_dir]/$[igatemout] #define ipath . $[target_ipath] -#define flags $[get_cflags] $[C++FLAGS] $[CFLAGS_OPT$[OPTIMIZE]] $[CFLAGS_SHARED] $[all_sources $[building_var:%=-D%],$[file]] +#define flags $[get_cflags] $[C++FLAGS] $[CFLAGS_OPT$[OPTIMIZE]] $[CFLAGS_SHARED] $[building_var:%=-D%] $[target] : $[source] $[COMPILE_C++] #endif // $[igatescan] diff --git a/dtool/pptempl/Template.unix.pp b/dtool/pptempl/Template.unix.pp index 3890ffb368..2bb94b3ada 100644 --- a/dtool/pptempl/Template.unix.pp +++ b/dtool/pptempl/Template.unix.pp @@ -243,7 +243,7 @@ $[directory] : // generated .in file that interrogate will produce (and which should // be installed into the /etc directory). #define igatescan $[get_igatescan] -#define igateoutput $[if $[igatescan],lib$[TARGET]_igate.cxx] +#define igateoutput $[get_igateoutput] #define igatedb $[get_igatedb] // If this is a metalib, it may have a number of components that diff --git a/ppremake/Makefile.am b/ppremake/Makefile.am index c147b4ca43..f1429e9528 100644 --- a/ppremake/Makefile.am +++ b/ppremake/Makefile.am @@ -1,8 +1,8 @@ bin_PROGRAMS = ppremake ppremake_SOURCES = \ - check_include.cxx check_include.h find_searchpath.cxx \ - find_searchpath.h \ + check_include.cxx check_include.h filename.cxx filename.h \ + find_searchpath.cxx find_searchpath.h \ gnu_getopt.c gnu_getopt.h \ ppCommandFile.cxx ppCommandFile.h ppDependableFile.cxx \ ppDependableFile.h ppDirectory.cxx \ diff --git a/ppremake/filename.cxx b/ppremake/filename.cxx new file mode 100644 index 0000000000..ade07ee4ff --- /dev/null +++ b/ppremake/filename.cxx @@ -0,0 +1,78 @@ +// Filename: filename.cxx +// Created by: drose (19Oct00) +// +//////////////////////////////////////////////////////////////////// + +#include "filename.h" +#include + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::is_fullpath +// Description: Returns true if the given pathname appears to be a +// fully-specified pathname. This means it begins with +// a slash for unix_platform, and it begins with a slash +// or backslash, with an optional drive leterr, for +// windows_platform. +//////////////////////////////////////////////////////////////////// +bool +is_fullpath(const string &pathname) { + if (pathname.empty()) { + return false; + } + + if (pathname[0] == '/') { + return true; + } + + if (windows_platform) { + if (pathname.length() > 2 && + isalpha(pathname[0]) && pathname[1] == ':') { + // A drive-letter prefix. + return (pathname[2] == '/' || pathname[2] == '\\'); + } + // No drive-letter prefix. + return (pathname[0] == '\\'); + } + + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::to_os_filename +// Description: Changes forward slashes to backslashes, but only if +// windows_platform is set. Otherwise returns the +// string unchanged. +//////////////////////////////////////////////////////////////////// +string +to_os_filename(string pathname) { + if (windows_platform) { + string::iterator si; + for (si = pathname.begin(); si != pathname.end(); ++si) { + if ((*si) == '/') { + (*si) = '\\'; + } + } + } + + return pathname; +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::to_unix_filename +// Description: Changes backslashes to forward slashes, but only if +// windows_platform is set. Otherwise returns the +// string unchanged. +//////////////////////////////////////////////////////////////////// +string +to_unix_filename(string pathname) { + if (windows_platform) { + string::iterator si; + for (si = pathname.begin(); si != pathname.end(); ++si) { + if ((*si) == '\\') { + (*si) = '/'; + } + } + } + + return pathname; +} diff --git a/ppremake/filename.h b/ppremake/filename.h new file mode 100644 index 0000000000..f6fc2358c8 --- /dev/null +++ b/ppremake/filename.h @@ -0,0 +1,19 @@ +// Filename: filename.h +// Created by: drose (19Oct00) +// +//////////////////////////////////////////////////////////////////// + +#ifndef FILENAME_H +#define FILENAME_H + +#include "ppremake.h" + +// This header file defines a few functions handy for dealing with +// filenames in a cross-platform world. + +bool is_fullpath(const string &pathname); +string to_os_filename(string pathname); +string to_unix_filename(string pathname); + +#endif + diff --git a/ppremake/ppCommandFile.cxx b/ppremake/ppCommandFile.cxx index 8e3bb26f5f..eba9779194 100644 --- a/ppremake/ppCommandFile.cxx +++ b/ppremake/ppCommandFile.cxx @@ -289,6 +289,14 @@ read_line(string line) { // If the comment was at the beginning of the line, ignore the whole // line, including its whitespace. if (comment != 0) { + // We also strip off whitespace at the end of the line, since this + // is generally invisible and almost always just leads to trouble. + size_t eol = line.length(); + while (eol > 0 && (isspace(line[eol - 1]) || line[eol - 1] == '\r')) { + eol--; + } + line = line.substr(0, eol); + if (_in_for) { // Save up the lines for later execution if we're within a #forscopes. _saved_lines.push_back(line); diff --git a/ppremake/ppDirectory.cxx b/ppremake/ppDirectory.cxx index 80b93b2c83..620a9d0085 100644 --- a/ppremake/ppDirectory.cxx +++ b/ppremake/ppDirectory.cxx @@ -346,30 +346,12 @@ report_depends() const { // Get the complete set of directories we depend on. Depends dep; get_complete_i_depend_on(dep); + + cerr << _dirname << " depends directly on the following directories:"; + show_directories(_i_depend_on); - // Copy the set into a vector, so we can sort it into a nice order - // for the user's pleasure. - vector dirs; - copy(dep.begin(), dep.end(), - back_insert_iterator >(dirs)); - - sort(dirs.begin(), dirs.end(), SortDirectoriesByDependencyAndName()); - - cerr << _dirname << " depends on the following directories:"; - static const int max_col = 72; - int col = max_col; - vector::const_iterator di; - for (di = dirs.begin(); di != dirs.end(); ++di) { - const string &dirname = (*di)->_dirname; - col += dirname.length() + 1; - if (col >= max_col) { - col = dirname.length() + 2; - cerr << "\n " << dirname; - } else { - cerr << " " << dirname; - } - } - cerr << "\n"; + cerr << "and directly or indirectly on the following directories:"; + show_directories(dep); } } @@ -389,29 +371,11 @@ report_needs() const { Depends dep; get_complete_depends_on_me(dep); - // Copy the set into a vector, so we can sort it into a nice order - // for the user's pleasure. - vector dirs; - copy(dep.begin(), dep.end(), - back_insert_iterator >(dirs)); - - sort(dirs.begin(), dirs.end(), SortDirectoriesByDependencyAndName()); - - cerr << _dirname << " is needed by the following directories:"; - static const int max_col = 72; - int col = max_col; - vector::const_iterator di; - for (di = dirs.begin(); di != dirs.end(); ++di) { - const string &dirname = (*di)->_dirname; - col += dirname.length() + 1; - if (col >= max_col) { - col = dirname.length() + 2; - cerr << "\n " << dirname; - } else { - cerr << " " << dirname; - } - } - cerr << "\n"; + cerr << _dirname << " is needed directly by the following directories:"; + show_directories(_depends_on_me); + + cerr << "and directly or indirectly by the following directories:"; + show_directories(dep); } } @@ -777,3 +741,35 @@ get_complete_depends_on_me(Depends &dep) const { } } } + +//////////////////////////////////////////////////////////////////// +// Function: PPDirectory::show_directories +// Access: Private +// Description: Writes a set of dependency directory names to +// standard error. The output begins with a newline. +//////////////////////////////////////////////////////////////////// +void PPDirectory:: +show_directories(const PPDirectory::Depends &dep) const { + // Copy the set into a vector, so we can sort it into a nice order + // for the user's pleasure. + vector dirs; + copy(dep.begin(), dep.end(), + back_insert_iterator >(dirs)); + + sort(dirs.begin(), dirs.end(), SortDirectoriesByDependencyAndName()); + + static const int max_col = 72; + int col = max_col; + vector::const_iterator di; + for (di = dirs.begin(); di != dirs.end(); ++di) { + const string &dirname = (*di)->_dirname; + col += dirname.length() + 1; + if (col >= max_col) { + col = dirname.length() + 2; + cerr << "\n " << dirname; + } else { + cerr << " " << dirname; + } + } + cerr << "\n"; +} diff --git a/ppremake/ppDirectory.h b/ppremake/ppDirectory.h index 010834fcc6..cbe8159fb3 100644 --- a/ppremake/ppDirectory.h +++ b/ppremake/ppDirectory.h @@ -67,6 +67,7 @@ private: void get_complete_i_depend_on(Depends &dep) const; void get_complete_depends_on_me(Depends &dep) const; + void show_directories(const Depends &dep) const; string _dirname; PPScope *_scope; diff --git a/ppremake/ppMain.cxx b/ppremake/ppMain.cxx index a4a5fd6a44..35da5f7c53 100644 --- a/ppremake/ppMain.cxx +++ b/ppremake/ppMain.cxx @@ -7,6 +7,7 @@ #include "ppScope.h" #include "ppCommandFile.h" #include "ppDirectory.h" +#include "tokenize.h" #include #include @@ -92,6 +93,15 @@ read_source(const string &root) { return false; } + // Now check the *_PLATFORM variables that System.pp was supposed to + // set. + if (!trim_blanks(_def_scope->expand_string("$[UNIX_PLATFORM]")).empty()) { + unix_platform = true; + } + if (!trim_blanks(_def_scope->expand_string("$[WINDOWS_PLATFORM]")).empty()) { + windows_platform = true; + } + PPScope::push_scope(_def_scope); if (!_tree.scan_source(&_named_scopes)) { diff --git a/ppremake/ppNamedScopes.cxx b/ppremake/ppNamedScopes.cxx index d1d4d52acf..1eedd36b5b 100644 --- a/ppremake/ppNamedScopes.cxx +++ b/ppremake/ppNamedScopes.cxx @@ -153,9 +153,21 @@ void PPNamedScopes:: p_get_scopes(const PPNamedScopes::Named &named, const string &name, Scopes &scopes) const { Named::const_iterator ni; - ni = named.find(name); - if (ni != named.end()) { - const Scopes &s = (*ni).second; - scopes.insert(scopes.end(), s.begin(), s.end()); + if (name == "*") { + // Scope name "*" means all nested scopes in this directory, + // except for the empty-name scope (which is the outer scope). + for (ni = named.begin(); ni != named.end(); ++ni) { + if (!(*ni).first.empty()) { + const Scopes &s = (*ni).second; + scopes.insert(scopes.end(), s.begin(), s.end()); + } + } + + } else { + ni = named.find(name); + if (ni != named.end()) { + const Scopes &s = (*ni).second; + scopes.insert(scopes.end(), s.begin(), s.end()); + } } } diff --git a/ppremake/ppScope.cxx b/ppremake/ppScope.cxx index 3ebe11439c..b5e4b71a8d 100644 --- a/ppremake/ppScope.cxx +++ b/ppremake/ppScope.cxx @@ -12,6 +12,7 @@ #include "ppDependableFile.h" #include "tokenize.h" #include "find_searchpath.h" +#include "filename.h" #include #include @@ -32,6 +33,11 @@ PPScope::MapVariableDefinition PPScope::_null_map_def; PPScope::ScopeStack PPScope::_scope_stack; +#ifdef __CYGWIN__ +extern "C" void cygwin_conv_to_win32_path(const char *path, char *win32); +extern "C" void cygwin_conv_to_posix_path(const char *path, char *posix); +#endif + //////////////////////////////////////////////////////////////////// // Function: PPScope::Constructor // Access: Public @@ -803,7 +809,17 @@ r_expand_variable(const string &str, size_t &vp, } // Is it a built-in function? - if (funcname == "wildcard") { + if (funcname == "isfullpath") { + return expand_isfullpath(params); + } else if (funcname == "osfilename") { + return expand_osfilename(params); + } else if (funcname == "unixfilename") { + return expand_unixfilename(params); + } else if (funcname == "cygpath_w") { + return expand_cygpath_w(params); + } else if (funcname == "cygpath_p") { + return expand_cygpath_p(params); + } else if (funcname == "wildcard") { return expand_wildcard(params); } else if (funcname == "isdir") { return expand_isdir(params); @@ -1020,6 +1036,133 @@ expand_variable_nested(const string &varname, return result; } +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_isfullpath +// Access: Private +// Description: Expands the "isfullpath" function variable. This +// returns true (actually, the same as its input) if the +// input parameter is a fully-specified path name, +// meaning it begins with a slash for unix_platform, and +// it begins with a slash or backslash, with an optional +// drive leterr, for windows_platform. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_isfullpath(const string ¶ms) const { + string filename = trim_blanks(expand_string(params)); + + string result; + if (is_fullpath(filename)) { + result = filename; + } + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_osfilename +// Access: Private +// Description: Expands the "osfilename" function variable. This +// converts the filename from a Unix-style filename +// (e.g. with slash separators) to a platform-specific +// filename. Currently, this only has an effect when +// generating code for a Windows platform: it simply +// converts forward slashes to backslashes. On other +// platforms it has no effect. +// +// This is different from cygpath_w in that (a) it works +// regardless of whether we are actually running under +// Cygwin, and (b) it does nothing more intelligent than +// reverse slashes. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_osfilename(const string ¶ms) const { + // Split the parameter into tokens based on the spaces. + vector words; + tokenize_whitespace(expand_string(params), words); + + vector::iterator wi; + for (wi = words.begin(); wi != words.end(); ++wi) { + (*wi) = to_os_filename(*wi); + } + + string result = repaste(words, " "); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_unixfilename +// Access: Private +// Description: Expands the "unixfilename" function variable. This +// converts the filename from a platform-specific +// filename to a Unix-style filename (e.g. with slash +// separators). Currently, this only has an effect when +// generating code for a Windows platform: it simply +// converts backslashes to forward slashes. On other +// platforms it has no effect. +// +// This is different from cygpath_p in that (a) it works +// regardless of whether we are actually running under +// Cygwin, and (b) it does nothing more intelligent than +// reverse slashes. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_unixfilename(const string ¶ms) const { + // Split the parameter into tokens based on the spaces. + vector words; + tokenize_whitespace(expand_string(params), words); + + vector::iterator wi; + for (wi = words.begin(); wi != words.end(); ++wi) { + (*wi) = to_unix_filename(*wi); + } + + string result = repaste(words, " "); + return result; +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_cygpath_w +// Access: Private +// Description: Expands the "cygpath_w" function variable. This is +// equivalent to $[shell cygpath -w ...] when running +// under Cygwin, and returns the parameter itself when +// not running under Cygwin. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_cygpath_w(const string ¶ms) const { + string filename = trim_blanks(expand_string(params)); + +#ifdef __CYGWIN__ + char result[4096]; + + cygwin_conv_to_win32_path(filename.c_str(), result); + filename = result; +#endif + + return filename; +} + +//////////////////////////////////////////////////////////////////// +// Function: PPScope::expand_cygpath_p +// Access: Private +// Description: Expands the "cygpath_p" function variable. This is +// equivalent to $[shell cygpath -p ...] when running +// under Cygwin, and returns the parameter itself when +// not running under Cygwin. +//////////////////////////////////////////////////////////////////// +string PPScope:: +expand_cygpath_p(const string ¶ms) const { + string filename = trim_blanks(expand_string(params)); + +#ifdef __CYGWIN__ + char result[4096]; + + cygwin_conv_to_posix_path(filename.c_str(), result); + filename = result; +#endif + + return filename; +} + //////////////////////////////////////////////////////////////////// // Function: PPScope::expand_wildcard // Access: Private @@ -1291,6 +1434,7 @@ expand_shell(const string ¶ms) const { if (pid == 0) { // Child. + close(pd[0]); dup2(pd[1], STDOUT_FILENO); char *argv[4]; argv[0] = "sh"; @@ -1355,7 +1499,7 @@ expand_shell(const string ¶ms) const { //////////////////////////////////////////////////////////////////// string PPScope:: expand_standardize(const string ¶ms) const { - string filename = expand_string(params); + string filename = trim_blanks(expand_string(params)); if (filename.empty()) { return string(); } @@ -1411,8 +1555,10 @@ expand_standardize(const string ¶ms) const { //////////////////////////////////////////////////////////////////// string PPScope:: expand_length(const string ¶ms) const { + string word = trim_blanks(expand_string(params)); + char buffer[32]; - sprintf(buffer, "%d", params.length()); + sprintf(buffer, "%d", word.length()); string result = buffer; return result; } @@ -1432,7 +1578,7 @@ expand_substr(const string ¶ms) const { tokenize_params(params, tokens, true); if (tokens.size() != 3) { - cerr << "wordlist requires three parameters.\n"; + cerr << "substr requires three parameters.\n"; return string(); } diff --git a/ppremake/ppScope.h b/ppremake/ppScope.h index 6c29b5679e..03c4048603 100644 --- a/ppremake/ppScope.h +++ b/ppremake/ppScope.h @@ -80,6 +80,11 @@ private: string expand_variable_nested(const string &varname, const string &scope_names) const; + string expand_isfullpath(const string ¶ms) const; + string expand_osfilename(const string ¶ms) const; + string expand_unixfilename(const string ¶ms) const; + string expand_cygpath_w(const string ¶ms) const; + string expand_cygpath_p(const string ¶ms) const; string expand_wildcard(const string ¶ms) const; string expand_isdir(const string ¶ms) const; string expand_isfile(const string ¶ms) const; diff --git a/ppremake/ppremake.cxx b/ppremake/ppremake.cxx index 1269f63679..74a391466c 100644 --- a/ppremake/ppremake.cxx +++ b/ppremake/ppremake.cxx @@ -21,6 +21,9 @@ #include #include +bool unix_platform = false; +bool windows_platform = false; + static void usage() { cerr << @@ -268,13 +271,14 @@ main(int argc, char *argv[]) { } for (int i = 1; i < argc; i++) { + cerr << "\n"; if (report_depends) { ppmain.report_depends(argv[i]); } + cerr << "\n"; if (report_needs) { ppmain.report_needs(argv[i]); } - cerr << "\n"; } } else { diff --git a/ppremake/ppremake.h b/ppremake/ppremake.h index 1a85a03bc5..c87e1024f1 100644 --- a/ppremake/ppremake.h +++ b/ppremake/ppremake.h @@ -49,4 +49,11 @@ using namespace std; #define SCOPE_DIRNAME_WILDCARD "*" #define SCOPE_DIRNAME_CURRENT "." +/* These are set from the similarly-named variables defined in + System.pp. */ +#ifdef __cplusplus +extern bool unix_platform; +extern bool windows_platform; +#endif + #endif