mirror of
https://github.com/panda3d/panda3d.git
synced 2025-09-28 07:48:37 -04:00
*** empty log message ***
This commit is contained in:
parent
8b678a38a5
commit
b376e16a00
@ -1,6 +1,6 @@
|
|||||||
dnl Process this file with autoconf to produce a configure script.
|
dnl Process this file with autoconf to produce a configure script.
|
||||||
AC_INIT(ppremake.cxx)
|
AC_INIT(ppremake.cxx)
|
||||||
AM_INIT_AUTOMAKE(ppremake, 0.51)
|
AM_INIT_AUTOMAKE(ppremake, 0.52)
|
||||||
AM_CONFIG_HEADER(config.h)
|
AM_CONFIG_HEADER(config.h)
|
||||||
|
|
||||||
AC_PREFIX_DEFAULT(/usr/local/panda)
|
AC_PREFIX_DEFAULT(/usr/local/panda)
|
||||||
|
@ -14,9 +14,49 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <utime.h>
|
#include <utime.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
static const string begin_comment(BEGIN_COMMENT);
|
static const string begin_comment(BEGIN_COMMENT);
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPCommandFile::IfNesting::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PPCommandFile::IfNesting::
|
||||||
|
IfNesting(IfState state) :
|
||||||
|
_state(state)
|
||||||
|
{
|
||||||
|
_block = (PPCommandFile::BlockNesting *)NULL;
|
||||||
|
_next = (PPCommandFile::IfNesting *)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPCommandFile::IfNesting::push
|
||||||
|
// Access: Public
|
||||||
|
// Description: Adds this IfNesting object to the top of the
|
||||||
|
// nesting stack.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PPCommandFile::IfNesting::
|
||||||
|
push(PPCommandFile *file) {
|
||||||
|
_block = file->_block_nesting;
|
||||||
|
_next = file->_if_nesting;
|
||||||
|
file->_if_nesting = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPCommandFile::IfNesting::pop
|
||||||
|
// Access: Public
|
||||||
|
// Description: Removes this IfNesting object from the top of the
|
||||||
|
// nesting stack, and restores the command file's
|
||||||
|
// nesting state.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PPCommandFile::IfNesting::
|
||||||
|
pop(PPCommandFile *file) {
|
||||||
|
assert(file->_if_nesting == this);
|
||||||
|
file->_if_nesting = _next;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PPCommandFile::WriteState::Constructor
|
// Function: PPCommandFile::WriteState::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -128,6 +168,58 @@ write_makefile_line(const string &line) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPCommandFile::BlockNesting::Constructor
|
||||||
|
// Access: Public
|
||||||
|
// Description:
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
PPCommandFile::BlockNesting::
|
||||||
|
BlockNesting(BlockState state, const string &name) :
|
||||||
|
_state(state),
|
||||||
|
_name(name)
|
||||||
|
{
|
||||||
|
_if = (PPCommandFile::IfNesting *)NULL;
|
||||||
|
_write_state = (PPCommandFile::WriteState *)NULL;
|
||||||
|
_scope = (PPScope *)NULL;
|
||||||
|
_tempnam = (char *)NULL;
|
||||||
|
_flags = 0;
|
||||||
|
_next = (PPCommandFile::BlockNesting *)NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPCommandFile::BlockNesting::push
|
||||||
|
// Access: Public
|
||||||
|
// Description: Adds this BlockNesting object to the top of the
|
||||||
|
// nesting stack.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PPCommandFile::BlockNesting::
|
||||||
|
push(PPCommandFile *file) {
|
||||||
|
_if = file->_if_nesting;
|
||||||
|
_write_state = file->_write_state;
|
||||||
|
_scope = file->_scope;
|
||||||
|
_next = file->_block_nesting;
|
||||||
|
file->_block_nesting = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPCommandFile::BlockNesting::pop
|
||||||
|
// Access: Public
|
||||||
|
// Description: Removes this BlockNesting object from the top of the
|
||||||
|
// nesting stack, and restores the command file's
|
||||||
|
// nesting state.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
void PPCommandFile::BlockNesting::
|
||||||
|
pop(PPCommandFile *file) {
|
||||||
|
assert(file->_block_nesting == this);
|
||||||
|
|
||||||
|
if (file->_write_state != _write_state) {
|
||||||
|
delete file->_write_state;
|
||||||
|
file->_write_state = _write_state;
|
||||||
|
}
|
||||||
|
file->_scope = _scope;
|
||||||
|
file->_block_nesting = _next;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PPCommandFile::Constructor
|
// Function: PPCommandFile::Constructor
|
||||||
// Access: Public
|
// Access: Public
|
||||||
@ -424,7 +516,7 @@ handle_command(const string &line) {
|
|||||||
_params = line.substr(p);
|
_params = line.substr(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_params[_params.length() - 1] == '\\') {
|
if (!_params.empty() && _params[_params.length() - 1] == '\\') {
|
||||||
// If the line ends with a backslash, there's more to come before
|
// If the line ends with a backslash, there's more to come before
|
||||||
// we can process the command.
|
// we can process the command.
|
||||||
_got_command = true;
|
_got_command = true;
|
||||||
@ -470,29 +562,30 @@ handle_command(const string &line) {
|
|||||||
} else if (_command == "formap") {
|
} else if (_command == "formap") {
|
||||||
return handle_formap_command();
|
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") {
|
} else if (_command == "defsub") {
|
||||||
return handle_defsub_command(true);
|
return handle_defsub_command(true);
|
||||||
|
|
||||||
} else if (_command == "defun") {
|
} else if (_command == "defun") {
|
||||||
return handle_defsub_command(false);
|
return handle_defsub_command(false);
|
||||||
|
|
||||||
|
} else if (_command == "output") {
|
||||||
|
return handle_output_command();
|
||||||
|
|
||||||
} else if (_command == "end") {
|
} else if (_command == "end") {
|
||||||
return handle_end_command();
|
return handle_end_command();
|
||||||
|
|
||||||
} else if (_in_for) {
|
} else if (_in_for) {
|
||||||
// If we're saving up #forscopes commands, we ignore any following
|
// If we're currently saving up lines within a block sequence, we
|
||||||
// commands for now.
|
// ignore all commands except for the block-related commands,
|
||||||
|
// above.
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
} else if (_command == "format") {
|
||||||
|
return handle_format_command();
|
||||||
|
|
||||||
|
} else if (_command == "print") {
|
||||||
|
return handle_print_command();
|
||||||
|
|
||||||
} else if (_command == "include") {
|
} else if (_command == "include") {
|
||||||
return handle_include_command();
|
return handle_include_command();
|
||||||
|
|
||||||
@ -537,10 +630,8 @@ handle_if_command() {
|
|||||||
// If we're *already* inside a failed if, we don't have to
|
// If we're *already* inside a failed if, we don't have to
|
||||||
// evaluate this one, but we do need to record the nesting level.
|
// evaluate this one, but we do need to record the nesting level.
|
||||||
|
|
||||||
IfNesting *nest = new IfNesting;
|
IfNesting *nest = new IfNesting(IS_done);
|
||||||
nest->_state = IS_done;
|
nest->push(this);
|
||||||
nest->_next = _if_nesting;
|
|
||||||
_if_nesting = nest;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -548,20 +639,19 @@ handle_if_command() {
|
|||||||
// Otherwise the case is true. However, if we're currently
|
// Otherwise the case is true. However, if we're currently
|
||||||
// scanning #forscopes or something, we don't evaluate this at
|
// scanning #forscopes or something, we don't evaluate this at
|
||||||
// all, because it doesn't matter.
|
// all, because it doesn't matter.
|
||||||
if (!_in_for) {
|
|
||||||
_params = _scope->expand_string(_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_empty = true;
|
bool is_empty = true;
|
||||||
string::const_iterator si;
|
if (!_in_for) {
|
||||||
for (si = _params.begin(); si != _params.end() && is_empty; ++si) {
|
_params = _scope->expand_string(_params);
|
||||||
is_empty = isspace(*si);
|
string::const_iterator si;
|
||||||
|
for (si = _params.begin(); si != _params.end() && is_empty; ++si) {
|
||||||
|
is_empty = isspace(*si);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IfNesting *nest = new IfNesting;
|
IfState state = is_empty ? IS_off : IS_on;
|
||||||
nest->_state = is_empty ? IS_off : IS_on;
|
IfNesting *nest = new IfNesting(state);
|
||||||
nest->_next = _if_nesting;
|
nest->push(this);
|
||||||
_if_nesting = nest;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -591,14 +681,13 @@ handle_elif_command() {
|
|||||||
|
|
||||||
// If the parameter string evaluates to empty, the case is false.
|
// If the parameter string evaluates to empty, the case is false.
|
||||||
// Otherwise the case is true.
|
// Otherwise the case is true.
|
||||||
|
bool is_empty = true;
|
||||||
if (!_in_for) {
|
if (!_in_for) {
|
||||||
_params = _scope->expand_string(_params);
|
_params = _scope->expand_string(_params);
|
||||||
}
|
string::const_iterator si;
|
||||||
|
for (si = _params.begin(); si != _params.end() && is_empty; ++si) {
|
||||||
bool is_empty = true;
|
is_empty = isspace(*si);
|
||||||
string::const_iterator si;
|
}
|
||||||
for (si = _params.begin(); si != _params.end() && is_empty; ++si) {
|
|
||||||
is_empty = isspace(*si);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_if_nesting->_state = is_empty ? IS_off : IS_on;
|
_if_nesting->_state = is_empty ? IS_off : IS_on;
|
||||||
@ -645,7 +734,13 @@ handle_endif_command() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
IfNesting *nest = _if_nesting;
|
IfNesting *nest = _if_nesting;
|
||||||
_if_nesting = _if_nesting->_next;
|
nest->pop(this);
|
||||||
|
|
||||||
|
if (nest->_block != _block_nesting) {
|
||||||
|
cerr << "If block not closed within scoping block.\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
delete nest;
|
delete nest;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -661,39 +756,27 @@ handle_endif_command() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool PPCommandFile::
|
bool PPCommandFile::
|
||||||
handle_begin_command() {
|
handle_begin_command() {
|
||||||
BlockNesting *nest = new BlockNesting;
|
string name = trim_blanks(_scope->expand_string(_params));
|
||||||
nest->_state = BS_begin;
|
BlockNesting *nest = new BlockNesting(BS_begin, name);
|
||||||
nest->_name = trim_blanks(_scope->expand_string(_params));
|
|
||||||
nest->_write_state = _write_state;
|
|
||||||
nest->_scope = _scope;
|
|
||||||
nest->_next = _block_nesting;
|
|
||||||
|
|
||||||
if (contains_whitespace(nest->_name)) {
|
if (contains_whitespace(name)) {
|
||||||
cerr << "Attempt to define scope named \"" << nest->_name
|
cerr << "Attempt to define scope named \"" << name
|
||||||
<< "\".\nScope names may not contain whitespace.\n";
|
<< "\".\nScope names may not contain whitespace.\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nest->_name.find(SCOPE_DIRNAME_SEPARATOR) != string::npos) {
|
if (name.find(SCOPE_DIRNAME_SEPARATOR) != string::npos) {
|
||||||
cerr << "Attempt to define scope named \"" << nest->_name
|
cerr << "Attempt to define scope named \"" << name
|
||||||
<< "\".\nScope names may not contain the '"
|
<< "\".\nScope names may not contain the '"
|
||||||
<< SCOPE_DIRNAME_SEPARATOR << "' character.\n";
|
<< SCOPE_DIRNAME_SEPARATOR << "' character.\n";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_block_nesting = nest;
|
nest->push(this);
|
||||||
|
|
||||||
if (nest->_name == "global") {
|
PPScope *named_scope = _scope->get_named_scopes()->make_scope(name);
|
||||||
// There's a special case for the named scope "global": this
|
named_scope->set_parent(_scope);
|
||||||
// refers to the global scope, allowing us to define macros
|
_scope = named_scope;
|
||||||
// etc. that all scopes can see.
|
|
||||||
_scope = PPScope::get_bottom_scope();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
PPScope *named_scope = _scope->get_named_scopes()->make_scope(nest->_name);
|
|
||||||
named_scope->set_parent(_scope);
|
|
||||||
_scope = named_scope;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -708,14 +791,10 @@ handle_begin_command() {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool PPCommandFile::
|
bool PPCommandFile::
|
||||||
handle_forscopes_command() {
|
handle_forscopes_command() {
|
||||||
BlockNesting *nest = new BlockNesting;
|
BlockState state = _in_for ? BS_nested_forscopes : BS_forscopes;
|
||||||
nest->_state = _in_for ? BS_nested_forscopes : BS_forscopes;
|
string name = trim_blanks(_scope->expand_string(_params));
|
||||||
nest->_name = trim_blanks(_scope->expand_string(_params));
|
BlockNesting *nest = new BlockNesting(state, name);
|
||||||
nest->_write_state = _write_state;
|
nest->push(this);
|
||||||
nest->_scope = _scope;
|
|
||||||
nest->_next = _block_nesting;
|
|
||||||
|
|
||||||
_block_nesting = nest;
|
|
||||||
|
|
||||||
if (!_in_for) {
|
if (!_in_for) {
|
||||||
_in_for = true;
|
_in_for = true;
|
||||||
@ -748,18 +827,13 @@ handle_foreach_command() {
|
|||||||
|
|
||||||
string variable_name = words.front();
|
string variable_name = words.front();
|
||||||
|
|
||||||
BlockNesting *nest = new BlockNesting;
|
BlockState state = _in_for ? BS_nested_foreach : BS_foreach;
|
||||||
nest->_state = _in_for ? BS_nested_foreach : BS_foreach;
|
BlockNesting *nest = new BlockNesting(state, variable_name);
|
||||||
nest->_name = variable_name;
|
nest->push(this);
|
||||||
nest->_write_state = _write_state;
|
|
||||||
nest->_scope = _scope;
|
|
||||||
nest->_next = _block_nesting;
|
|
||||||
|
|
||||||
// We insert in all but the first word in the words vector.
|
// We insert in all but the first word in the words vector.
|
||||||
nest->_words.insert(nest->_words.end(), words.begin() + 1, words.end());
|
nest->_words.insert(nest->_words.end(), words.begin() + 1, words.end());
|
||||||
|
|
||||||
_block_nesting = nest;
|
|
||||||
|
|
||||||
if (!_in_for) {
|
if (!_in_for) {
|
||||||
_in_for = true;
|
_in_for = true;
|
||||||
_saved_lines.clear();
|
_saved_lines.clear();
|
||||||
@ -792,17 +866,12 @@ handle_formap_command() {
|
|||||||
|
|
||||||
string variable_name = words.front();
|
string variable_name = words.front();
|
||||||
|
|
||||||
BlockNesting *nest = new BlockNesting;
|
BlockState state = _in_for ? BS_nested_formap : BS_formap;
|
||||||
nest->_state = _in_for ? BS_nested_formap : BS_formap;
|
BlockNesting *nest = new BlockNesting(state, words[0]);
|
||||||
nest->_name = words[0];
|
nest->push(this);
|
||||||
nest->_write_state = _write_state;
|
|
||||||
nest->_scope = _scope;
|
|
||||||
nest->_next = _block_nesting;
|
|
||||||
|
|
||||||
nest->_words.push_back(words[1]);
|
nest->_words.push_back(words[1]);
|
||||||
|
|
||||||
_block_nesting = nest;
|
|
||||||
|
|
||||||
if (!_in_for) {
|
if (!_in_for) {
|
||||||
_in_for = true;
|
_in_for = true;
|
||||||
_saved_lines.clear();
|
_saved_lines.clear();
|
||||||
@ -811,127 +880,6 @@ handle_formap_command() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: PPCommandFile::handle_format_command
|
|
||||||
// Access: Protected
|
|
||||||
// Description: Handles the #format command: change the formatting
|
|
||||||
// mode of lines as they are output.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool PPCommandFile::
|
|
||||||
handle_format_command() {
|
|
||||||
_params = trim_blanks(_scope->expand_string(_params));
|
|
||||||
if (_params == "straight") {
|
|
||||||
_write_state->_format = WF_straight;
|
|
||||||
|
|
||||||
} else if (_params == "collapse") {
|
|
||||||
_write_state->_format = WF_collapse;
|
|
||||||
|
|
||||||
} else if (_params == "makefile") {
|
|
||||||
_write_state->_format = WF_makefile;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
cerr << "Ignoring invalid write format: " << _params << "\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: PPCommandFile::handle_output_command
|
|
||||||
// Access: Protected
|
|
||||||
// Description: Handles the #output command: all text between this
|
|
||||||
// command and the corresponding #end command will be
|
|
||||||
// sent to the indicated output file.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool PPCommandFile::
|
|
||||||
handle_output_command() {
|
|
||||||
vector<string> words;
|
|
||||||
tokenize_whitespace(_scope->expand_string(_params), words);
|
|
||||||
|
|
||||||
if (words.empty()) {
|
|
||||||
cerr << "#output command requires one parameter.\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
BlockNesting *nest = new BlockNesting;
|
|
||||||
nest->_state = BS_output;
|
|
||||||
nest->_name = words[0];
|
|
||||||
nest->_write_state = _write_state;
|
|
||||||
nest->_scope = _scope;
|
|
||||||
nest->_next = _block_nesting;
|
|
||||||
|
|
||||||
// Also check the output flags.
|
|
||||||
nest->_flags = 0;
|
|
||||||
for (int i = 1; i < (int)words.size(); i++) {
|
|
||||||
if (words[i] == "notouch") {
|
|
||||||
nest->_flags |= OF_notouch;
|
|
||||||
} else {
|
|
||||||
cerr << "Invalid output flag: " << words[i] << "\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_block_nesting = nest;
|
|
||||||
|
|
||||||
if (!_in_for) {
|
|
||||||
string filename = nest->_name;
|
|
||||||
if (filename.empty()) {
|
|
||||||
cerr << "Attempt to output to empty filename\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
string prefix = _scope->expand_variable("DIRPREFIX");
|
|
||||||
if (filename[0] != '/') {
|
|
||||||
filename = prefix + filename;
|
|
||||||
}
|
|
||||||
|
|
||||||
nest->_true_name = filename;
|
|
||||||
nest->_tempnam = (char *)NULL;
|
|
||||||
|
|
||||||
if (access(filename.c_str(), F_OK) == 0) {
|
|
||||||
// If the file already exists, create a temporary file first.
|
|
||||||
|
|
||||||
nest->_tempnam = tempnam((prefix + ".").c_str(), "pptmp");
|
|
||||||
assert(nest->_tempnam != (char *)NULL);
|
|
||||||
|
|
||||||
nest->_output.open(nest->_tempnam);
|
|
||||||
if (nest->_output.fail()) {
|
|
||||||
cerr << "Unable to open output file " << nest->_tempnam << "\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
// If the file does not already exist, create it directly instead
|
|
||||||
// of monkeying around with temporary files.
|
|
||||||
cerr << "Generating " << filename << "\n";
|
|
||||||
|
|
||||||
nest->_output.open(filename.c_str(), ios::out, 0666);
|
|
||||||
if (nest->_output.fail()) {
|
|
||||||
cerr << "Unable to open output file " << filename << "\n";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_write_state = new WriteState(*_write_state);
|
|
||||||
_write_state->_out = &nest->_output;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
// Function: PPCommandFile::handle_print_command
|
|
||||||
// Access: Protected
|
|
||||||
// Description: Handles the #print command: immediately output the
|
|
||||||
// arguments to this line to standard error.
|
|
||||||
////////////////////////////////////////////////////////////////////
|
|
||||||
bool PPCommandFile::
|
|
||||||
handle_print_command() {
|
|
||||||
if (!_in_for) {
|
|
||||||
cerr << _scope->expand_string(_params) << "\n";
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PPCommandFile::handle_defsub_command
|
// Function: PPCommandFile::handle_defsub_command
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
@ -980,15 +928,11 @@ handle_defsub_command(bool is_defsub) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockNesting *nest = new BlockNesting;
|
BlockState state = is_defsub ? BS_defsub : BS_defun;
|
||||||
nest->_state = is_defsub ? BS_defsub : BS_defun;
|
BlockNesting *nest = new BlockNesting(state, subroutine_name);
|
||||||
nest->_name = subroutine_name;
|
|
||||||
nest->_write_state = _write_state;
|
|
||||||
nest->_scope = _scope;
|
|
||||||
nest->_next = _block_nesting;
|
|
||||||
nest->_words.swap(formals);
|
|
||||||
|
|
||||||
_block_nesting = nest;
|
nest->push(this);
|
||||||
|
nest->_words.swap(formals);
|
||||||
|
|
||||||
_in_for = true;
|
_in_for = true;
|
||||||
_saved_lines.clear();
|
_saved_lines.clear();
|
||||||
@ -996,6 +940,82 @@ handle_defsub_command(bool is_defsub) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPCommandFile::handle_output_command
|
||||||
|
// Access: Protected
|
||||||
|
// Description: Handles the #output command: all text between this
|
||||||
|
// command and the corresponding #end command will be
|
||||||
|
// sent to the indicated output file.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PPCommandFile::
|
||||||
|
handle_output_command() {
|
||||||
|
vector<string> words;
|
||||||
|
tokenize_whitespace(_scope->expand_string(_params), words);
|
||||||
|
|
||||||
|
if (words.empty()) {
|
||||||
|
cerr << "#output command requires one parameter.\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockNesting *nest = new BlockNesting(BS_output, words[0]);
|
||||||
|
|
||||||
|
// Also check the output flags.
|
||||||
|
for (int i = 1; i < (int)words.size(); i++) {
|
||||||
|
if (words[i] == "notouch") {
|
||||||
|
nest->_flags |= OF_notouch;
|
||||||
|
} else {
|
||||||
|
cerr << "Invalid output flag: " << words[i] << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nest->push(this);
|
||||||
|
|
||||||
|
if (!_in_for) {
|
||||||
|
string filename = nest->_name;
|
||||||
|
if (filename.empty()) {
|
||||||
|
cerr << "Attempt to output to empty filename\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
string prefix = _scope->expand_variable("DIRPREFIX");
|
||||||
|
if (filename[0] != '/') {
|
||||||
|
filename = prefix + filename;
|
||||||
|
}
|
||||||
|
|
||||||
|
nest->_true_name = filename;
|
||||||
|
nest->_tempnam = (char *)NULL;
|
||||||
|
|
||||||
|
if (access(filename.c_str(), F_OK) == 0) {
|
||||||
|
// If the file already exists, create a temporary file first.
|
||||||
|
|
||||||
|
nest->_tempnam = tempnam((prefix + ".").c_str(), "pptmp");
|
||||||
|
assert(nest->_tempnam != (char *)NULL);
|
||||||
|
|
||||||
|
nest->_output.open(nest->_tempnam);
|
||||||
|
if (nest->_output.fail()) {
|
||||||
|
cerr << "Unable to open output file " << nest->_tempnam << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// If the file does not already exist, create it directly instead
|
||||||
|
// of monkeying around with temporary files.
|
||||||
|
cerr << "Generating " << filename << "\n";
|
||||||
|
|
||||||
|
nest->_output.open(filename.c_str(), ios::out, 0666);
|
||||||
|
if (nest->_output.fail()) {
|
||||||
|
cerr << "Unable to open output file " << filename << "\n";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_write_state = new WriteState(*_write_state);
|
||||||
|
_write_state->_out = &nest->_output;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PPCommandFile::handle_end_command
|
// Function: PPCommandFile::handle_end_command
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
@ -1017,15 +1037,13 @@ handle_end_command() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
BlockNesting *nest = _block_nesting;
|
BlockNesting *nest = _block_nesting;
|
||||||
|
nest->pop(this);
|
||||||
|
|
||||||
_scope = nest->_scope;
|
if (nest->_if != _if_nesting) {
|
||||||
if (_write_state != nest->_write_state) {
|
cerr << "If block not closed within scoping block.\n";
|
||||||
delete _write_state;
|
return false;
|
||||||
_write_state = nest->_write_state;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_block_nesting = nest->_next;
|
|
||||||
|
|
||||||
if (nest->_state == BS_forscopes) {
|
if (nest->_state == BS_forscopes) {
|
||||||
// Now replay all of the saved lines.
|
// Now replay all of the saved lines.
|
||||||
_in_for = false;
|
_in_for = false;
|
||||||
@ -1091,6 +1109,43 @@ handle_end_command() {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPCommandFile::handle_format_command
|
||||||
|
// Access: Protected
|
||||||
|
// Description: Handles the #format command: change the formatting
|
||||||
|
// mode of lines as they are output.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PPCommandFile::
|
||||||
|
handle_format_command() {
|
||||||
|
_params = trim_blanks(_scope->expand_string(_params));
|
||||||
|
if (_params == "straight") {
|
||||||
|
_write_state->_format = WF_straight;
|
||||||
|
|
||||||
|
} else if (_params == "collapse") {
|
||||||
|
_write_state->_format = WF_collapse;
|
||||||
|
|
||||||
|
} else if (_params == "makefile") {
|
||||||
|
_write_state->_format = WF_makefile;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
cerr << "Ignoring invalid write format: " << _params << "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
// Function: PPCommandFile::handle_print_command
|
||||||
|
// Access: Protected
|
||||||
|
// Description: Handles the #print command: immediately output the
|
||||||
|
// arguments to this line to standard error.
|
||||||
|
////////////////////////////////////////////////////////////////////
|
||||||
|
bool PPCommandFile::
|
||||||
|
handle_print_command() {
|
||||||
|
cerr << _scope->expand_string(_params) << "\n";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Function: PPCommandFile::handle_include_command
|
// Function: PPCommandFile::handle_include_command
|
||||||
// Access: Protected
|
// Access: Protected
|
||||||
@ -1418,6 +1473,8 @@ include_file(const string &filename) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool PPCommandFile::
|
bool PPCommandFile::
|
||||||
replay_forscopes(const string &name) {
|
replay_forscopes(const string &name) {
|
||||||
|
assert(!_in_for);
|
||||||
|
|
||||||
bool okflag = true;
|
bool okflag = true;
|
||||||
|
|
||||||
vector<string> lines;
|
vector<string> lines;
|
||||||
@ -1443,8 +1500,12 @@ replay_forscopes(const string &name) {
|
|||||||
}
|
}
|
||||||
PPNamedScopes::sort_by_dependency(scopes);
|
PPNamedScopes::sort_by_dependency(scopes);
|
||||||
|
|
||||||
|
// And finally, replay all of the saved lines.
|
||||||
|
BlockNesting *saved_block = _block_nesting;
|
||||||
|
IfNesting *saved_if = _if_nesting;
|
||||||
|
|
||||||
PPNamedScopes::Scopes::const_iterator si;
|
PPNamedScopes::Scopes::const_iterator si;
|
||||||
for (si = scopes.begin(); si != scopes.end(); ++si) {
|
for (si = scopes.begin(); si != scopes.end() && okflag; ++si) {
|
||||||
PPScope::push_scope(_scope);
|
PPScope::push_scope(_scope);
|
||||||
_scope = (*si);
|
_scope = (*si);
|
||||||
|
|
||||||
@ -1455,6 +1516,11 @@ replay_forscopes(const string &name) {
|
|||||||
_scope = PPScope::pop_scope();
|
_scope = PPScope::pop_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (saved_block != _block_nesting || saved_if != _if_nesting) {
|
||||||
|
cerr << "Misplaced #end or #endif.\n";
|
||||||
|
okflag = false;
|
||||||
|
}
|
||||||
|
|
||||||
return okflag;
|
return okflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1466,6 +1532,8 @@ replay_forscopes(const string &name) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool PPCommandFile::
|
bool PPCommandFile::
|
||||||
replay_foreach(const string &varname, const vector<string> &words) {
|
replay_foreach(const string &varname, const vector<string> &words) {
|
||||||
|
assert(!_in_for);
|
||||||
|
|
||||||
bool okflag = true;
|
bool okflag = true;
|
||||||
|
|
||||||
vector<string> lines;
|
vector<string> lines;
|
||||||
@ -1477,8 +1545,11 @@ replay_foreach(const string &varname, const vector<string> &words) {
|
|||||||
lines.pop_back();
|
lines.pop_back();
|
||||||
|
|
||||||
// Now traverse through the saved words.
|
// Now traverse through the saved words.
|
||||||
|
BlockNesting *saved_block = _block_nesting;
|
||||||
|
IfNesting *saved_if = _if_nesting;
|
||||||
|
|
||||||
vector<string>::const_iterator wi;
|
vector<string>::const_iterator wi;
|
||||||
for (wi = words.begin(); wi != words.end(); ++wi) {
|
for (wi = words.begin(); wi != words.end() && okflag; ++wi) {
|
||||||
_scope->define_variable(varname, (*wi));
|
_scope->define_variable(varname, (*wi));
|
||||||
vector<string>::const_iterator li;
|
vector<string>::const_iterator li;
|
||||||
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
|
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
|
||||||
@ -1486,6 +1557,11 @@ replay_foreach(const string &varname, const vector<string> &words) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (saved_block != _block_nesting || saved_if != _if_nesting) {
|
||||||
|
cerr << "Misplaced #end or #endif.\n";
|
||||||
|
okflag = false;
|
||||||
|
}
|
||||||
|
|
||||||
return okflag;
|
return okflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1497,6 +1573,8 @@ replay_foreach(const string &varname, const vector<string> &words) {
|
|||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
bool PPCommandFile::
|
bool PPCommandFile::
|
||||||
replay_formap(const string &varname, const string &mapvar) {
|
replay_formap(const string &varname, const string &mapvar) {
|
||||||
|
assert(!_in_for);
|
||||||
|
|
||||||
bool okflag = true;
|
bool okflag = true;
|
||||||
|
|
||||||
vector<string> lines;
|
vector<string> lines;
|
||||||
@ -1516,6 +1594,9 @@ replay_formap(const string &varname, const string &mapvar) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now traverse through the map definition.
|
// Now traverse through the map definition.
|
||||||
|
BlockNesting *saved_block = _block_nesting;
|
||||||
|
IfNesting *saved_if = _if_nesting;
|
||||||
|
|
||||||
PPScope::MapVariableDefinition::const_iterator di;
|
PPScope::MapVariableDefinition::const_iterator di;
|
||||||
for (di = def.begin(); di != def.end() && okflag; ++di) {
|
for (di = def.begin(); di != def.end() && okflag; ++di) {
|
||||||
_scope->define_variable(varname, (*di).first);
|
_scope->define_variable(varname, (*di).first);
|
||||||
@ -1531,6 +1612,11 @@ replay_formap(const string &varname, const string &mapvar) {
|
|||||||
_scope = PPScope::pop_scope();
|
_scope = PPScope::pop_scope();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (saved_block != _block_nesting || saved_if != _if_nesting) {
|
||||||
|
cerr << "Misplaced #end or #endif.\n";
|
||||||
|
okflag = false;
|
||||||
|
}
|
||||||
|
|
||||||
return okflag;
|
return okflag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,12 +46,12 @@ protected:
|
|||||||
bool handle_forscopes_command();
|
bool handle_forscopes_command();
|
||||||
bool handle_foreach_command();
|
bool handle_foreach_command();
|
||||||
bool handle_formap_command();
|
bool handle_formap_command();
|
||||||
bool handle_format_command();
|
|
||||||
bool handle_output_command();
|
|
||||||
bool handle_print_command();
|
|
||||||
bool handle_defsub_command(bool is_defsub);
|
bool handle_defsub_command(bool is_defsub);
|
||||||
|
bool handle_output_command();
|
||||||
bool handle_end_command();
|
bool handle_end_command();
|
||||||
|
|
||||||
|
bool handle_format_command();
|
||||||
|
bool handle_print_command();
|
||||||
bool handle_include_command();
|
bool handle_include_command();
|
||||||
bool handle_sinclude_command();
|
bool handle_sinclude_command();
|
||||||
bool handle_call_command();
|
bool handle_call_command();
|
||||||
@ -85,8 +85,7 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PPScope *_native_scope;
|
class BlockNesting;
|
||||||
PPScope *_scope;
|
|
||||||
|
|
||||||
enum IfState {
|
enum IfState {
|
||||||
IS_on, // e.g. a passed #if
|
IS_on, // e.g. a passed #if
|
||||||
@ -97,7 +96,12 @@ private:
|
|||||||
|
|
||||||
class IfNesting {
|
class IfNesting {
|
||||||
public:
|
public:
|
||||||
|
IfNesting(IfState state);
|
||||||
|
void push(PPCommandFile *file);
|
||||||
|
void pop(PPCommandFile *file);
|
||||||
|
|
||||||
IfState _state;
|
IfState _state;
|
||||||
|
BlockNesting *_block;
|
||||||
IfNesting *_next;
|
IfNesting *_next;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -139,8 +143,13 @@ private:
|
|||||||
|
|
||||||
class BlockNesting {
|
class BlockNesting {
|
||||||
public:
|
public:
|
||||||
|
BlockNesting(BlockState state, const string &name);
|
||||||
|
void push(PPCommandFile *file);
|
||||||
|
void pop(PPCommandFile *file);
|
||||||
|
|
||||||
BlockState _state;
|
BlockState _state;
|
||||||
string _name;
|
string _name;
|
||||||
|
IfNesting *_if;
|
||||||
WriteState *_write_state;
|
WriteState *_write_state;
|
||||||
PPScope *_scope;
|
PPScope *_scope;
|
||||||
string _true_name;
|
string _true_name;
|
||||||
@ -151,6 +160,8 @@ private:
|
|||||||
BlockNesting *_next;
|
BlockNesting *_next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
PPScope *_native_scope;
|
||||||
|
PPScope *_scope;
|
||||||
bool _got_command;
|
bool _got_command;
|
||||||
bool _in_for;
|
bool _in_for;
|
||||||
IfNesting *_if_nesting;
|
IfNesting *_if_nesting;
|
||||||
|
@ -2658,6 +2658,7 @@ expand_function(const string &funcname,
|
|||||||
if (okflag) {
|
if (okflag) {
|
||||||
okflag = command.end_read();
|
okflag = command.end_read();
|
||||||
}
|
}
|
||||||
|
// We don't do anything with okflag here. What can we do?
|
||||||
|
|
||||||
PPScope::pop_scope();
|
PPScope::pop_scope();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user