add 1.1 elements: #for, #while, #mkdir

This commit is contained in:
David Rose 2002-06-03 17:19:23 +00:00
parent 16a371eecb
commit b7155fcde1
5 changed files with 250 additions and 9 deletions

View File

@ -80,5 +80,5 @@
** Also be sure to change the version number **
** at the beginning of configure.in. **
**************** ****************/
#define VERSION "1.05"
#define VERSION "1.1"
/**************** UPDATE VERSION NUMBER HERE ****************/

View File

@ -5,7 +5,7 @@ dnl **************** UPDATE VERSION NUMBER HERE ****************
dnl ** Also be sure to change the version number **
dnl ** at the end of config_msvc.h. **
dnl **************** ****************
AM_INIT_AUTOMAKE(ppremake, 1.05)
AM_INIT_AUTOMAKE(ppremake, 1.1)
dnl **************** UPDATE VERSION NUMBER HERE ****************
AM_CONFIG_HEADER(config.h)

View File

@ -491,6 +491,11 @@ end_read() {
cerr << "Unclosed begin " << _block_nesting->_name << "\n";
break;
case BS_while:
case BS_nested_while:
cerr << "Unclosed while " << _block_nesting->_name << "\n";
break;
case BS_forscopes:
case BS_nested_forscopes:
cerr << "Unclosed forscopes " << _block_nesting->_name << "\n";
@ -597,6 +602,12 @@ handle_command(const string &line) {
} else if (_command == "begin") {
return handle_begin_command();
} else if (_command == "while") {
return handle_while_command();
} else if (_command == "for") {
return handle_for_command();
} else if (_command == "forscopes") {
return handle_forscopes_command();
@ -645,6 +656,9 @@ handle_command(const string &line) {
} else if (_command == "error") {
return handle_error_command();
} else if (_command == "mkdir") {
return handle_mkdir_command();
} else if (_command == "defer") {
return handle_defer_command();
@ -831,6 +845,70 @@ handle_begin_command() {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_while_command
// Access: Protected
// Description: Handles the #while command: repeat a block of
// commands while a condition is true (nonempty).
// Unlike many of the other block commands, this does
// not begin a new scope.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
handle_while_command() {
BlockState state = _in_for ? BS_nested_while : BS_while;
string name = trim_blanks(_params);
BlockNesting *nest = new BlockNesting(state, name);
nest->push(this);
if (!_in_for) {
_in_for = true;
_saved_lines.clear();
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_for_command
// Access: Protected
// Description: Handles the #for command: repeat a block of
// commands with a loop variable iterating over a range
// of numeric values.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
handle_for_command() {
// We get the name of the variable out first.
size_t p = _scope->scan_to_whitespace(_params);
string name = _params.substr(0, p);
if (name.empty()) {
cerr << "#for without varname\n";
return false;
}
// The rest is the comma-delimited range of values.
vector<string> words;
_scope->tokenize_params(_params.substr(p), words, true);
if (words.size() != 2 && words.size() != 3) {
cerr << "Invalid numeric range: '" << _params.substr(p)
<< "' for #for " << name << "\n";
return false;
}
BlockState state = _in_for ? BS_nested_for : BS_for;
BlockNesting *nest = new BlockNesting(state, name);
nest->push(this);
if (!_in_for) {
_in_for = true;
_saved_lines.clear();
nest->_words.swap(words);
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_forscopes_command
// Access: Protected
@ -1034,12 +1112,12 @@ handle_output_command() {
return false;
}
string prefix = _scope->expand_variable("DIRPREFIX");
if (filename[0] != '/') {
string prefix = _scope->expand_variable("DIRPREFIX");
filename = prefix + filename;
}
nest->_filename = filename;
nest->_params = filename;
// Generate an in-memory copy of the file first.
_write_state = new WriteState(*_write_state);
@ -1083,7 +1161,21 @@ handle_end_command() {
return false;
}
if (nest->_state == BS_forscopes) {
if (nest->_state == BS_while) {
// Now replay all of the saved lines.
_in_for = false;
if (!replay_while(nest->_name)) {
return false;
}
} else if (nest->_state == BS_for) {
// Now replay all of the saved lines.
_in_for = false;
if (!replay_for(nest->_name, nest->_words)) {
return false;
}
} else if (nest->_state == BS_forscopes) {
// Now replay all of the saved lines.
_in_for = false;
if (!replay_forscopes(nest->_name)) {
@ -1126,7 +1218,7 @@ handle_end_command() {
} else if (nest->_state == BS_output) {
if (!_in_for) {
if (!nest->_output) {
cerr << "Error while writing " << nest->_filename << "\n";
cerr << "Error while writing " << nest->_params << "\n";
return false;
}
@ -1135,7 +1227,7 @@ handle_end_command() {
nest->_output << ends;
const char *generated_file = nest->_output.str();
if (!compare_output(generated_file, nest->_filename,
if (!compare_output(generated_file, nest->_params,
(nest->_flags & OF_notouch) != 0)) {
return false;
}
@ -1327,6 +1419,34 @@ handle_error_command() {
return false;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_mkdir_command
// Access: Protected
// Description: Handles the #mkdir command: create a directory or
// directories.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
handle_mkdir_command() {
vector<string> words;
tokenize_whitespace(_scope->expand_string(_params), words);
if (words.empty()) {
cerr << "No directory name specifed to #mkdir.\n";
} else {
vector<string>::const_iterator wi;
for (wi = words.begin(); wi != words.end(); ++wi) {
Filename dirname(*wi, ".");
if (!dirname.make_dir()) {
if (!dirname.is_directory()) {
cerr << "Unable to create directory " << *wi << "\n";
}
}
}
}
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::handle_defer_command
// Access: Protected
@ -1572,6 +1692,118 @@ include_file(Filename filename) {
return true;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::replay_while
// Access: Protected
// Description: Replays all the lines that were saved during a
// previous #while..#end block.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
replay_while(const string &name) {
assert(!_in_for);
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 replay all of the saved lines.
BlockNesting *saved_block = _block_nesting;
IfNesting *saved_if = _if_nesting;
while (!_scope->expand_string(name).empty()) {
vector<string>::const_iterator li;
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
okflag = read_line(*li);
}
}
if (saved_block != _block_nesting || saved_if != _if_nesting) {
cerr << "Misplaced #end or #endif.\n";
okflag = false;
}
return okflag;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::replay_for
// Access: Protected
// Description: Replays all the lines that were saved during a
// previous #for..#end block.
////////////////////////////////////////////////////////////////////
bool PPCommandFile::
replay_for(const string &name, const vector<string> &words) {
assert(!_in_for);
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();
// Expand the variable name.
string varname = _scope->expand_string(name);
// Get out the numeric range.
int range[3] = {0, 0, 1};
assert(words.size() <= 3);
for (int i = 0; i < (int)words.size(); i++) {
const char *param = words[i].c_str();
char *n;
range[i] = strtol(param, &n, 10);
if (n == param) {
cerr << "Invalid integer in #for: " << param << "\n";
return false;
}
}
if (range[2] == 0) {
cerr << "Step by zero in #for " << name << "\n";
return false;
}
// Now replay all of the saved lines.
BlockNesting *saved_block = _block_nesting;
IfNesting *saved_if = _if_nesting;
int index_var;
if (range[2] > 0) {
for (index_var = range[0]; index_var <= range[1]; index_var += range[2]) {
_scope->define_variable(varname, _scope->format_int(index_var));
vector<string>::const_iterator li;
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
okflag = read_line(*li);
}
}
} else {
for (index_var = range[0]; index_var >= range[1]; index_var += range[2]) {
_scope->define_variable(varname, _scope->format_int(index_var));
vector<string>::const_iterator li;
for (li = lines.begin(); li != lines.end() && okflag; ++li) {
okflag = read_line(*li);
}
}
}
_scope->define_variable(varname, _scope->format_int(index_var));
if (saved_block != _block_nesting || saved_if != _if_nesting) {
cerr << "Misplaced #end or #endif.\n";
okflag = false;
}
return okflag;
}
////////////////////////////////////////////////////////////////////
// Function: PPCommandFile::replay_forscopes
// Access: Protected

View File

@ -45,6 +45,8 @@ protected:
bool handle_endif_command();
bool handle_begin_command();
bool handle_while_command();
bool handle_for_command();
bool handle_forscopes_command();
bool handle_foreach_command();
bool handle_formap_command();
@ -59,6 +61,7 @@ protected:
bool handle_sinclude_command();
bool handle_call_command();
bool handle_error_command();
bool handle_mkdir_command();
bool handle_defer_command();
bool handle_define_command();
@ -68,6 +71,8 @@ protected:
bool handle_push_command();
bool include_file(Filename filename);
bool replay_while(const string &name);
bool replay_for(const string &name, const vector<string> &words);
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);
@ -111,6 +116,10 @@ private:
enum BlockState {
BS_begin,
BS_while,
BS_nested_while,
BS_for,
BS_nested_for,
BS_forscopes,
BS_nested_forscopes,
BS_foreach,
@ -157,7 +166,7 @@ private:
IfNesting *_if;
WriteState *_write_state;
PPScope *_scope;
string _filename;
string _params;
ostrstream _output;
vector<string> _words;
int _flags;

View File

@ -2601,7 +2601,7 @@ expand_minus(const string &params) {
int num_words = words.size();
if (num_words == 1) {
// Simular unary minus by setting the first operand to 0.
// Simulate unary minus by setting the first operand to 0.
results[0] = 0.0;
} else if (num_words != 2) {