From b376e16a00bf5d403ffadc951a9b2083ed8e0e75 Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 23 Oct 2000 21:34:35 +0000 Subject: [PATCH] *** empty log message *** --- ppremake/configure.in | 2 +- ppremake/ppCommandFile.cxx | 520 +++++++++++++++++++++---------------- ppremake/ppCommandFile.h | 21 +- ppremake/ppScope.cxx | 1 + 4 files changed, 321 insertions(+), 223 deletions(-) diff --git a/ppremake/configure.in b/ppremake/configure.in index 0889e9f05d..f9efac00bd 100644 --- a/ppremake/configure.in +++ b/ppremake/configure.in @@ -1,6 +1,6 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(ppremake.cxx) -AM_INIT_AUTOMAKE(ppremake, 0.51) +AM_INIT_AUTOMAKE(ppremake, 0.52) AM_CONFIG_HEADER(config.h) AC_PREFIX_DEFAULT(/usr/local/panda) diff --git a/ppremake/ppCommandFile.cxx b/ppremake/ppCommandFile.cxx index eba9779194..ab4db687e7 100644 --- a/ppremake/ppCommandFile.cxx +++ b/ppremake/ppCommandFile.cxx @@ -14,9 +14,49 @@ #include #include #include +#include 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 // Access: Public @@ -128,6 +168,58 @@ write_makefile_line(const string &line) { 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 // Access: Public @@ -424,7 +516,7 @@ handle_command(const string &line) { _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 // we can process the command. _got_command = true; @@ -470,29 +562,30 @@ handle_command(const string &line) { } 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(true); } else if (_command == "defun") { return handle_defsub_command(false); + } else if (_command == "output") { + return handle_output_command(); + } else if (_command == "end") { return handle_end_command(); } else if (_in_for) { - // If we're saving up #forscopes commands, we ignore any following - // commands for now. + // If we're currently saving up lines within a block sequence, we + // ignore all commands except for the block-related commands, + // above. return true; + } else if (_command == "format") { + return handle_format_command(); + + } else if (_command == "print") { + return handle_print_command(); + } else if (_command == "include") { return handle_include_command(); @@ -537,10 +630,8 @@ handle_if_command() { // 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. - IfNesting *nest = new IfNesting; - nest->_state = IS_done; - nest->_next = _if_nesting; - _if_nesting = nest; + IfNesting *nest = new IfNesting(IS_done); + nest->push(this); } else { @@ -548,20 +639,19 @@ handle_if_command() { // Otherwise the case is true. However, if we're currently // scanning #forscopes or something, we don't evaluate this at // all, because it doesn't matter. + + bool is_empty = true; if (!_in_for) { _params = _scope->expand_string(_params); + string::const_iterator si; + for (si = _params.begin(); si != _params.end() && is_empty; ++si) { + is_empty = isspace(*si); + } } - bool is_empty = true; - string::const_iterator si; - for (si = _params.begin(); si != _params.end() && is_empty; ++si) { - is_empty = isspace(*si); - } - - IfNesting *nest = new IfNesting; - nest->_state = is_empty ? IS_off : IS_on; - nest->_next = _if_nesting; - _if_nesting = nest; + IfState state = is_empty ? IS_off : IS_on; + IfNesting *nest = new IfNesting(state); + nest->push(this); } return true; @@ -591,14 +681,13 @@ handle_elif_command() { // If the parameter string evaluates to empty, the case is false. // Otherwise the case is true. + bool is_empty = true; if (!_in_for) { _params = _scope->expand_string(_params); - } - - bool is_empty = true; - string::const_iterator si; - for (si = _params.begin(); si != _params.end() && is_empty; ++si) { - 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; @@ -645,7 +734,13 @@ handle_endif_command() { } 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; return true; @@ -661,39 +756,27 @@ handle_endif_command() { //////////////////////////////////////////////////////////////////// bool PPCommandFile:: handle_begin_command() { - BlockNesting *nest = new BlockNesting; - nest->_state = BS_begin; - nest->_name = trim_blanks(_scope->expand_string(_params)); - nest->_write_state = _write_state; - nest->_scope = _scope; - nest->_next = _block_nesting; + string name = trim_blanks(_scope->expand_string(_params)); + BlockNesting *nest = new BlockNesting(BS_begin, name); - if (contains_whitespace(nest->_name)) { - cerr << "Attempt to define scope named \"" << nest->_name + if (contains_whitespace(name)) { + cerr << "Attempt to define scope named \"" << name << "\".\nScope names may not contain whitespace.\n"; return false; } - if (nest->_name.find(SCOPE_DIRNAME_SEPARATOR) != string::npos) { - cerr << "Attempt to define scope named \"" << nest->_name + if (name.find(SCOPE_DIRNAME_SEPARATOR) != string::npos) { + cerr << "Attempt to define scope named \"" << name << "\".\nScope names may not contain the '" << SCOPE_DIRNAME_SEPARATOR << "' character.\n"; return false; } - _block_nesting = nest; + nest->push(this); - if (nest->_name == "global") { - // There's a special case for the named scope "global": this - // refers to the global scope, allowing us to define macros - // 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; - } + PPScope *named_scope = _scope->get_named_scopes()->make_scope(name); + named_scope->set_parent(_scope); + _scope = named_scope; return true; } @@ -708,14 +791,10 @@ handle_begin_command() { //////////////////////////////////////////////////////////////////// bool PPCommandFile:: handle_forscopes_command() { - BlockNesting *nest = new BlockNesting; - nest->_state = _in_for ? BS_nested_forscopes : BS_forscopes; - nest->_name = trim_blanks(_scope->expand_string(_params)); - nest->_write_state = _write_state; - nest->_scope = _scope; - nest->_next = _block_nesting; - - _block_nesting = nest; + BlockState state = _in_for ? BS_nested_forscopes : BS_forscopes; + string name = trim_blanks(_scope->expand_string(_params)); + BlockNesting *nest = new BlockNesting(state, name); + nest->push(this); if (!_in_for) { _in_for = true; @@ -748,18 +827,13 @@ handle_foreach_command() { string variable_name = words.front(); - BlockNesting *nest = new BlockNesting; - nest->_state = _in_for ? BS_nested_foreach : BS_foreach; - nest->_name = variable_name; - nest->_write_state = _write_state; - nest->_scope = _scope; - nest->_next = _block_nesting; + BlockState state = _in_for ? BS_nested_foreach : BS_foreach; + BlockNesting *nest = new BlockNesting(state, variable_name); + nest->push(this); // 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; - if (!_in_for) { _in_for = true; _saved_lines.clear(); @@ -792,17 +866,12 @@ handle_formap_command() { 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; + BlockState state = _in_for ? BS_nested_formap : BS_formap; + BlockNesting *nest = new BlockNesting(state, words[0]); + nest->push(this); nest->_words.push_back(words[1]); - _block_nesting = nest; - if (!_in_for) { _in_for = true; _saved_lines.clear(); @@ -811,127 +880,6 @@ handle_formap_command() { 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 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 // Access: Protected @@ -980,15 +928,11 @@ handle_defsub_command(bool is_defsub) { return false; } - BlockNesting *nest = new BlockNesting; - 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); + BlockState state = is_defsub ? BS_defsub : BS_defun; + BlockNesting *nest = new BlockNesting(state, subroutine_name); - _block_nesting = nest; + nest->push(this); + nest->_words.swap(formals); _in_for = true; _saved_lines.clear(); @@ -996,6 +940,82 @@ handle_defsub_command(bool is_defsub) { 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 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 // Access: Protected @@ -1017,15 +1037,13 @@ handle_end_command() { } BlockNesting *nest = _block_nesting; + nest->pop(this); - _scope = nest->_scope; - if (_write_state != nest->_write_state) { - delete _write_state; - _write_state = nest->_write_state; + if (nest->_if != _if_nesting) { + cerr << "If block not closed within scoping block.\n"; + return false; } - _block_nesting = nest->_next; - if (nest->_state == BS_forscopes) { // Now replay all of the saved lines. _in_for = false; @@ -1091,6 +1109,43 @@ handle_end_command() { 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 // Access: Protected @@ -1418,6 +1473,8 @@ include_file(const string &filename) { //////////////////////////////////////////////////////////////////// bool PPCommandFile:: replay_forscopes(const string &name) { + assert(!_in_for); + bool okflag = true; vector lines; @@ -1442,9 +1499,13 @@ replay_forscopes(const string &name) { named_scopes->get_scopes(*wi, 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; - for (si = scopes.begin(); si != scopes.end(); ++si) { + for (si = scopes.begin(); si != scopes.end() && okflag; ++si) { PPScope::push_scope(_scope); _scope = (*si); @@ -1455,6 +1516,11 @@ replay_forscopes(const string &name) { _scope = PPScope::pop_scope(); } + if (saved_block != _block_nesting || saved_if != _if_nesting) { + cerr << "Misplaced #end or #endif.\n"; + okflag = false; + } + return okflag; } @@ -1466,6 +1532,8 @@ replay_forscopes(const string &name) { //////////////////////////////////////////////////////////////////// bool PPCommandFile:: replay_foreach(const string &varname, const vector &words) { + assert(!_in_for); + bool okflag = true; vector lines; @@ -1477,8 +1545,11 @@ replay_foreach(const string &varname, const vector &words) { lines.pop_back(); // Now traverse through the saved words. + BlockNesting *saved_block = _block_nesting; + IfNesting *saved_if = _if_nesting; + vector::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)); vector::const_iterator li; for (li = lines.begin(); li != lines.end() && okflag; ++li) { @@ -1486,6 +1557,11 @@ replay_foreach(const string &varname, const vector &words) { } } + if (saved_block != _block_nesting || saved_if != _if_nesting) { + cerr << "Misplaced #end or #endif.\n"; + okflag = false; + } + return okflag; } @@ -1497,6 +1573,8 @@ replay_foreach(const string &varname, const vector &words) { //////////////////////////////////////////////////////////////////// bool PPCommandFile:: replay_formap(const string &varname, const string &mapvar) { + assert(!_in_for); + bool okflag = true; vector lines; @@ -1516,6 +1594,9 @@ replay_formap(const string &varname, const string &mapvar) { } // Now traverse through the map definition. + BlockNesting *saved_block = _block_nesting; + IfNesting *saved_if = _if_nesting; + PPScope::MapVariableDefinition::const_iterator di; for (di = def.begin(); di != def.end() && okflag; ++di) { _scope->define_variable(varname, (*di).first); @@ -1531,6 +1612,11 @@ replay_formap(const string &varname, const string &mapvar) { _scope = PPScope::pop_scope(); } + if (saved_block != _block_nesting || saved_if != _if_nesting) { + cerr << "Misplaced #end or #endif.\n"; + okflag = false; + } + return okflag; } diff --git a/ppremake/ppCommandFile.h b/ppremake/ppCommandFile.h index ec547490d6..f7576ac150 100644 --- a/ppremake/ppCommandFile.h +++ b/ppremake/ppCommandFile.h @@ -46,12 +46,12 @@ protected: bool handle_forscopes_command(); bool handle_foreach_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_output_command(); bool handle_end_command(); + bool handle_format_command(); + bool handle_print_command(); bool handle_include_command(); bool handle_sinclude_command(); bool handle_call_command(); @@ -85,8 +85,7 @@ private: }; private: - PPScope *_native_scope; - PPScope *_scope; + class BlockNesting; enum IfState { IS_on, // e.g. a passed #if @@ -97,7 +96,12 @@ private: class IfNesting { public: + IfNesting(IfState state); + void push(PPCommandFile *file); + void pop(PPCommandFile *file); + IfState _state; + BlockNesting *_block; IfNesting *_next; }; @@ -139,8 +143,13 @@ private: class BlockNesting { public: + BlockNesting(BlockState state, const string &name); + void push(PPCommandFile *file); + void pop(PPCommandFile *file); + BlockState _state; string _name; + IfNesting *_if; WriteState *_write_state; PPScope *_scope; string _true_name; @@ -151,6 +160,8 @@ private: BlockNesting *_next; }; + PPScope *_native_scope; + PPScope *_scope; bool _got_command; bool _in_for; IfNesting *_if_nesting; diff --git a/ppremake/ppScope.cxx b/ppremake/ppScope.cxx index b5e4b71a8d..115265c54d 100644 --- a/ppremake/ppScope.cxx +++ b/ppremake/ppScope.cxx @@ -2658,6 +2658,7 @@ expand_function(const string &funcname, if (okflag) { okflag = command.end_read(); } + // We don't do anything with okflag here. What can we do? PPScope::pop_scope();